6.4 KiB
Logout from All Devices - Implementation Summary
Overview
This document describes the implementation of the "Logout from All Devices" feature, which allows users to immediately invalidate all access and refresh tokens across all devices when a security breach or account compromise is suspected.
Implementation Details
1. Database Schema Changes
Added Column to users table:
token_version(INT, NOT NULL, DEFAULT 1)- Incremented on logout-all-devices to invalidate all existing access tokens
- Validated on each access token verification
Migration Required: For existing databases, run:
ALTER TABLE users ADD COLUMN IF NOT EXISTS token_version INT NOT NULL DEFAULT 1;
2. Token Service Updates
File: src/services/tokenService.js
- Updated
signAccessToken(): Now includestoken_versionclaim in JWT payload - Added
revokeAllUserTokens(userId):- Revokes all refresh tokens for the user
- Marks all devices as inactive
- Increments user's
token_versionto invalidate all access tokens
3. Authentication Middleware Updates
File: src/middleware/authMiddleware.js
- Made middleware async: Required for database query
- Added token version validation:
- Queries user's current
token_versionfrom database - Compares with
token_versionclaim in access token - Rejects token if versions don't match (token has been invalidated)
- Queries user's current
4. New API Endpoint
Endpoint: POST /users/me/logout-all-devices
Security Requirements:
- Requires authentication (access token)
- Requires step-up authentication (recent OTP or
high_assurancetoken) - Rate limited: 10 requests per hour per user
Functionality:
- Revokes all refresh tokens for the user
- Marks all devices as inactive
- Increments user's
token_version(invalidates all access tokens) - Logs HIGH_RISK security event (triggers security alert webhook)
Response:
{
"ok": true,
"message": "Logged out from all devices successfully",
"revoked_tokens_count": 5
}
5. Audit Logging
Event Type: logout_all_devices
Risk Level: HIGH_RISK
Status: success
Metadata:
revoked_tokens_count: Number of refresh tokens revokednew_token_version: New token version after incrementreason: "user_initiated_global_logout"message: "User initiated logout from all devices - security breach suspected"
Alerting: This event triggers security alert webhook (if configured) due to HIGH_RISK level.
How It Works
Access Token Invalidation
-
Token Issuance: When an access token is issued, it includes the user's current
token_versionin the JWT payload. -
Token Validation: On each authenticated request:
authMiddlewareextractstoken_versionfrom the JWT payload- Queries the user's current
token_versionfrom the database - Compares versions - if they don't match, the token is rejected
-
Global Logout: When user calls
/users/me/logout-all-devices:- All refresh tokens are revoked (marked with
revoked_at) - All devices are marked as inactive
- User's
token_versionis incremented - All existing access tokens (even if not expired) become invalid immediately
- All refresh tokens are revoked (marked with
Refresh Token Invalidation
Refresh tokens are stored in the database and can be directly revoked by setting revoked_at. The revokeAllUserTokens() function revokes all refresh tokens for a user.
Security Considerations
-
Step-Up Authentication Required: Users must provide recent OTP verification or have a
high_assurancetoken to perform this action. -
Rate Limiting: Limited to 10 requests per hour per user to prevent abuse.
-
HIGH_RISK Logging: All logout-all-devices events are logged with HIGH_RISK level and trigger security alerts.
-
Immediate Invalidation: Access tokens are invalidated immediately via token versioning, not just on expiry.
-
Database Query Overhead: Token version validation requires a database query on each authenticated request. This is acceptable for security-critical operations.
Testing
Manual Testing
-
Login and get tokens:
POST /auth/verify-otp # Save access_token and refresh_token -
Verify token works:
GET /users/me Authorization: Bearer <access_token> # Should return 200 OK -
Logout from all devices:
POST /users/me/logout-all-devices Authorization: Bearer <access_token> # Requires step-up auth (recent OTP or high_assurance token) -
Verify old token is invalid:
GET /users/me Authorization: Bearer <old_access_token> # Should return 401 Unauthorized -
Verify refresh token is invalid:
POST /auth/refresh { "refresh_token": "<old_refresh_token>" } # Should return 401 Unauthorized
API Integration
Request
POST /users/me/logout-all-devices
Authorization: Bearer <access_token>
Note: The access token must have high_assurance: true or the user must have verified OTP within the last 5 minutes.
Response
Success (200 OK):
{
"ok": true,
"message": "Logged out from all devices successfully",
"revoked_tokens_count": 5
}
Error (403 Forbidden - Step-up required):
{
"error": "step_up_required",
"message": "This action requires additional verification. Please verify your OTP first.",
"requires_otp": true
}
Error (429 Too Many Requests):
{
"error": "Too many requests",
"retry_after": 3600
}
Files Modified
db/farmmarket-db/init.sql- Addedtoken_versioncolumn to users tablesrc/services/tokenService.js- Added token versioning andrevokeAllUserTokens()functionsrc/middleware/authMiddleware.js- Added token version validationsrc/routes/authRoutes.js- Updated user queries to includetoken_versionsrc/routes/userRoutes.js- Added/users/me/logout-all-devicesendpointdocs/ARCHITECTURE.md- Updated documentation with new flow
Future Improvements
-
Caching: Consider caching user's
token_versionin Redis to reduce database queries (with TTL matching access token expiry). -
Metrics: Add metrics for logout-all-devices events to track security incidents.
-
Notification: Optionally notify user via email/SMS when logout-all-devices is triggered.
-
Admin Override: Allow admins to trigger logout-all-devices for a user (with proper audit logging).