Skip to content

Feature: OAuth2 Token Introspection (RFC 7662) + Token Revocation (RFC 7009) #3

Description

@hoangsonww

Summary
Add standard OAuth2 endpoints for /oauth/introspect and /oauth/revoke so resource servers can verify token status (active, scopes, expiry, subject) and clients can proactively revoke access and refresh tokens. Works with both JWT and opaque tokens; enables central revocation beyond JWT signature checks.

Why

  • Plays nicely with gateways/API proxies that expect RFC endpoints.
  • Lets services confirm a token is still valid (not expired/revoked) even if it’s a self-verifying JWT.
  • Clean logout flows: clients can revoke refresh tokens and derived access tokens immediately.
  • Complements the OIDC provider feature and supports mixed ecosystems.

Scope (MVP)

Endpoints

  • POST /oauth/introspect

    • Auth: client authentication (basic or body client_id/client_secret for confidential clients; public clients denied).

    • Request: token, optional token_type_hint (access_token | refresh_token).

    • Response (per RFC 7662):

      {
        "active": true,
        "scope": "openid email",
        "client_id": "myapp-web",
        "username": "[email protected]",
        "token_type": "access_token",
        "exp": 1712345678,
        "iat": 1712342078,
        "nbf": 1712342078,
        "sub": "user-uuid",
        "aud": "myapp-web",
        "iss": "https://auth.example.com",
        "jti": "uuid-of-token"
      }
    • If inactive/unknown/expired → {"active": false}.

  • POST /oauth/revoke

    • Auth: confidential client auth (same as above).

    • Request: token, optional token_type_hint.

    • Effect:

      • If refresh token → revoke that session + invalidate its descendant access tokens.
      • If access token (opaque or JWT) → mark as revoked (store jti) until expiry.
    • Response: 200 with empty body (idempotent per RFC 7009).

Token model & storage

  • Store jti, sub, client_id, scopes, exp, type for refresh and opaque access tokens in SQLite.
  • For JWT access tokens, include jti claim and maintain a revocation set (SQLite table) to deny listed JTIs at introspect and during internal validation.
  • Indexes on jti, client_id, sub, exp.

Client policy

  • Public clients: may not call introspect/revoke (lack client secret).
  • Confidential clients: must match the token’s client_id unless server policy allows broader admin clients.
  • Rate-limit per client & IP.

Config (TOML)

[oauth_introspection]
enable = true
allow_jwt_access_tokens = true       # if true, introspect JWTs too
include_username = true              # mirror email as username

[oauth_revocation]
enable = true
revoke_access_jwt_by_jti = true      # maintain revocation list for JWTs

Acceptance Criteria

  • POST /oauth/introspect returns active:true for valid tokens; false for expired/unknown/revoked.

  • POST /oauth/revoke successfully revokes:

    • refresh token → subsequent refresh fails; new access tokens no longer issued.
    • access token (JWT or opaque) → introspection shows active:false; internal middleware denies it.
  • Confidential client auth enforced; public clients rejected with 401/400.

  • Proper handling of token_type_hint (optional optimization; not required).

  • Unit tests: happy paths, wrong client auth, wrong client_id, expired, already revoked, JWT jti revocation.

  • Integration tests: full login → introspect(active) → revoke → introspect(inactive).

  • Basic DoS safeguards: per-route rate limiting & short DB queries (indexes present).


Security Notes

  • Always require client authentication for these endpoints; do not leak token metadata to unauthorized parties.
  • Introspection must only reveal claims for the owning client (or an admin client role).
  • Store only necessary fields; avoid logging raw tokens.
  • Keep revocation list bounded by TTL (delete expired rows).
  • Ensure constant-time comparisons where applicable.

Out of Scope (v1)

  • UMA/RPT, token exchange, back-channel logout, PAR.
  • Admin UI for viewing sessions (future).
  • JWT Detachment or MTLS-bound tokens.

Migration / Docs

  • New sections in README.md: Introspection & Revocation with cURL examples.

  • Add docs/oauth-introspection-revocation.md covering policies, examples for NGINX/Kong/API Gateway integration.

  • Provide sample snippet for resource servers:

    • Prefer local JWT verify; fallback to introspect for revocation checks, or periodic revocation cache.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdocumentationImprovements or additions to documentationduplicateThis issue or pull request already existsenhancementNew feature or requestgood first issueGood for newcomershelp wantedExtra attention is neededquestionFurther information is requested

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions