Authenticate with mTLS

mTLS in OAuth/OIDC

Default OAuth/OIDC flows are not always secure because of the following issues:

  • The use of a shared Client Secret as a form of client authentication.

  • The ability for an access token to be used by unintended parties.

In 2020, the Internet Engineering Task Force (IETF) released RFC 8705 Mutual-TLS (mTLS) client authentication to address these issues. With mTLS authentication, the client certificate with a private key functions like a Client Secret in an OAuth/OIDC flow to verify the client’s identity. If a client is already authenticated at the network layer, there’s no need for a Client Secret at the application layer. Additionally, client certificates can be used with multiple servers to prove a client’s identity to a resource server. Note there are other approaches to solve the above issues, namely Private Key JWT and DPoP respectively.

To secure an OAuth flow with mTLS, clients send a mTLS certificate to the TLS termination point on the customer edge network when the TLS connection is being established. Before the authorization server processes the request, it must first verify the client’s mTLS certificate.

Optionally, mTLS can also be used to ensure an access token is used only by the intended party, known as Sender Constraining or Token Binding. When the client calls the /oauth/token endpoint on the authorization server using an mTLS connection, the resulting access token contains information that the resource server uses to verify that the client’s TLS certificate matches that of the access token.

Note: mTLS client authentication and mTLS Token Binding can be used independently of each other. mTLS client authentication can be used without mTLS Token Binding, and mTLS Token Binding can be used with other forms of client authentication such as Client Secret or Private Key JWT. Even if other forms of client authentication are used, the client still sends the client certificate to the authorization server for mTLS Token Binding.

mTLS at Auth0

mTLS for Auth0 builds on custom domains and leverages the customer’s existing mTLS infrastructure to perform certificate provisioning and verification.

Authenticated client calls to Auth0 that normally require a Client Secret are first sent to the customer edge. This already happens for custom domains that use customer-managed certificates. The customer edge performs the mTLS handshake with the client and validates the client certificate. Once the client certificate is verified, the request is then forwarded to the tenant’s edge domain at Auth0, including the validated client certificate in an HTTP header along with the correct cname-api-key as per the custom domains functionality.

Call the authorization server

Since mTLS serves both client authentication and access token binding, the client must know whether these features are enabled on the authorization server. In addition, an authorization server’s mTLS endpoints and non-mTLS endpoints may be exposed on different domains.

To get configuration details about the authorization server, the client sends a GET request to the OpenID Connect Discovery endpoint: https://<custom-domain>/.well-known/openid-configuration

A successful response returns the OIDC discovery document, or a JSON object listing the authorization server’s properties and endpoints, including those related to mTLS.

If mTLS client authentication is enabled, the OIDC discovery document includes the token_endpoint_auth_methods_supported property, which contains either tls_client_auth or self_signed_tls_client_auth:

{
  ...
  "token_endpoint_auth_methods_supported": ["tls_client_auth"]
  ...
}

Was this helpful?

/

If mTLS Token Binding is enabled, the OIDC discovery document sets the  tls_client_certificate_bound_access_tokens property to true:

{
  ...
  "tls_client_certificate_bound_access_tokens": true
  ...
}

Was this helpful?

/

Environments that support mTLS endpoint aliases expose a new property, mtls_endpoint_aliases, that contains a list of endpoints that support mTLS. For clients that support mTLS, the endpoints listed under mtls_endpoint_aliases take precedence over the same endpoints exposed outside of mtls_endpoint_aliases.

In the following code sample, the token_endpoint property is exposed twice. The endpoint to use for mTLS calls is listed under mtls_endpoint_aliases, or https://mtls.auth.bank.com/oauth/token:

{
  ...
  "mtls_endpoint_aliases": {
"token_endpoint": "https://mtls.auth.bank.com/oauth/token"
  },
  "token_endpoint": "https://auth.bank.com/oauth/token",
  "pushed_authorization_request_endpoint": "https://auth.bank.com/oauth/par",
  ...
}

Was this helpful?

/

If an endpoint is not listed under mtls_endpoint_aliases, use the same endpoint listed outside of mtls_endpoint_aliases. In the example above, pushed_authorization_request_endpoint is not listed under mtls_endpoint_aliases. As a result, use the pushed_authorization_request_endpoint exposed outside of mtls_endpoint_aliases, or https://auth.bank.com/oauth/par.

For more information, see RFC 8705’s section on endpoint aliases.

Call the resource server

Once a client receives an access token, it can access protected resources on a resource server. If mTLS Token Binding is enabled, the authorization server returns the OIDC discovery document that contains the tls_client_certificate_bound_access_tokens property. 

When the client calls the resource server with a mTLS-bound access token, the resource server requests a mTLS certificate from the client during the TLS handshake. The resource server should reject requests with an access token that does not match that client certificate with a 401 HTTP status code and an invalid_token error code. To learn more, read Configure Resource Server for Sender Constraining.

Learn more