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/authorizeto 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
sidclaim. 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:
- Open the tenant.
- Go to General → Token lifetimes.
- Enter a value in seconds (for example
900for 15 minutes, or2592000for 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 URLsub: user ID (or the app's client ID for client_credentials)aud: the resource the token was requested for with theresourceparameter; without one, the app's client IDexp,iat,nbf: standard expiry and timing claimsjti: token IDtid: tenant IDclient_id: the client ID of the app the token was issued toscope: granted scopes, space-separatedemail,email_verified: the user's email address and whether it is verified, present when theemailscope is granted, so an API or MCP server knows who is calling without another request. Not on client_credentials tokensexternal_id: present whenexternal_idscope is grantedorg_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 wayhttps://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 claimsnonce: replay protection for the appauth_time: time of authenticationsid: the browser session the user signed in with, the session'sidin the User API. Absent from tokens issued before Authalla recorded sessionsorg_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 wayemail,email_verified: present when theemailscope is grantedname,picture: present when theprofilescope is granted;pictureonly when the user signed in with a social login that has oneat_hash,c_hash: hashes of access token / authorization codeexternal_id: present whenexternal_idscope is grantedhttps://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:
- Use
/.well-known/openid-configurationto discover the issuer andjwks_uri. - Use
jwks_urito verify the JWT signature. - Validate the
typheader (at+jwtfor access tokens) and standard claims likeiss,aud, andexp. - Enforce your app rules using
scopeandtid.
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_idredirect_uriresponse_type=codescope(must includeopenid)state
Optional parameters:
nonce(ID token replay protection)code_challenge,code_challenge_method(PKCE;S256recommended)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:
issuerauthorization_endpointtoken_endpointjwks_urirevocation_endpointandintrospection_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.