Session Management
Endpoints for managing user sessions, logging out, and refreshing access tokens.
Endpoints
| Method | Path | Description |
|---|---|---|
POST |
/api/auth/logout |
Logout and revoke session |
POST |
/api/auth/refresh |
Refresh access token |
POST /api/auth/logout
Logout the current user and revoke their session.
Synopsis
| Property | Value |
|---|---|
| Authentication | Required (JWT) |
| Authorization | Authenticated User |
| Rate Limit | None |
| Idempotent | Yes |
Request Headers
| Header | Value | Required |
|---|---|---|
Authorization |
Bearer {jwt} |
Yes |
Example Request
curl -X POST https://sso.example.com/api/auth/logout \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."
Response (200 OK)
{
"message": "Logged out successfully"
}
Behavior
- Current session is marked as revoked
- Associated refresh token is invalidated
- JWT remains valid until expiration (stateless)
- To enforce immediate logout, services should check
jtiagainst session store
POST /api/auth/refresh
Exchange a valid refresh token for a new access token.
Synopsis
| Property | Value |
|---|---|
| Authentication | None (uses refresh token) |
| Rate Limit | 10 requests/minute |
| Idempotent | No (token rotation) |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
refresh_token |
string |
Yes | Valid refresh token (UUID) |
Example Request
curl -X POST https://sso.example.com/api/auth/refresh \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "550e8400-e29b-41d4-a716-446655440000"
}'
Response (200 OK)
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"refresh_token": "660f9500-e30c-41d5-b827-557766551111",
"token_type": "Bearer",
"expires_in": 86400
}
Response Fields
| Field | Type | Description |
|---|---|---|
access_token |
string |
New JWT access token |
refresh_token |
string |
New refresh token (rotated) |
token_type |
string |
Always "Bearer" |
expires_in |
integer |
Token lifetime in seconds |
Errors
| Status | Code | Condition |
|---|---|---|
401 |
UNAUTHORIZED |
Invalid or expired refresh token |
401 |
SESSION_REVOKED |
Session has been revoked |
Security Notes
- Refresh tokens are rotated on each use
- Old refresh token becomes invalid after rotation
- Storing old token and attempting use will fail
Session Invalidation Events
Sessions are automatically invalidated when:
| Event | Scope | Description |
|---|---|---|
| Password Change | All other sessions | Current session preserved |
| MFA Disable | All sessions | Full re-authentication required |
| Admin Force-Logout | Specific user | All sessions for user |
| Account Suspension | All sessions | Organization suspended |
Token Lifetimes
| Token Type | Lifetime | Configurable |
|---|---|---|
| Access Token | 24 hours | No |
| Refresh Token | 30 days | No |
| Pre-auth Token | 10 minutes | No |
Implementing Token Refresh
Automatic Refresh Pattern
class AuthClient {
constructor(baseUrl) {
this.baseUrl = baseUrl;
this.accessToken = null;
this.refreshToken = null;
}
async fetch(url, options = {}) {
options.headers = {
...options.headers,
'Authorization': `Bearer ${this.accessToken}`
};
let response = await fetch(this.baseUrl + url, options);
if (response.status === 401) {
const error = await response.json();
if (error.error_code === 'TOKEN_EXPIRED') {
await this.refreshTokens();
// Retry with new token
options.headers['Authorization'] = `Bearer ${this.accessToken}`;
response = await fetch(this.baseUrl + url, options);
}
}
return response;
}
async refreshTokens() {
const response = await fetch(this.baseUrl + '/api/auth/refresh', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ refresh_token: this.refreshToken })
});
if (!response.ok) {
// Refresh failed, user must re-authenticate
throw new Error('Session expired');
}
const data = await response.json();
this.accessToken = data.access_token;
this.refreshToken = data.refresh_token;
}
logout() {
return fetch(this.baseUrl + '/api/auth/logout', {
method: 'POST',
headers: { 'Authorization': `Bearer ${this.accessToken}` }
});
}
}
Session Storage Recommendations
| Environment | Access Token | Refresh Token |
|---|---|---|
| Browser SPA | Memory only | httpOnly cookie |
| Mobile App | Secure storage | Secure storage |
| Server-side | Environment/secrets manager | Environment/secrets manager |
Security Best Practices:
- Never store access tokens in localStorage
- Use httpOnly cookies for refresh tokens when possible
- Implement token rotation
- Clear tokens on logout
- Handle refresh failures gracefully