barycenter/docs/oidc-conformance.md
Claude 7b16f54223
feat: Add token introspection endpoint, docs, and validation scripts
Implement the remaining items from docs/next-iteration-plan.md:

- Add POST /introspect endpoint (RFC 7662) with client authentication,
  support for access and refresh tokens, and token_type_hint
- Add raw token lookup functions in storage for introspection
- Add revocation_endpoint and introspection_endpoint to discovery metadata
- Create docs/flows.md with end-to-end curl examples for all OIDC flows
- Create scripts/validate-oidc.sh to verify discovery, JWKS, registration,
  introspection, and revocation endpoints
- Update docs/oidc-conformance.md to reflect actual implementation status
- Update README.md and CLAUDE.md pending sections to be accurate

https://claude.ai/code/session_01JBxVy75XfwwZB8iBXjTxT3
2026-03-19 20:30:31 +00:00

135 lines
6.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

### OpenID Connect OP conformance plan (context7 summary)
This project is an OpenID Provider (OP) scaffold. This document summarizes what must be implemented to align with OpenID Connect 1.0 (and adjacent OAuth2/OAuth 2.1 guidance), what we already have, and the minimal viable roadmap.
Scope references (context7 up-to-date pointers):
- OpenID Connect Core 1.0 (final)
- OpenID Connect Discovery 1.0 (/.well-known/openid-configuration)
- OAuth 2.0 (RFC 6749) + PKCE (RFC 7636) and OAuth 2.1 draft guidance + OAuth 2.0 Security BCP (RFC 6819 successor BCPs)
- OpenID Connect Dynamic Client Registration 1.0
- OpenID Federation 1.0 (for later phases)
1) Endpoints required for a basic, interoperable OP
- Authorization endpoint: GET/POST /authorize
- Response type: code (Authorization Code Flow)
- Required request params: client_id, redirect_uri, response_type=code, scope (includes openid), state; Recommended: nonce; If PKCE is used: code_challenge, code_challenge_method=S256
- Validations: registered redirect_uri match, scope contains openid, client is known, response_type supported, PKCE required for public clients
- Output: HTTP redirect to redirect_uri with code and state
- Token endpoint: POST /token (application/x-www-form-urlencoded)
- Grant type: authorization_code
- Parameters: grant_type, code, redirect_uri, client authentication
- Client auth: client_secret_post and client_secret_basic (both supported)
- PKCE verification: code_verifier must match stored code_challenge (S256)
- Output: JSON with access_token, token_type=bearer, expires_in, id_token (JWT), possibly refresh_token
- Error model: RFC 6749 + OIDC specific where applicable
- UserInfo endpoint: GET/POST /userinfo (Bearer token)
- Input: Authorization: Bearer <access_token>
- Output: JSON claims for the subject consistent with scopes (profile, email, etc.)
- Discovery endpoint: GET /.well-known/openid-configuration
- Must publish: issuer, authorization_endpoint, token_endpoint, jwks_uri, response_types_supported, subject_types_supported, id_token_signing_alg_values_supported
- Should publish: registration_endpoint (if supported), scopes_supported, claims_supported, grant_types_supported, token_endpoint_auth_methods_supported, code_challenge_methods_supported
- JWKS endpoint: GET /.well-known/jwks.json
- Publish public keys used to sign ID Tokens; include kid values
- Dynamic Client Registration endpoint: POST /connect/register
- Accept a subset of metadata: redirect_uris (required), client_name, token_endpoint_auth_method, etc.
- Output per spec: client_id, client_secret (for confidential clients), client_id_issued_at, token_endpoint_auth_method, and echoed metadata
- Later: registration access token and client configuration endpoint
2) Tokens and claims
- ID Token (JWT, JWS RS256 initially)
- Required claims: iss, sub, aud, exp, iat, auth_time (if max_age requested), nonce (if provided in auth request), at_hash (if access token issued), c_hash (optional if code returned from token endpoint)
- kid header must match a key in JWKS; alg consistent with discovery
- Access Token
- Can be opaque initially; include reference in DB; expires_in typically 3600s
- Optionally JWT access tokens later
- Refresh Token (optional in MVP)
- Issue for offline_access scope; secure storage; rotation recommended
3) Storage additions (DB)
- auth_codes: code, client_id, redirect_uri, scope, subject, nonce, code_challenge (S256), created_at, expires_at, consumed
- access_tokens: token, client_id, subject, scope, created_at, expires_at, revoked
- refresh_tokens (optional initially)
4) Security requirements (minimum)
- Enforce PKCE S256 for public clients; allow confidential without PKCE only if policy allows (recommended: require for all)
- Validate redirect_uri exact match against one of the clients registered URIs
- Validate aud (client_id) and iss in ID Token; use correct exp/iat skew bounds
- Use state and nonce to prevent CSRF and token replay
- Use HTTPS in production; publish an https issuer in discovery via server.public_base_url
5) Discovery metadata we should publish once endpoints exist
- issuer: <base URL>
- authorization_endpoint: <issuer>/authorize
- token_endpoint: <issuer>/token
- jwks_uri: <issuer>/.well-known/jwks.json
- registration_endpoint: <issuer>/connect/register
- response_types_supported: ["code"]
- grant_types_supported: ["authorization_code"]
- subject_types_supported: ["public"]
- id_token_signing_alg_values_supported: ["RS256"]
- token_endpoint_auth_methods_supported: ["client_secret_post", "client_secret_basic"]
- code_challenge_methods_supported: ["S256"]
- scopes_supported: ["openid", "profile", "email"]
- claims_supported: ["sub", "iss", "aud", "exp", "iat", "auth_time", "nonce", "name", "given_name", "family_name", "email", "email_verified"]
- userinfo_endpoint: <issuer>/userinfo (once implemented)
6) Current status in this repository
- Implemented:
- Authorization Code flow with PKCE (S256 enforced)
- Token endpoint with client_secret_post and client_secret_basic authentication
- ID Token signing (RS256) with at_hash, nonce, auth_time, AMR, and ACR claims
- UserInfo endpoint with Bearer token authentication
- Discovery endpoint with full metadata
- JWKS publication with key generation and persistence
- Dynamic client registration
- Refresh token grant with rotation
- Token revocation (RFC 7009)
- Token introspection (RFC 7662)
- Device Authorization Grant (RFC 8628)
- User authentication with sessions (password + passkey/WebAuthn)
- Two-factor authentication (admin-enforced, context-based)
- Consent flow with database persistence
- Background jobs for cleanup (sessions, tokens, challenges)
- Admin GraphQL API for user management
- Simple property storage API (non-standard)
- Federation trust anchors stub
- Remaining for full OIDC compliance:
- OpenID Federation trust chain validation
- User account management UI
- Key rotation and multi-key JWKS
7) Roadmap (remaining work)
Steps 1-5 of the original roadmap are complete. Remaining items:
Step 6: Federation
- Entity statement issuance, publication, and trust chain verification; policy application to registration
Step 7: Account management UI
- User-facing pages for profile, passkey management, and session management
Step 8: Advanced key management
- Key rotation, multi-key JWKS, algorithm agility
Implementation notes
- Keep issuer stable and correct in settings.server.public_base_url for production
- Ensure JWKS kid selection and alg entry match discovery
- Prefer S256 for PKCE; do not support plain
- See docs/flows.md for end-to-end curl examples
- See scripts/validate-oidc.sh for automated validation