The variable 'html' was being assigned to store HTML content, which
caused Python to treat 'html' as a local variable throughout the
function. This prevented access to the 'html' module (imported at
the top) within f-strings that referenced html.escape().
Renamed the HTML content variable to 'html_content' to avoid the
naming conflict with the html module.
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
* chore: add yaml config ref
* feat: add initial implementation of a traefik like cli
* refactor: remove dependency on traefik
* chore: update example env
* refactor: update build
* chore: remove unused code
* fix: fix translations not loading
* feat: add experimental config file support
* chore: mod tidy
* fix: review comments
* refactor: move tinyauth to separate package
* chore: add quotes to all env variables
* chore: resolve go mod and sum conflicts
* chore: go mod tidy
* fix: review comments
Previously IsRedirectSafe rejected redirects to the exact cookie domain
when AppURL had multiple subdomain levels, because it stripped the first
label twice.