This document describes the secure cookie-based session management system implemented for CommitLabs. The system uses JWT tokens delivered via HTTP-only cookies with CSRF protection for web-based authentication.
- Authentication Request: Client sends Stellar signature verification request to
/api/auth/verify - Signature Verification: Server validates the signature and nonce
- Session Creation: Server generates JWT session token with embedded CSRF token
- Cookie Setting: Server sets secure HTTP-only session cookie and non-HttpOnly CSRF cookie
- Authenticated Requests: Client includes session cookie automatically and CSRF token in headers for state-changing requests
- Session Validation: Server validates JWT and CSRF token for protected routes
- Session Termination: Client can logout via
/api/auth/logoutto revoke session
- Algorithm: HS256 with server-side secret
- Expiry: 24 hours
- Payload: User address, issued timestamp, expiry timestamp, CSRF token
- Revocation: In-memory revocation list (TODO: Redis/database for production)
- Session Cookie: HTTP-only, Secure (production), SameSite=Strict, 24-hour expiry
- CSRF Cookie: Non-HttpOnly, Secure (production), SameSite=Strict, 24-hour expiry
- Path:
/(site-wide availability)
- Synchronizer Token Pattern: CSRF token embedded in JWT and mirrored in header
- Double-Submit Cookie Pattern: CSRF token available in non-HttpOnly cookie
- Origin Validation: Additional defense-in-depth with Origin/Referer header checks
Creates JWT session token with embedded CSRF token for authenticated user.
const { token, csrfToken } = createSessionToken(address);Returns: Object containing JWT token and CSRF token
Validates JWT token and returns session information.
const result = verifySessionToken(token);
// result.valid, result.address, result.csrfToken, result.errorReturns: SessionVerificationResult with validity status and user data
Revokes a session token for logout functionality.
const revoked = revokeSessionToken(token);Returns: Boolean indicating successful revocation
Middleware function for protecting routes that extracts and validates session cookies.
const authenticatedReq = requireAuth(req);
// authenticatedReq.user.address, authenticatedReq.user.csrfTokenThrows: UnauthorizedError for invalid/missing sessions
Validates CSRF token for state-changing requests (POST, PUT, PATCH, DELETE).
validateCsrfToken(req, expectedCsrfToken);Throws: UnauthorizedError for missing/invalid CSRF tokens
Validates Origin/Referer headers for additional CSRF protection.
validateOrigin(req);Throws: UnauthorizedError for cross-origin requests
Authenticates user via Stellar signature and creates session.
Request Body:
{
"address": "G...",
"signature": "signature-hex",
"message": "Sign in to CommitLabs: nonce"
}Response:
{
"verified": true,
"address": "G...",
"message": "Signature verified successfully",
"csrfToken": "csrf-token-hex"
}Cookies Set:
session: HTTP-only JWT token (24 hours)csrf: Non-HttpOnly CSRF token (24 hours)
Terminates user session and clears cookies.
Headers: Requires valid session cookie
Response:
{
"loggedOut": true,
"message": "Session terminated successfully"
}Cookies Cleared: Both session and CSRF cookies
import { requireAuth, validateCsrfToken, validateOrigin } from '@/lib/backend/requireAuth';
import { NextRequest, NextResponse } from 'next/server';
export const POST = async (req: NextRequest) => {
// Authenticate user
const authenticatedReq = requireAuth(req);
// Validate CSRF for state-changing requests
validateCsrfToken(req, authenticatedReq.user.csrfToken);
// Additional origin validation
validateOrigin(req);
// Process authenticated request
const userAddress = authenticatedReq.user.address;
return NextResponse.json({
message: 'Action completed successfully',
user: userAddress,
});
};// After successful authentication
const response = await fetch('/api/auth/verify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
address,
signature,
message,
}),
});
// For subsequent authenticated requests
const protectedResponse = await fetch('/api/protected-route', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': getCsrfToken(), // Get from cookie or response
},
body: JSON.stringify(data),
});- JWT Secret: Set
JWT_SECRETenvironment variable with strong random value - HTTPS: Ensure all cookies are marked Secure (automatic in production)
- Session Store: Replace in-memory store with Redis/database for scalability
- Rate Limiting: Implement rate limiting on authentication endpoints
- Monitoring: Log authentication failures and suspicious activity
- HTTP-only cookies prevent JavaScript access
- SameSite=Strict prevents cross-site request forgery
- Secure flag ensures HTTPS-only transmission
- 24-hour expiry limits exposure window
- Synchronizer token pattern requires server-generated token
- Origin validation provides additional protection
- Double-submit cookie pattern for client-side access
- JWT includes issued timestamp (iat) and expiry (exp)
- Server-side revocation list for immediate logout
- Nonce consumption prevents signature replay
- SameSite=Strict prevents cross-site cookie transmission
- Origin/Referer header validation
- Host header validation in production
-
Session Token Creation/Verification
- Valid token generation
- Token validation
- Expired token handling
- Invalid token rejection
- Token revocation
-
Authentication Middleware
- Valid session authentication
- Missing session rejection
- Invalid session rejection
- CSRF token validation
- Origin validation
-
API Endpoints
- Successful authentication
- Invalid signature handling
- Malformed request handling
- Logout functionality
# Run all session-related tests
npm test -- auth
# Run with coverage
npm run test:coverage -- auth- Update Client Code: Remove handling of
sessionTokenin response body - Cookie Handling: Ensure browser automatically includes session cookie
- CSRF Implementation: Add CSRF token to headers for state-changing requests
- Error Handling: Update error handling for 401/403 responses
# Required for production
JWT_SECRET=your-super-secret-random-key-here
# Optional (defaults to secure settings in production)
NODE_ENV=production- Refresh Tokens: Implement token rotation without requiring re-authentication
- Session Analytics: Track session patterns and anomalies
- Multi-Device Support: Allow multiple simultaneous sessions per user
- Session Persistence: Database-backed session storage for persistence across restarts
- Advanced CSRF: Implement more sophisticated CSRF protection mechanisms
- Horizontal Scaling: Redis-based session store for multiple server instances
- Load Balancing: Ensure session affinity or shared session store
- Caching: Implement session caching for high-traffic scenarios
- Monitoring: Add metrics for session creation, validation, and revocation
- Token Verification Fails: Check JWT_SECRET consistency across servers
- CSRF Validation Fails: Ensure client includes X-CSRF-Token header
- Cookie Not Set: Verify SameSite and Secure settings match environment
- Session Expires Too Soon: Check server time synchronization
Enable debug logging by setting:
DEBUG=session:* npm run devThis will provide detailed logging for session operations without exposing sensitive data.