This error occurs when a Firebase session cookie has exceeded its expiration time, requiring the user to re-authenticate. Session cookies can be configured to last between 5 minutes and 2 weeks.
The "auth/session-cookie-expired" error indicates that the Firebase session cookie being verified has passed its expiration time. Firebase Admin SDK allows server-side session management using session cookies as an alternative to ID tokens for traditional web applications that rely on session cookies. Session cookies are created with custom expiration times ranging from 5 minutes to 2 weeks (the maximum allowed). When you attempt to verify an expired session cookie using `verifySessionCookie()`, Firebase rejects it and returns this error. Unlike ID tokens which automatically refresh, session cookies do not have an automatic refresh mechanism and must be manually recreated when they expire. This is a security feature to ensure that user sessions don't persist indefinitely, reducing the risk of session hijacking or unauthorized access from stolen cookies.
Check what expiration duration your session cookies are configured with:
// When creating a session cookie, check the expiresIn value
const expiresIn = 60 * 60 * 24 * 5 * 1000; // 5 days in milliseconds
admin.auth().createSessionCookie(idToken, { expiresIn })
.then((sessionCookie) => {
console.log('Session cookie created with expiration:', expiresIn);
});Verify that the expiration time is appropriate for your use case. If it's too short, users will be logged out frequently.
Add proper error handling when verifying session cookies:
const sessionCookie = req.cookies.session || '';
admin.auth().verifySessionCookie(sessionCookie, true)
.then((decodedClaims) => {
// Session is valid
console.log('User authenticated:', decodedClaims.uid);
})
.catch((error) => {
if (error.code === 'auth/session-cookie-expired') {
// Clear the expired cookie and redirect to login
res.clearCookie('session');
return res.redirect('/login');
}
// Handle other errors
console.error('Session verification error:', error);
});This ensures expired sessions are handled gracefully by prompting re-authentication.
If users are being logged out too frequently, increase the expiration time (up to 2 weeks maximum):
// Example: Set to 14 days (maximum allowed)
const expiresIn = 60 * 60 * 24 * 14 * 1000; // 14 days in milliseconds
admin.auth().createSessionCookie(idToken, { expiresIn })
.then((sessionCookie) => {
// Set the cookie with matching expiration
const options = {
maxAge: expiresIn,
httpOnly: true,
secure: true,
sameSite: 'strict'
};
res.cookie('session', sessionCookie, options);
});Balance security requirements with user experience when choosing the duration.
For applications where users should remain logged in during active use, implement a refresh mechanism:
// Middleware to refresh session cookie before expiration
async function refreshSessionIfNeeded(req, res, next) {
const sessionCookie = req.cookies.session;
try {
const decodedClaims = await admin.auth().verifySessionCookie(sessionCookie);
// Check if cookie is close to expiration (e.g., less than 1 day left)
const expirationTime = decodedClaims.exp * 1000; // Convert to milliseconds
const oneDayFromNow = Date.now() + (24 * 60 * 60 * 1000);
if (expirationTime < oneDayFromNow) {
// Create a new session cookie
const newExpiresIn = 60 * 60 * 24 * 14 * 1000; // 14 days
const newSessionCookie = await admin.auth().createSessionCookie(
await admin.auth().createCustomToken(decodedClaims.uid),
{ expiresIn: newExpiresIn }
);
res.cookie('session', newSessionCookie, {
maxAge: newExpiresIn,
httpOnly: true,
secure: true
});
}
next();
} catch (error) {
res.clearCookie('session');
res.redirect('/login');
}
}Note: This requires generating a custom token from the user ID, which the client then uses to sign in and get a new ID token for creating a fresh session cookie.
Implement client-side logic to detect expired sessions and prompt re-authentication:
// Client-side: Check session validity before critical operations
async function checkSession() {
try {
const response = await fetch('/api/verify-session', {
credentials: 'include'
});
if (!response.ok) {
// Session expired or invalid
window.location.href = '/login?session=expired';
}
} catch (error) {
console.error('Session check failed:', error);
}
}
// Check session periodically (e.g., every 5 minutes)
setInterval(checkSession, 5 * 60 * 1000);This provides a better user experience by proactively detecting expired sessions.
Session Cookie vs. ID Token Strategy: While Firebase ID tokens automatically refresh and are valid for 1 hour, session cookies do not auto-refresh and require manual management. Session cookies are better suited for traditional server-rendered applications, while ID tokens work well for single-page applications (SPAs).
Security Considerations: Shorter session durations improve security by limiting the window of opportunity for session hijacking. However, this must be balanced against user experience. Consider implementing:
- Secure flag (HTTPS only)
- HttpOnly flag (prevent JavaScript access)
- SameSite attribute (CSRF protection)
- Different expiration times for different security contexts (e.g., admin vs. regular users)
Revocation: You can manually revoke session cookies using admin.auth().revokeRefreshTokens(uid) if you suspect token theft or need to force logout. The second parameter in verifySessionCookie(sessionCookie, checkRevoked) when set to true will check if the token has been revoked.
Rolling Sessions Best Practice: The most common approach for rolling sessions is to refresh the session cookie when it's halfway through its lifetime. This minimizes the number of refresh operations while ensuring active users remain authenticated. However, note that creating a new session cookie requires a valid ID token, so you'll need to implement a client-server flow to obtain a fresh ID token.
Time Synchronization: Ensure your server's system time is accurate (use NTP) as significant time drift can cause premature expiration or validation failures. Firebase uses Unix timestamps for expiration validation.
messaging/UNSPECIFIED_ERROR: No additional information available
How to fix "messaging/UNSPECIFIED_ERROR: No additional information available" in Firebase Cloud Messaging
App Check: reCAPTCHA Score Too Low
App Check reCAPTCHA Score Too Low
storage/invalid-url: Invalid URL format for Cloud Storage reference
How to fix invalid URL format in Firebase Cloud Storage
auth/missing-uid: User ID identifier required
How to fix "auth/missing-uid: User ID identifier required" in Firebase
auth/invalid-argument: Invalid parameter passed to method
How to fix "auth/invalid-argument: Invalid parameter passed to method" in Firebase