goauthentik / goauthentik/authentik
Support RFC 8705 Mutual TLS (mTLS) Certificate-Bound Access Tokens (cnf.x5t#S256)
- Dominant language
- Python
- Stars
- 25.6k
- Forks
- 2k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 644
Description
### Is your feature request related to a problem?
I'm building an OAuth2/OIDC-based zero-trust architecture where Authentik-issued access tokens are used inside a service mesh protected by mutual TLS (mTLS).
I want to enforce sender-constrained access tokens so that a stolen JWT cannot be replayed from a different client or device.
Specifically, I am trying to implement RFC 8705 (OAuth 2.0 Mutual-TLS Client Certificate Bound Access Tokens), where:
- The authorization server binds an access token to the client certificate used during authentication
- The access token includes a `cnf.x5t#S256` claim (certificate thumbprint)
- The resource server can verify that the request’s TLS client certificate matches the token binding
Currently, Authentik does not provide a native, supported mechanism to:
- Bind an access token to a client certificate in a standards-compliant way (RFC 8705)
- Emit `cnf.x5t#S256` based on the actual mTLS client certificate used in the authentication flow
- Maintain per-session or per-token certificate binding without relying on shared mutable user attributes or external proxy-side injection
As a result, implementing RFC 8705 requires unsafe or indirect workarounds such as:
- Storing certificate fingerprints in `user.attributes`
- Injecting headers via reverse proxies (forwardAuth / ext_authz)
- External token exchange or gateway-side binding enforcement
These approaches introduce race conditions, implicit shared state, or move critical security logic outside the identity provider.
### Describe the solution you'd like
I would like Authentik to provide native support for RFC 8705 (Mutual TLS certificate-bound access tokens).
Concretely:
1. Token binding to client certificate identity
- When a user authenticates via a flow where a trusted upstream proxy performs mTLS and forwards verified client certificate metadata, Authentik should be able to:
- Consume trusted client certificate identity context (e.g. SHA-256 thumbprint)
- Bind that identity to the issued OAuth2 access token
2. Automatic `cnf` claim support
- Optionally emit:
```json
"cnf": {
"x5t#S256": ""
}
```
- Following RFC 8705 semantics
3. First-class OAuth2 provider configuration option
- A toggle such as:
- "Enable mutual TLS sender-constrained tokens (RFC 8705)"
- With configurable trusted header sources (e.g. X-Forwarded-Client-Cert)
4. No reliance on mutable user attributes
- Binding should be per-token or per-session, not stored in global user state
5. Compatibility mode
- Allow both:
- Bearer tokens (default behavior)
- Sender-constrained tokens (RFC 8705 mode)
### Describe alternatives that you've considered
1. Gateway-enforced binding (Envoy / reverse proxy enforcement)
- Validate JWT + client cert match at the edge
- Pros: no IdP changes
- Cons: binding is not self-contained in the token; cannot be verified by downstream services
2. Token exchange service (RFC 8693-style pattern)
- Exchange Authentik-issued JWT for a new bound token
- Pros: supports proper `cnf` claim
- Cons: introduces a new critical signing service and additional trust anchor
3. Storing certificate thumbprints in `user.attributes`
- Attempt to propagate cert identity through scope mappings
- Cons: race conditions between sessions, shared mutable state, not session-safe
4. Switching to Keycloak
- Keycloak supports RFC 8705-style certificate-bound tokens natively
- Cons: significant migration cost and loss of Authentik flow flexibility
None of these approaches provide a clean, standards-based, first-class implementation inside Authentik.
### Additional context
Security requirement:
- Reduce replay risk of OAuth2 access tokens in deployments using mTLS at the reverse proxy by supporting RFC 8705 sender-constrained tokens (cnf.x5t#S256) using trusted client certificate metadata provided by the upstream proxy.
- Avoid reliance on external binding services or shared mutable state
- Keep enforcement inside identity provider + standard claims where possible
Contributor guide
Assessment
This issue has not been assessed yet.