Session Timeouts
Configure session duration, idle timeouts, and access token lifetimes in HelloJohn.
Session Timeouts
HelloJohn provides fine-grained control over session and token lifetimes. Configure these to balance security and user experience.
Timeout Settings
| Setting | Default | Description |
|---|---|---|
session_duration | 30d | How long the refresh token is valid (full session lifetime) |
access_token_ttl | 1h | How long each access token is valid |
idle_timeout | None | Revoke session after this period of inactivity |
max_sessions_per_user | Unlimited | Cap concurrent sessions per user |
Session Duration
The session_duration controls how long a user stays signed in without re-authenticating. It is the lifetime of the refresh token.
Examples:
30d— 30 days (default, standard web app)7d— 7 days (higher security apps)1y— 1 year (trusted devices)24h— 24 hours (banking, healthcare)
After session_duration, the refresh token expires and the user must sign in again.
Access Token TTL
The access_token_ttl controls how often a new access token is issued. Shorter values improve security at the cost of more refresh calls.
| Value | Use Case |
|---|---|
1h | Default — good balance |
15m | High-security apps needing faster revocation |
5m | Critical systems (token introspection still recommended) |
24h | Simple apps with low-security requirements |
Revoking a session does not immediately invalidate outstanding access tokens. A revoked session will reject refresh attempts, but existing access tokens remain valid until their
expclaim. For instant revocation, use API-based token verification rather than local JWT verification.
Idle Timeout
The idle timeout revokes sessions that haven't been active for a specified period. HelloJohn tracks activity via refresh token usage.
curl -X PATCH "https://api.hellojohn.dev/v1/admin/config" \
-H "Authorization: Bearer sk_live_abc123" \
-H "X-Tenant-ID: tnt_01HABCDEF654321" \
-H "Content-Type: application/json" \
-d '{"idle_timeout": "7d"}'When idle timeout is configured:
- Each time the access token is refreshed,
last_active_atis updated - Sessions where
last_active_atis older thanidle_timeoutare revoked - The next refresh attempt returns
session_expired
Configuring Timeouts
Via Dashboard
Go to Tenant Settings → Authentication → Session Settings.
Via Admin API
curl -X PATCH "https://api.hellojohn.dev/v1/admin/config" \
-H "Authorization: Bearer sk_live_abc123" \
-H "X-Tenant-ID: tnt_01HABCDEF654321" \
-H "Content-Type: application/json" \
-d '{
"session_duration": "14d",
"access_token_ttl": "15m",
"idle_timeout": "7d",
"max_sessions_per_user": 5
}'Recommended Configurations
Standard Web App
{
"session_duration": "30d",
"access_token_ttl": "1h",
"idle_timeout": null
}High-Security App (Banking, Healthcare)
{
"session_duration": "24h",
"access_token_ttl": "15m",
"idle_timeout": "1h",
"max_sessions_per_user": 3
}Enterprise / Compliance
{
"session_duration": "8h",
"access_token_ttl": "5m",
"idle_timeout": "30m",
"max_sessions_per_user": 2
}Remember Me
Implement "remember me" by issuing different session durations based on user choice:
const sessionDuration = rememberMe ? "30d" : "24h";
const session = await hj.auth.signIn({
email,
password,
sessionOptions: { duration: sessionDuration },
});Handling Expired Sessions in Your App
When an access token cannot be refreshed (session expired), redirect the user to sign in:
async function apiRequest(endpoint: string) {
let response = await fetch(endpoint, {
headers: { Authorization: `Bearer ${getAccessToken()}` },
});
if (response.status === 401) {
// Try to refresh
try {
await refreshTokens();
response = await fetch(endpoint, {
headers: { Authorization: `Bearer ${getAccessToken()}` },
});
} catch {
// Refresh failed — session expired
redirectToSignIn();
return;
}
}
return response.json();
}