Skip to main content

introspect

Function introspect 

Source
pub async fn introspect(
    pool: Data<PgPool>,
    __arg1: OAuthValidated<IntrospectQuery>,
    app_conf: Data<ApplicationConfiguration>,
) -> ControllerResult<HttpResponse>
Expand description

Handles the /introspect endpoint for OAuth 2.0 token introspection (RFC 7662).

This endpoint allows resource servers to query the authorization server about the active state and metadata of an access token.

§Security Features

  • Only a confidential client may introspect; an unknown client, a public client or a bad secret is 401 invalid_client (RFC 7662 §2.1, §2.3)
  • Returns 200 with active: false for an invalid/expired token (RFC 7662 §2.1), so token existence is never disclosed to an authenticated caller

§Request Parameters

  • token (required): The token to be introspected
  • token_type_hint (optional): Hint about token type (“access_token” or “refresh_token”)
  • client_id (required): Client identifier of a confidential client
  • client_secret (required): Client secret

§Response

Returns a JSON object with:

  • active (bool, required): Whether the token is active
  • Additional fields only present if active: true:
    • scope: Space-separated list of scopes
    • client_id: Client identifier
    • username/sub: User identifier (if token has user)
    • exp: Expiration timestamp (Unix time)
    • iat: Issued at timestamp (Unix time)
    • aud: Audience
    • iss: Issuer
    • jti: JWT ID
    • token_type: “Bearer” or “DPoP”
  • Non-standard members, returned only to callers that authenticated as a confidential client and omitted (never falsified) otherwise:
    • upstream_id: the token owner’s legacy TMC user id
    • client_bearer_allowed: whether the client the token was issued to may use it as a plain Bearer credential. Consumers must fail closed if it is absent.

Follows RFC 7662 — OAuth 2.0 Token Introspection.

§Example

POST /api/v0/main-frontend/oauth/introspect HTTP/1.1
Content-Type: application/x-www-form-urlencoded

token=ACCESS_TOKEN&client_id=test-client-id&client_secret=test-secret

Successful response:

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store

{
  "active": true,
  "scope": "openid profile email",
  "client_id": "test-client-id",
  "sub": "550e8400-e29b-41d4-a716-446655440000",
  "username": "550e8400-e29b-41d4-a716-446655440000",
  "exp": 1735689600,
  "iat": 1735686000,
  "iss": "https://example.com/api/v0/main-frontend/oauth",
  "jti": "123e4567-e89b-12d3-a456-426614174000",
  "token_type": "Bearer"
}

Inactive token response:

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store

{
  "active": false
}