OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens
OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens (RFC 8705) enhance security measures for OAuth 2.0 client authentication and access token validation. By using mutual Transport Layer Security (TLS) authentication with X.509 certificates, this specification strengthens the security of OAuth 2.0 interactions.
This document outlines the implementation of RFC 8705 in the Safewhere Identify. It details the integration of mutual-TLS Client Authentication and Certificate-Bound Access Tokens within Identify, providing a secure and reliable authentication mechanism for clients accessing resources.
OpenId Connect Discovery endpoint
The OpenID Connect Discovery endpoint now includes the tls_client_certificate_bound_access_tokens property set to be true and introduces new Mutual-TLS endpoints and their supported authentication methods:
 "token_endpoint_auth_methods_supported": [
    ...
    "tls_client_auth",
    "self_signed_tls_client_auth"
  ],
 "introspection_endpoint_auth_methods_supported": [
    ...
    "tls_client_auth",
    "self_signed_tls_client_auth"
  ],
  "revocation_endpoint_auth_methods_supported": [
    ...
    "tls_client_auth",
    "self_signed_tls_client_auth"
  ],
  "tls_client_certificate_bound_access_tokens": "true",
  "mtls_endpoint_aliases": {
    "introspection_endpoint": "https://dev.safewhere.local/runtime/oauth2/mtls/introspect.idp",
    "revocation_endpoint": "https://dev.safewhere.local/runtime/oauth2/mtls/revoke.idp",
    "token_endpoint": "https://dev.safewhere.local/runtime/oauth2/mtls/token.idp"
  },

Configuration
Mutual-TLS client authentication requires Identify to validate the client certificates. To do this, configure the Client jwks uri or the Client jwks on the corresponding OAuth connection to validate the received client certificate.
Below is an example of Client jwks on the OAuth connection:
{
    "keys": [{
            "kid": "2vX8X64cGPzS_Ea7-RSsV1S1mJU",
            "use": "sig",
            "kty": "RSA",
            "alg": "RS256",
            "e": "AQAB",
            "n": "6-yr1EYwZisHKlE...RCAND0nY5-HQ",
            "x5t": "2vX8X64cGPzS_Ea7-RSsV1S1mJU",
            "x5c": [
           "MIIDYzCCA...JfSANszA=="
            ]
        }
}

You can also enable additional client certificate validation option:
- Client certificate revocation check: When the selected value is not None, Safewhere Identify performs a revocation check for the client certificate used in the mTLS endpoints.
Mutual-TLS endpoints
As shown in the OpenID Connect Discovery endpoint, there are three endpoints supporting mutual-TLS client authentication:
Token endpoint
The token exchange endpoint now has an alias for mutual-TLS client authentication at /runtime/oauth2/mtls/token.idp. You can use this endpoint to request an access token without providing a client_secret; however, it requires a client certificate for authentication.
Request URL:
https://#identifydomain/runtime/oauth2/mtls/token.idp
| Key | Value | 
|---|---|
| client_id | oidc_active_id2 | 
| grant_type | client_credentials | 

The mTLS token request must include the client certificate, which should be registered in the Client jwks uri or the Client jwks on the corresponding OAuth connection

Certificate-Bound access token
The access token obtained from this endpoint will be a Certificate-Bound access token. It will include a cnf (confirmation) claim containing the hashed value of the client certificate

Introspection and Revocation endpoints
The Introspection endpoint and the Revocation endpoint function similarly to the Token endpoint, requiring a client certificate instead of a client_secret for authentication
Request URL:
https://#identifydomain/runtime/oauth2/mtls/introspect.idp
| Key | Value | 
|---|---|
| token | eyJhbGciOiJSUzI1...UYmJGtgHjF | 
| client_id | oidc-mutual-flow-clientid | 

Request URL:
https://#identifydomain/runtime/oauth2/mtls/revoke.idp
| Key | Value | 
|---|---|
| token | eyJhbGciOiJSUzI1...NmUUYmJGtgHjF | 
| client_id | oidc-mutual-flow-clientid | 
| token_type_hint | access_token | 

Confirmation method for Token Introspection
When invoking the introspection endpoint to inspect a Certificate-Bound token, the introspection response contains the cnf (confirmation) claim. This claim's value is the hash of the client certificate to which the token is bound.
Example:
{
    "active": true,
    "iss": "https://identify.identify.safewhere.com/runtime/oauth2",
    "sub": "abc",
    "jti": "199167c4-df77-4017-94a3-682398f37a74",
    "token_type": "Bearer",
    "client_id": "oidc-mutual-flow-clientid",
    "cnf": {
        "x5t#S256": "E53-0vh8rl1ZKdrqthXcLqEWHhqX-x3_JZ_ZtGh_yVg"
    },
    "iat": 1718702792,
    "nbf": 1718702792,
    "exp": 1719062792,
    "aud": "https://api01.demo.com/runtime/"
    ]
}
Security considerations
- Implementing RFC 8705 introduces security enhancements but requires careful management of potential risks. Administrators must handle client certificates securely in the Client jwks urisetting and theClient jwkssettings, ensuring they remain valid and revoking them when necessary.
- When combining mutual-TLS OAuth endpoints with private_key_jwtmethod, the validation of theclient_idparameter is skipped.