goauthentik / goauthentik/authentik

Support RFC 8705 Mutual TLS (mTLS) Certificate-Bound Access Tokens (cnf.x5t#S256)

Open
#22,370 0 comments 0 reactions 0 assignees View on GitHub
enhancement enhancement/confirmed
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.