Back to Documentation

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.com

3Token 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_SECRET

Secure 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.