Tokens and Sessions
Understanding OAuth2 tokens, their lifecycle, and session management strategies for secure and efficient authentication.
Token Types
Access Token
A credential used to access protected resources. Access tokens are short-lived (typically 15-60 minutes) and should be sent in the Authorization header of API requests.
Properties:
- • Format: JWT (JSON Web Token)
- • Lifetime: 1 hour (default)
- • Scope: Limited to granted permissions
- • Usage: Bearer token in Authorization header
Refresh Token
A long-lived credential used to obtain new access tokens without requiring the user to re-authenticate. Must include offline_access scope.
Properties:
- • Format: Opaque string (not a JWT)
- • Lifetime: 30 days (or until revoked)
- • Single-use: Rotated on each refresh
- • Storage: Secure, HTTP-only cookies recommended
ID Token (OIDC)
Contains claims about the authentication event and the user. Only issued when using OpenID Connect (with openid scope).
Properties:
- • Format: JWT (JSON Web Token)
- • Lifetime: Same as access token
- • Purpose: User identity verification
- • Not used for API authorization
Token Lifecycle
1Token Issuance
Tokens are issued after successful authentication via the token endpoint:
POST /oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&
code=AUTH_CODE&
redirect_uri=https://yourapp.com/callback&
client_id=YOUR_CLIENT_ID&
code_verifier=CODE_VERIFIER
Response:
{
"access_token": "eyJhbGciOi...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "eyJhbGciOi...",
"id_token": "eyJhbGciOi..." // if openid scope
}2Token Usage
Use the access token in the Authorization header for API requests:
GET /api/users/me
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Host: api.oauth42.com3Token Refresh
When the access token expires, use the refresh token to get a new one:
POST /oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token&
refresh_token=REFRESH_TOKEN&
client_id=YOUR_CLIENT_ID&
client_secret=YOUR_CLIENT_SECRET
Response:
{
"access_token": "new_access_token...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "new_refresh_token..." // rotated
}Refresh Token Rotation (Enhanced Security)
OAuth42 automatically rotates refresh tokens on each use, immediately invalidating the old token. This limits the window of opportunity if a token is compromised—unlike providers like Google, Azure AD, or Okta (with rotation disabled), where a stolen refresh token remains valid until expiration.
Always store and use the new refresh token from each response.
4Token Revocation
Revoke tokens when the user logs out or when security is compromised:
POST /oauth/revoke
Content-Type: application/x-www-form-urlencoded
token=REFRESH_TOKEN&
token_type_hint=refresh_token&
client_id=YOUR_CLIENT_ID&
client_secret=YOUR_CLIENT_SECRETSecure Token Storage
✓ Recommended: HTTP-Only Cookies
Store refresh tokens in secure, HTTP-only cookies with SameSite=Strict:
// Server-side: Set cookie after token exchange
response.cookie('refresh_token', tokens.refresh_token, {
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days
path: '/api/refresh'
});Benefits: Protected from XSS attacks, not accessible to JavaScript
⚠ Acceptable: Server-Side Session
Store tokens in server-side sessions with a session ID in a cookie:
// Store in session
req.session.tokens = {
access_token: tokens.access_token,
refresh_token: tokens.refresh_token,
expires_at: Date.now() + tokens.expires_in * 1000
};Trade-offs: Requires server-side state, scales differently
✗ Not Recommended: LocalStorage or JavaScript-Accessible Cookies
Storing tokens in localStorage or cookies accessible to JavaScript exposes them to XSS attacks:
Security Risk
Any JavaScript running on your page (including third-party scripts) can access these tokens. Use HTTP-only cookies or server-side sessions instead.
Session Management
Device Tracking
OAuth42 tracks active sessions per device and provides device management capabilities:
- View all active sessions for a user
- See device information (browser, OS, location)
- Revoke individual sessions
- Enforce concurrent session limits
Session Revocation
Revoke all sessions for a user (e.g., after password change):
DELETE /api/users/:id/sessions
Authorization: Bearer ACCESS_TOKEN
Response:
{
"revoked": 3,
"message": "All sessions revoked"
}Activity Monitoring
Track and log session activity for security auditing:
- Last active timestamp
- IP address and location
- Login/logout events
- Suspicious activity detection
Best Practices
Implement Token Refresh Proactively
Refresh access tokens before they expire (e.g., 5 minutes before expiration) to avoid API errors and provide a seamless user experience.
Handle Token Expiration Gracefully
Catch 401 Unauthorized errors, refresh the token, and retry the request. Most SDKs handle this automatically.
Revoke on Logout
Always revoke refresh tokens when users explicitly log out. This prevents token reuse and improves security.
Monitor Token Usage
Track token issuance, refresh, and revocation events. Alert on suspicious patterns like rapid token refreshes or refresh from multiple IPs.
Use Short-Lived Access Tokens
Keep access token lifetimes short (15-60 minutes). This limits the impact of token theft since they expire quickly. Use refresh tokens for long-lived sessions.