Core authentication

Sessions & tokens

Sessions keep users signed in. Tokens are the credentials your apps use to call APIs.

For a full flow overview, see Authentication overview.


Sessions

  • Sessions keep a user signed in across pages and refreshes.
  • Sessions are used during /oauth2/authorize to complete login.
  • Admins see and end a user's sessions on the user's Sessions tab. Users can see and end their own from your product with the User API (GET /me/v1/sessions, DELETE /me/v1/sessions/{id}).
  • Tokens record the browser session they were signed in from, and refreshed tokens keep it. The ID token carries it as the sid claim. Ending a session doesn't revoke the tokens that came from it.

Token types

Authalla issues three kinds of tokens:

  • Access token (JWT): used by your API to authorize requests.
  • ID token (JWT): OpenID Connect identity token for the app.
  • Refresh token: used to mint new access/ID tokens. Refresh tokens are rotated on every use, and the refresh token TTL is sliding (see below).

Refresh tokens are only issued when the offline_access scope is granted.


Token lifetimes

Defaults (per tenant):

  • Access token: 15 minutes
  • ID token: 15 minutes
  • Refresh token: 30 days

You can override these in the Admin UI:

  1. Open the tenant.
  2. Go to General → Token lifetimes.
  3. Enter a value in seconds (for example 900 for 15 minutes, or 2592000 for 30 days).

Changes apply to newly issued tokens.


Refresh token TTL is sliding (rotating refresh tokens)

Authalla uses refresh token rotation. When a refresh token is used successfully:

  • The old refresh token is revoked.
  • A new refresh token is issued.
  • The new refresh token expires at now + refresh token TTL.

This means the refresh token TTL acts like an inactivity window. If your app refreshes regularly, the refresh session can extend beyond the original login time.


Revoking tokens

Revoking ends a grant: the refresh token and every access token issued from the same sign-in. It happens when:

  • an app revokes its own token at /oauth2/revoke (Token revocation);
  • an admin revokes an app from the user's Connected apps tab, or uses Sign out everywhere;
  • the user revokes an app through the User API;
  • the user is suspended or deactivated.

A revoked refresh token fails at once with invalid_grant. A revoked access token still passes a local JWT check until it expires; servers that call the introspection endpoint refuse it at once. See Revoke access.


Access token claims (important ones)

Access tokens follow RFC 9068 (JWT profile for OAuth 2.0 access tokens). Their header has typ: at+jwt; ID tokens don't, so check typ to make sure you were handed an access token.

  • iss: issuer URL
  • sub: user ID (or the app's client ID for client_credentials)
  • aud: the resource the token was requested for with the resource parameter; without one, the app's client ID
  • exp, iat, nbf: standard expiry and timing claims
  • jti: token ID
  • tid: tenant ID
  • client_id: the client ID of the app the token was issued to
  • scope: granted scopes, space-separated
  • email, email_verified: the user's email address and whether it is verified, present when the email scope is granted, so an API or MCP server knows who is calling without another request. Not on client_credentials tokens
  • external_id: present when external_id scope is granted
  • org_id: the organization whose single sign-on the user signed in through. No scope is needed, and refreshed tokens keep it. Absent when the user signed in any other way
  • https://authalla.com/claims/sign_in: custom claims from the Sign-in hook

ID token claims (important ones)

  • iss, sub, aud, exp, iat, jti: standard OIDC claims
  • nonce: replay protection for the app
  • auth_time: time of authentication
  • sid: the browser session the user signed in with, the session's id in the User API. Absent from tokens issued before Authalla recorded sessions
  • org_id: the organization whose single sign-on the user signed in through. No scope is needed, and refreshed tokens keep it. Absent when the user signed in any other way
  • email, email_verified: present when the email scope is granted
  • name, picture: present when the profile scope is granted; picture only when the user signed in with a social login that has one
  • at_hash, c_hash: hashes of access token / authorization code
  • external_id: present when external_id scope is granted
  • https://authalla.com/claims/sign_in: custom claims from the Sign-in hook

JWT validation guidelines

If you're integrating Authalla into your app, always use a JWT validation library when one is available. For a full example, see Authorize middleware: validate access tokens.

At a high level, validate tokens as follows:

  1. Use /.well-known/openid-configuration to discover the issuer and jwks_uri.
  2. Use jwks_uri to verify the JWT signature.
  3. Validate the typ header (at+jwt for access tokens) and standard claims like iss, aud, and exp.
  4. Enforce your app rules using scope and tid.

If you need user profile data, call /oauth2/userinfo with the access token.

A local check can't see revocation. To refuse a revoked token before it expires, ask the introspection endpoint instead.


Endpoints to inspect

Authorization endpoint (/oauth2/authorize)

Required parameters:

  • client_id
  • redirect_uri
  • response_type=code
  • scope (must include openid)
  • state

Optional parameters:

  • nonce (ID token replay protection)
  • code_challenge, code_challenge_method (PKCE; S256 recommended)
  • login_hint (the user's email: the sign-in and sign-up pages open with it filled in, and an email domain with an SSO connection goes straight to that identity provider)

Discovery endpoint (/.well-known/openid-configuration)

Use this to find:

  • issuer
  • authorization_endpoint
  • token_endpoint
  • jwks_uri
  • revocation_endpoint and introspection_endpoint
  • supported scopes, grant types, and response types

JWKS endpoint (/.well-known/jwks.json)

Contains the public key(s) for validating Authalla JWTs for the tenant.

Revocation endpoint (/oauth2/revoke)

An app revokes its own access or refresh token, and with it the whole grant. See Token revocation.

Introspection endpoint (/oauth2/introspect)

A confidential app with the tokens:introspect scope asks whether a token is active. See Token introspection.

Previous
Let your customer set up SSO