Skip to main content

Overview

AgenticPal uses Google OAuth2 for authentication, allowing the agent to access user’s Google Calendar, Gmail, and Tasks. Sessions are managed with HttpOnly cookies and stored in Redis.

Authentication Flow

1

Initiate OAuth Flow

Client calls GET /auth/google/login to get the authorization URL
2

User Authorization

Redirect user to Google’s authorization page
3

OAuth Callback

Google redirects back to GET /auth/google/callback with authorization code
4

Token Exchange

Backend exchanges code for access/refresh tokens
5

Session Creation

Credentials stored in Redis, session cookie set with HttpOnly flag

OAuth Scopes

The API requests the following Google OAuth scopes:
calendar
scope
https://www.googleapis.com/auth/calendar - Full access to Google Calendar
gmail
scope
https://mail.google.com/ - Full access to Gmail
tasks
scope
https://www.googleapis.com/auth/tasks - Full access to Google Tasks
email
scope
https://www.googleapis.com/auth/userinfo.email - Access user’s email address
openid
scope
openid - OpenID Connect authentication

Endpoints

GET /auth/google/login

Initiate the Google OAuth2 login flow. Query Parameters:
frontend_redirect
string
Optional URL to redirect to after successful authentication. Defaults to FRONTEND_URL environment variable.
Response:
authorization_url
string
The Google OAuth authorization URL to redirect the user to
Example Request:
curl -X GET "http://localhost:8000/auth/google/login?frontend_redirect=http://localhost:3000/dashboard" \
  -H "Accept: application/json"
Example Response:
{
  "authorization_url": "https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=...&redirect_uri=...&scope=...&state=..."
}
Implementation Notes:
  • Sets a session_id HttpOnly cookie
  • Generates a CSRF state token stored in Redis (10-minute TTL)
  • Forces consent prompt to ensure refresh token is granted
  • Session cookie expires in 7 days

GET /auth/google/callback

Handle the OAuth callback from Google.
This endpoint is called by Google’s OAuth service, not directly by clients.
Query Parameters:
code
string
required
Authorization code from Google
state
string
required
CSRF protection state token
error
string
Error code if authorization was denied
Response:
  • Success: 302 Redirect to frontend URL with session cookie
  • Error: 400 Bad Request or 500 Internal Server Error
Error Responses:
// Invalid or expired state
{
  "error": "invalid_state",
  "message": "Invalid or expired OAuth state. Please try logging in again."
}
// Token exchange failed
{
  "error": "token_exchange_error",
  "message": "Failed to exchange authorization code: [details]"
}
Implementation Notes:
  • Validates CSRF state parameter
  • Exchanges authorization code for access and refresh tokens
  • Retrieves user email from Google API
  • Stores credentials in Redis with 7-day TTL
  • Sets HttpOnly session cookie
  • Redirects to frontend URL

GET /auth/session

Get information about the current session. Headers:
Session cookie: session_id=...
Response:
session_id
string
Unique session identifier
user_email
string
User’s Google email address (if authenticated)
authenticated
boolean
Whether the session has valid Google credentials
created_at
string
ISO 8601 timestamp of session creation
Example Request:
curl -X GET "http://localhost:8000/auth/session" \
  -H "Cookie: session_id=abc123..."
Example Response:
{
  "session_id": "abc123...",
  "user_email": "[email protected]",
  "authenticated": true,
  "created_at": "2026-03-08T10:30:00.000Z"
}
Error Response:
// No session cookie
{
  "error": "no_session",
  "message": "No active session"
}
// Session expired
{
  "error": "session_expired",
  "message": "Session has expired. Please log in again."
}
Implementation Notes:
  • Automatically refreshes expired tokens if refresh token is available
  • Updates last_accessed timestamp on each request
  • Extends session TTL on access

POST /auth/refresh

Manually refresh Google OAuth credentials. Headers:
Session cookie: session_id=...
Response:
{
  "message": "Credentials refreshed successfully"
}
Error Responses:
// No refresh token available
{
  "error": "no_refresh_token",
  "message": "No refresh token available. Please log in again."
}
// Refresh failed
{
  "error": "refresh_failed",
  "message": "Failed to refresh credentials: [details]"
}

POST /auth/logout

Log out the current user and clear session. Headers:
Session cookie: session_id=...
Response:
{
  "message": "Successfully logged out"
}
Example Request:
curl -X POST "http://localhost:8000/auth/logout" \
  -H "Cookie: session_id=abc123..."
Implementation Notes:
  • Deletes session from Redis
  • Deletes stored credentials
  • Clears session cookie

Session Management

Session Storage

Sessions are stored in Redis (db=0) with the following structure: Session Data:
{
  "session_id": "unique_session_id",
  "user_email": "[email protected]",
  "created_at": "2026-03-08T10:30:00.000Z",
  "last_accessed": "2026-03-08T12:45:00.000Z",
  "thread_ids": ["thread_1", "thread_2"]
}
Credentials stored separately:
{
  "token": "access_token",
  "refresh_token": "refresh_token",
  "token_uri": "https://oauth2.googleapis.com/token",
  "client_id": "...",
  "client_secret": "...",
  "scopes": ["https://www.googleapis.com/auth/calendar", ...]
}

Session Lifecycle

1

Creation

Session created on first /auth/google/login call or when cookie is missing
2

Authentication

Credentials stored after successful OAuth callback
3

Usage

Session validated on each API request via dependency injection
4

Expiration

Sessions expire after 7 days of inactivity (configurable)
5

Deletion

Explicitly deleted on logout or automatically by Redis TTL
Session cookies are configured as follows:
httponly
boolean
default:true
Prevents JavaScript access (XSS protection)
secure
boolean
Enabled in production (HTTPS only)
samesite
string
default:"lax"
CSRF protection
domain
string
Cookie domain (configurable via COOKIE_DOMAIN)
max_age
integer
default:604800
Cookie expiration in seconds (7 days)

Security Considerations

OAuth state parameter provides CSRF protection during login flow. State tokens are:
  • Randomly generated (cryptographically secure)
  • Stored in Redis with 10-minute TTL
  • Validated on callback
  • Deleted after use
  • Session cookies are HttpOnly (not accessible via JavaScript)
  • Credentials never exposed to frontend
  • All credential operations happen server-side
  • Access tokens automatically refreshed when expired
  • Refresh tokens stored securely in Redis
  • Consent prompt forced to ensure refresh token is granted
  • Sessions use cryptographically random IDs (32-byte URL-safe tokens)
  • Redis persistence with configurable TTL
  • Automatic expiration after inactivity
  • Session secret required in production

Configuration

Required Setup

1

Google Cloud Project

Create a project in Google Cloud Console and enable Calendar, Gmail, and Tasks APIs
2

OAuth Credentials

Create OAuth 2.0 credentials and download credentials.json
3

Environment Variables

Configure OAuth redirect URI and session secret:
GOOGLE_CREDENTIALS_PATH=credentials.json
GOOGLE_REDIRECT_URI=http://localhost:8000/auth/google/callback
SESSION_SECRET=your-secret-key-here
FRONTEND_URL=http://localhost:3000
4

Redis

Ensure Redis is running and accessible

Environment Variables

GOOGLE_CREDENTIALS_PATH
string
default:"credentials.json"
Path to Google OAuth credentials JSON file
GOOGLE_REDIRECT_URI
string
default:"http://localhost:8000/auth/google/callback"
OAuth callback URL (must match Google Cloud Console configuration)
FRONTEND_URL
string
default:"http://localhost:3000"
Frontend application URL for post-authentication redirects
Cookie domain (omit for localhost, set for production domains)
SESSION_SECRET
string
required
Secret key for session signing (generate with openssl rand -hex 32)
SESSION_TTL_SECONDS
integer
default:"604800"
Session expiration time in seconds (default: 7 days)
OAUTH_STATE_TTL_SECONDS
integer
default:"600"
OAuth state token expiration in seconds (default: 10 minutes)
ENVIRONMENT
string
default:"development"
Environment mode: development or production

Example: Complete Authentication Flow

// 1. Start login flow
const loginResponse = await fetch('http://localhost:8000/auth/google/login?frontend_redirect=http://localhost:3000/dashboard');
const { authorization_url } = await loginResponse.json();

// 2. Redirect user to Google
window.location.href = authorization_url;

// 3. After OAuth, user is redirected to /dashboard with session cookie

// 4. Check session status
const sessionResponse = await fetch('http://localhost:8000/auth/session', {
  credentials: 'include' // Include cookies
});
const session = await sessionResponse.json();
console.log(session);
// {
//   "session_id": "...",
//   "user_email": "[email protected]",
//   "authenticated": true,
//   "created_at": "2026-03-08T10:30:00.000Z"
// }

// 5. Make authenticated API calls
const chatResponse = await fetch('http://localhost:8000/chat', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  credentials: 'include', // Include session cookie
  body: JSON.stringify({
    user_message: 'What meetings do I have today?'
  })
});

// 6. Logout when done
await fetch('http://localhost:8000/auth/logout', {
  method: 'POST',
  credentials: 'include'
});

Next Steps

Chat Endpoints

Send messages and interact with the agent

API Overview

Learn about the API architecture

Build docs developers (and LLMs) love