ID tokens
Build on Kinde
Access tokens are a secure way of authenticating users and passing information about a user to a system.
{ "aud": [ "myapp:prod-api" ], "azp": "dee7f3c57b3c47e8b96edde2c7ecab7d", "exp": 1693371599, "feature_flags": { "analytics": { "t": "b", "v": true }, "theme": { "t": "s", "v": "pink" } }, "iat": 1693285199, "iss": "https://<your_subdomain>.kinde.com", "jti": "fbb6bc62-x64e-4256-8ea4-8fb9a645b123", "org_code": "org_xxxxxxxxx", "permissions": [ "create:competitions", "delete:competitions", "view:stats", "invite:users", "view:profile" ], "scp": [ "openid", "profile", "email", "offline" ], "sub": "kp:_xxxxxxxxx" // your user id}Bearer is a common token type used in OAuth 2.0.exp - Access tokens come with an expiration time (also known as expiry or lifetime) after which it is no longer valid. The timestamp is usually represented in seconds and can be calculated using the Epoch timestamp (UNIX) or other methods. More about setting token expiry in Kinde.scp - information about the scopes granted to the token holder. These scopes define what actions or resources the token can access. There can be multiple scope values, so the type of this claim is an array.iss claim in JWT. Typically your kinde domain e.g. https://<your_subdomain>.kinde.comsub claim in JWT. If this is an access token for a Kinde user this will be their ID e.g. kp_xxxx. The sub claim is set by Kinde and cannot be overridden.aud claim in JWT. There can be multiple audience values, so the type of this claim is an array.iat claim in JWT. The timestamp is usually represented in seconds and can be calculated using the Epoch timestamp (UNIX) or other methods.jti - identifier for the access token, useful for tracking and validation purposes. See this definition.Organization - org_code claim for the organization they are accessing. Format is org_xxxx.
Feature flags - feature_flags claim. Access controls for what features the user can see and access. Format is:
"feature_flags": { "analytics": { "t": "b", "v": true }, "theme": { "t": "s", "v": "pink" }}We use short codes for the various keys in the feature flags claim such as t and v to keep the token size down.
t = type
v = value
b = boolean
i= integer
s = strong
Permissions - permissions claim controls for what the user can do in an app. This is an array. For example:
"permissions": [ "create:competitions", "delete:competitions", "view:stats", "invite:users", "view:profile]Billing trial - When a user has an active billing trial on their plan, the token may include has_trial_period (boolean) and trial_expires_on (ISO 8601 datetime string for when the trial ends). trial_expires_on is typically present when has_trial_period is true. For definitions, see Billing concepts & terms.
External provider ID - The ID you use to identify the organization the user is authorized against
(MS Entra ID authentication only) Claims starting with ext_ indicate that user details have come from a third party enterprise auth provider like Microsoft. For example:
"ext_groups": [ "group1", "group2],"ext_attributes": { "jobTitle": "engineer", "mail": "engineer@kinde.com", "preferredLanguage": "en",}Yes. Kinde automatically populates the access token with claims like permissions, feature_flags, and org_code. If your app handles this data another way — or you want to keep JWTs small and free of client-readable claims — you can strip any of these from the token at generation time using the user token generation workflow.
The workflow fires whenever a token is issued and gives you full control over what goes into the final token. You can also use it to retrieve data from the Kinde Management API server-side instead of embedding it in the JWT.
Access tokens have a default lifetime of 24 hours (86,400 seconds). You can change this in Settings > Environment > Applications > [your app] > Tokens. Kinde does not recommend extending the access token lifetime beyond 1 day, as access tokens are the most exposed token type and a longer lifetime increases the window of risk if one is compromised.
For a comparison of all token default lifetimes, see Configure token and session expiry.
When you use the refresh_token grant to refresh an access token, Kinde will return an existing access token if that existing access token is not expired. You will get a completely new access token if one (or more) of the following conditions are met: