⏰ Session Management
Odac uses a secure cookie-based session system with automatic expiration and cleanup.
How Sessions Work
When a user logs in, Odac creates a session token stored in secure cookies:
// Login creates a session
await Odac.Auth.login({email, password})
// Session is automatically checked on each request
if (await Odac.Auth.check()) {
const user = Odac.Auth.user(null)
}
Session Expiration
Sessions use a sliding window approach (similar to NextAuth.js):
- maxAge: Maximum session lifetime (default: 30 days)
- updateAge: How often to refresh the session (default: 1 day)
How it works:
- User logs in, session created
- User is active, session refreshed every 24 hours
- User inactive for 30 days, session expires
- Active users stay logged in indefinitely (up to 30 days of inactivity)
Token Rotation (Enterprise Grade)
Odac implements a non-blocking Refresh Token Rotation mechanism to enhance security:
- rotationAge: How often to rotate tokens (default: 15 minutes)
- Grace Period: When a token is rotated, the old token remains valid for 60 seconds to prevent race conditions in Single Page Applications (SPAs) making concurrent requests.
How it works:
- A request is made with an active token older than
rotationAge. - Odac issues a brand new token set and sends them as cookies.
- The old token is marked as "rotated" and assigned a 60-second lütuf (grace) period.
- Subsequent concurrent requests using the old token still pass within those 60 seconds.
- After 60 seconds, the old token is naturally expired.
Configuration
Configure session behavior in odac.json:
{
"auth": {
"table": "users",
"token": "user_tokens",
"maxAge": 2592000000,
"updateAge": 86400000,
"rotationAge": 900000,
"rotation": true
}
}
Options:
maxAge(milliseconds): Maximum inactivity period before session expires. Note: Cookies also use this value for persistence.- Default:
2592000000(30 days) - Example:
604800000(7 days)
- Default:
updateAge(milliseconds): How often to update the session timestamp (heartbeat)- Default:
86400000(1 day) - Example:
3600000(1 hour)
- Default:
rotationAge(milliseconds): How often to rotate the session tokens- Default:
900000(15 minutes)
- Default:
rotation(boolean): Enable or disable token rotation- Default:
true
- Default:
Common Configurations
Short sessions (banking apps):
{
"auth": {
"maxAge": 900000,
"updateAge": 300000
}
}
- 15 minutes inactivity timeout
- Refresh every 5 minutes
Long sessions (social apps):
{
"auth": {
"maxAge": 7776000000,
"updateAge": 86400000
}
}
- 90 days inactivity timeout
- Refresh every 1 day
Standard sessions (most apps):
{
"auth": {
"maxAge": 2592000000,
"updateAge": 86400000
}
}
- 30 days inactivity timeout (default)
- Refresh every 1 day (default)
Automatic Cleanup
Expired sessions are automatically cleaned up:
- When: During each login
- What: Removes sessions older than
maxAge - Why: Keeps database clean and performant
No manual cleanup needed!
Session Security
Sessions are protected with:
- httpOnly cookies: JavaScript cannot access tokens
- secure flag: Only sent over HTTPS
- sameSite: Strict: CSRF protection
- bcrypt hashing: Tokens are hashed in database
- browser fingerprinting: Tied to user agent
Manual Session Management
Logout current session:
await Odac.Auth.logout()
Check session status:
const isLoggedIn = await Odac.Auth.check()
Get user info:
const user = Odac.Auth.user(null) // Full user object
const user = Odac.Auth.user(null) // Full user object
const email = Odac.Auth.user('email') // Specific field
Custom Session Data
If you need to store your own data in the session (e.g. shopping cart ID, preferences), use the Odac.session() helper:
// Store data
Odac.session('theme', 'dark')
// Retrieve data
const theme = Odac.session('theme')
Best Practices
- Choose appropriate timeouts based on your app's security needs
- Use shorter sessions for sensitive operations (banking, admin panels)
- Use longer sessions for convenience apps (social media, content sites)
- Don't set updateAge too low - it causes unnecessary database writes
- Monitor session table size - cleanup runs automatically but check periodically
Troubleshooting
Users getting logged out too quickly:
- Increase
maxAgevalue - Check if users are actually inactive
Too many database writes:
- Increase
updateAgevalue - Default (1 day) is usually optimal
Session table growing too large:
- Check if cleanup is running (happens on login)
- Manually clean old sessions if needed:
const cutoffDate = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000)
await Odac.DB.user_tokens
.where('active', '<', cutoffDate)
.delete()