Access tokens include an 'aud' (audience) claim set to the client ID,
but this was never validated during token validation. This allowed
tokens issued for one client to be used by another client, violating
the OAuth 2.0 security model.
Changes:
- Add ValidateAccessTokenForClient method that validates audience
if expectedClientID is provided
- Update ValidateAccessToken to call ValidateAccessTokenForClient
(backward compatible, no audience check if not specified)
- Update userinfo endpoint to accept optional client_id parameter
and validate token audience matches it
Security impact:
- Prevents token reuse across different clients
- Ensures tokens are scoped to specific clients as intended
- Prevents attackers from using tokens issued for one client to
access resources protected by another client
The discovery document only advertises client_secret_basic and
client_secret_post as supported authentication methods. Query parameters
are insecure because they are:
- Logged in access logs
- Stored in browser history
- Exposed in referrer headers
This fix removes the query parameter fallback, ensuring client secrets
are only accepted via:
- Authorization header (client_secret_basic)
- POST form body (client_secret_post)
This aligns the implementation with the advertised capabilities and
prevents client secret exposure through query strings.
Per OAuth 2.0 RFC 6749 §4.1.2.1, errors should NOT redirect to
unvalidated redirect_uri values. This fix:
- Returns JSON errors for failures before redirect_uri validation
(missing parameters, invalid client)
- Only redirects to redirect_uri after it has been validated
against registered client URIs
- Prevents open redirect attacks where malicious redirect_uri
values could be used to redirect users to attacker-controlled sites
PKCE was advertised in the discovery document but not actually implemented.
This commit adds full PKCE support:
- Store code_challenge and code_challenge_method in authorization code JWT
- Accept code_verifier parameter in token endpoint
- Validate code_verifier against stored code_challenge
- Support both S256 (SHA256) and plain code challenge methods
- PKCE validation is required when code_challenge is present
This prevents authorization code interception attacks by requiring
the client to prove possession of the code_verifier that was used
to generate the code_challenge.
The validateAccessToken method was only decoding the JWT payload without
verifying the signature, allowing attackers to forge tokens. This fix:
- Adds ValidateAccessToken method to OIDCService that properly verifies
JWT signature using RSA public key
- Validates issuer, expiration, and required claims
- Updates controller to use the secure validation method
- Removes insecure manual JWT parsing code
This commit adds OpenID Connect (OIDC) provider functionality to tinyauth,
allowing it to act as an OIDC identity provider for other applications.
Features:
- OIDC discovery endpoint at /.well-known/openid-configuration
- Authorization endpoint for OAuth 2.0 authorization code flow
- Token endpoint for exchanging authorization codes for tokens
- ID token generation with JWT signing
- JWKS endpoint for public key distribution
- Support for PKCE (code challenge/verifier)
- Nonce validation for ID tokens
- Configurable OIDC clients with redirect URIs, scopes, and grant types
Validation:
- Docker Compose setup for local testing
- OIDC test client (oidc-whoami) with session management
- Nginx reverse proxy configuration
- DNS server (dnsmasq) for custom domain resolution
- Chrome launch script for easy testing
Configuration:
- OIDC configuration in config.yaml
- Example configuration in config.example.yaml
- Database migrations for OIDC client storage