HelloJohn / docs
Authentication

Sessions

How HelloJohn manages user sessions — access tokens, refresh tokens, session revocation, and multi-device management.

Every successful authentication creates a session in HelloJohn. A session represents an authenticated user on a specific device or browser, and persists until it expires or is revoked.

Tokens

Each session issues two tokens:

TokenTypeDefault TTLPurpose
Access tokenJWT (EdDSA signed)15 minutesAuthorizes API requests
Refresh tokenOpaque string30 daysGets new access tokens

Access token

The access token is a standard JWT. Your backend verifies it locally using HelloJohn's public JWKS — no network call required.

{
  "sub": "usr_01HX...",
  "iat": 1709900000,
  "exp": 1709900900,
  "iss": "https://your-instance.hellojohn.dev",
  "aud": "your-app",
  "tenant_id": "ten_01HX...",
  "roles": ["admin"],
  "email": "user@example.com",
  "email_verified": true
}

See JWT & Claims → for the full claim reference.

Refresh token

The refresh token is an opaque string stored server-side. When the access token expires, the SDK uses the refresh token to get a new access token silently — the user stays logged in.

Refresh token rotation is enabled by default: every time a refresh token is used, HelloJohn issues a new one and invalidates the old one. If an attacker steals and uses a refresh token, HelloJohn detects the reuse and revokes the entire session.

Session lifecycle

Login
  └─> Session created
        ├─ Access token (15 min)
        └─ Refresh token (30 days)

               │ (every 15 min, silently)

         Token refresh
               ├─ New access token
               └─ New refresh token (old one invalidated)

               │ (after 30 days of inactivity)

         Session expires


         User must log in again

Configuring TTLs

Adjust token lifetimes in your environment:

ACCESS_TOKEN_TTL=900     # seconds (default: 15 minutes)
REFRESH_TOKEN_TTL=2592000  # seconds (default: 30 days)

Or per-tenant via the API:

PATCH /v2/admin/tenants/{tenantId}/auth/config
{
  "access_token_ttl": 3600,    // 1 hour
  "refresh_token_ttl": 604800  // 7 days
}

Shorter access token TTLs improve security (an intercepted token is valid for less time) at the cost of more refresh calls. 15 minutes is a good default for most applications.

Listing active sessions

Users can see their active sessions in your app if you expose this functionality:

GET /v2/auth/sessions
Authorization: Bearer {access_token}
{
  "sessions": [
    {
      "id": "ses_01HX...",
      "created_at": "2026-03-01T10:00:00Z",
      "last_active_at": "2026-03-07T14:00:00Z",
      "user_agent": "Mozilla/5.0 (Mac) Chrome/121",
      "ip_address": "203.0.113.1",
      "current": true
    },
    {
      "id": "ses_01HY...",
      "created_at": "2026-02-15T08:00:00Z",
      "last_active_at": "2026-02-20T12:00:00Z",
      "user_agent": "Mozilla/5.0 (iPhone) Safari/17",
      "ip_address": "203.0.113.42",
      "current": false
    }
  ]
}

Revoking sessions

Revoke a specific session (logout this device)

DELETE /v2/auth/sessions/{sessionId}
Authorization: Bearer {access_token}

Revoke all sessions (logout everywhere)

DELETE /v2/auth/sessions
Authorization: Bearer {access_token}

Admin: revoke all sessions for a user

DELETE /v2/admin/users/{userId}/sessions
Authorization: Bearer {admin_token}

This is useful for security incidents — immediately invalidates all the user's sessions across all devices.

SDK: logout

SDK logout() calls always revoke the current session on the server first, then clears local tokens.

// React
const { logout } = useAuth()
await logout()           // revoke current session + clear tokens

// Next.js
const { signOut } = useHelloJohn()
await signOut({ redirectTo: '/login' })

Session security

FeatureBehavior
Refresh token rotationEvery use issues a new RT, old one invalidated
Reuse detectionUsing an invalidated RT revokes the entire session
IP bindingOptional — session can be bound to the IP at creation
User agent bindingOptional — session invalidated if UA changes
Server-side revocationImmediate — no waiting for token expiry

Enable IP and UA binding (stricter security)

PATCH /v2/admin/tenants/{tenantId}/auth/config
{
  "session_bind_ip": true,
  "session_bind_user_agent": true
}

Use this for high-security applications (banking, admin dashboards). It will log out users who switch networks or browsers.

On this page