Skip to main content

Opaque token

During the authentication process, if no resource is specified, Logto will issue an opaque access token instead of a JWT. The opaque token is a random string and it's much shorter than a JWT:

{
"access_token": "some-random-string", // opaque token
"expires_in": 3600,
"id_token": "eyJhbGc...aBc", // JWT
"scope": "openid profile email",
"token_type": "Bearer"
}

The opaque token can be used to call the userinfo endpoint and to access protected resources that require authentication. Since it's not a JWT, how can the resource server validate it?

Logto provides an introspection endpoint that can be used to validate opaque tokens. By default, the introspection endpoint is /oidc/token/introspection and accepts POST requests. The following parameter is required:

  • token: the opaque token to validate

The endpoint also requires client authentication. You can use one of the following methods:

  • HTTP Basic authentication: Use the Authorization header with the value Basic <base64-encoded-credentials>. The credentials must be the client ID and client secret separated by a colon (:) and base64-encoded.
  • HTTP POST authentication: Use the client_id and client_secret parameters:
    • client_id: the client ID of the application that requested the token
    • client_secret: the client secret of the application that requested the token

The client ID (app ID) and client secret (app secret) can be the app credentials from any "traditional web" or "machine-to-machine" application in Logto. The introspection endpoint will return an error if the credentials are invalid.

The introspection endpoint returns a JSON object with the claims of the token:

{
"active": true, // whether the token is valid or not
"sub": "1234567890", // the subject of the token (the user ID)
"acr": "urn:logto:acr:1fa", // authentication assurance level, when achieved
"amr": ["pwd"], // authentication methods used in the interaction
"auth_time": 1787745600 // when the user authenticated (epoch seconds)
}

If the token is invalid, the active field will be false and the other claims will be omitted. See Step-up authentication for how to validate acr, amr, and auth_time. Note that structured JWT access tokens cannot be introspected at /oidc/token/introspection—always validate JWT access tokens locally against your tenant's JWKS.

Here's a non-normative example of the introspection request:

curl --location \
--request POST 'https://[tenant-id].logto.app/oidc/token/introspection' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'token=some-random-string' \
--data-urlencode 'client_id=1234567890' \
--data-urlencode 'client_secret=1234567890'

Remember to replace [tenant-id] with your tenant ID.

Opaque token and organizations​

Opaque tokens can be used to retrieve organization membership information via the userinfo endpoint. When you request the urn:logto:scope:organizations scope, the userinfo endpoint will return the user's organization-related claims, such as organizations (organization IDs) and organization_data.

However, opaque tokens cannot be used as organization tokens. Organization tokens are always issued in JWT format because:

  1. Organization tokens contain organization-specific claims (like organization_id and scoped permissions) that need to be validated by resource servers.
  2. The JWT format allows resource servers to verify the token and extract organization context without additional API calls.

To obtain an organization token, you need to use the refresh token flow or client credentials flow with organization parameters.