This error occurs when verifying a Firebase session cookie that has been explicitly revoked or invalidated due to account changes. Fix by clearing the invalid cookie and prompting the user to re-authenticate.
The `auth/session-cookie-revoked` error is thrown by Firebase Admin SDK when attempting to verify a session cookie that has been invalidated. This happens during server-side authentication flows when you call `verifySessionCookie()` with the `checkRevoked: true` option. Firebase can revoke session cookies in several scenarios: when an admin explicitly revokes a user's refresh tokens using the Admin SDK, when critical account changes occur (like password resets or email updates), or when a user account is deleted or disabled. The revocation check requires an additional RPC call to Firebase servers, which adds latency but provides enhanced security by detecting compromised or outdated sessions. This error indicates that while the session cookie itself may be structurally valid and not expired, Firebase has marked it as invalid due to security concerns or account state changes. The cookie should no longer be trusted, and the user must establish a new authenticated session.
Check your error logs to confirm you're receiving the specific Firebase error code:
// Node.js example
try {
const decodedClaims = await admin.auth().verifySessionCookie(
sessionCookie,
true // checkRevoked = true
);
} catch (error) {
if (error.code === 'auth/session-cookie-revoked') {
console.log('Session cookie has been revoked');
// Handle revoked session
}
}If you see this specific error code, the session has been invalidated by Firebase.
Remove the revoked session cookie from the user's browser to prevent repeated verification attempts:
// Express.js example
app.post('/sessionLogout', (req, res) => {
res.clearCookie('session'); // Clear the session cookie
res.json({ message: 'Session cleared' });
});# Python Flask example
from flask import make_response
@app.route('/sessionLogout', methods=['POST'])
def session_logout():
resp = make_response({'message': 'Session cleared'})
resp.set_cookie('session', '', expires=0)
return respMake sure your cookie name matches what you used when creating the session.
Force the user to sign in again to establish a new valid session:
// Client-side redirect
if (error.code === 'auth/session-cookie-revoked') {
// Clear any client-side state
localStorage.removeItem('userSession');
// Redirect to login page
window.location.href = '/login?session_expired=true';
}// Server-side redirect (Express)
res.status(401).json({
error: 'Session revoked',
redirect: '/login?session_expired=true'
});Show a user-friendly message explaining they need to log in again due to security or account changes.
After the user signs in again, create a fresh session cookie:
// Create new session cookie after login
app.post('/sessionLogin', async (req, res) => {
const idToken = req.body.idToken;
const expiresIn = 60 * 60 * 24 * 5 * 1000; // 5 days
try {
const sessionCookie = await admin.auth().createSessionCookie(idToken, { expiresIn });
const options = {
maxAge: expiresIn,
httpOnly: true,
secure: true, // Use in production with HTTPS
sameSite: 'strict'
};
res.cookie('session', sessionCookie, options);
res.json({ status: 'success' });
} catch (error) {
res.status(401).send('Failed to create session cookie');
}
});This establishes a new authenticated session with a valid, non-revoked cookie.
Consider whether you need the checkRevoked option in your verification flow:
// Without revocation check (faster, less secure)
const decodedClaims = await admin.auth().verifySessionCookie(sessionCookie);
// With revocation check (slower, more secure)
const decodedClaims = await admin.auth().verifySessionCookie(
sessionCookie,
true // checkRevoked
);When to use checkRevoked:
- High-security applications (banking, healthcare)
- After password reset or account changes
- When you've explicitly revoked tokens
- Infrequent authentication checks (login, sensitive operations)
When to skip it:
- High-traffic endpoints checked on every request
- Low-risk operations where latency matters
- Applications with short-lived session cookies
The revocation check adds an RPC call to Firebase, increasing latency but providing immediate detection of compromised sessions.
Understanding Token Revocation Timing:
When you call revokeRefreshTokens(uid), Firebase updates the user's tokensValidAfterTime timestamp. Any session cookie or ID token issued before this time will fail the revocation check. This is immediate and doesn't require waiting for token expiration.
Handling Revocation in Multi-Device Scenarios:
If a user changes their password on one device, all other devices will receive auth/session-cookie-revoked errors on their next verification attempt (if using checkRevoked: true). Design your UX to handle this gracefully:
// Graceful multi-device handling
catch (error) {
if (error.code === 'auth/session-cookie-revoked') {
// Log for security monitoring
logger.info('Session revoked', { uid: sessionData.uid, reason: 'possible_password_change' });
// Show friendly message
return res.status(401).json({
code: 'SESSION_REVOKED',
message: 'Your session expired due to recent account changes. Please sign in again.',
requiresReauth: true
});
}
}Performance Optimization:
For high-traffic applications, consider a hybrid approach:
// Check revocation periodically, not on every request
const REVOCATION_CHECK_INTERVAL = 60 * 60 * 1000; // 1 hour
async function verifyWithCaching(sessionCookie, sessionData) {
const lastCheck = sessionData.lastRevocationCheck || 0;
const checkRevoked = (Date.now() - lastCheck) > REVOCATION_CHECK_INTERVAL;
const decoded = await admin.auth().verifySessionCookie(sessionCookie, checkRevoked);
if (checkRevoked) {
// Update cache to indicate revocation was checked
await updateSessionCache(decoded.uid, { lastRevocationCheck: Date.now() });
}
return decoded;
}Security Best Practices:
Always use checkRevoked: true when:
- Processing financial transactions
- Changing account settings
- Accessing sensitive user data
- After detecting suspicious activity
The additional latency (typically 50-200ms) is worthwhile for security-critical operations.
Callable Functions: INTERNAL - Unhandled exception
How to fix "Callable Functions: INTERNAL - Unhandled exception" in Firebase
auth/invalid-hash-algorithm: Hash algorithm doesn't match supported options
How to fix "auth/invalid-hash-algorithm: Hash algorithm doesn't match supported options" in Firebase
Hosting: CORS configuration not set up properly
How to fix CORS configuration in Firebase Hosting
auth/reserved-claims: Custom claims use reserved OIDC claim names
How to fix "reserved claims" error when setting custom claims in Firebase
Callable Functions: UNAUTHENTICATED - Invalid credentials
How to fix "UNAUTHENTICATED - Invalid credentials" in Firebase Callable Functions