How to setup a TLS termination proxy for client authentication with X.509 certificate
Connect2id server 6.13 added support for
letting OAuth 2.0 clients authenticate with a X.509 certificate submitted
during the TLS handshake, thus enabling issued access tokens to be bound to it
(fixing the bearer weakness). The public key encoded in the certificate must be
registered as an RSA or EC JWK with the Connect2id server. This authentication
self_signed_tls_client_auth, is specified in the Mutual TLS
Profile for OAuth 2.0.
TLS (HTTPS) can be handled by the servlet container (e.g. Apache Tomcat) where the Connect2id server is deployed, or by a dedicated TLS termination proxy, such as Nginx or Apache httpd. We recommend the latter method, as it provides more flexibility.
In order for
self_signed_tls_client_auth to work:
The TLS proxy must be configured to accept self-signed client certificates;
Once TLS proxy and client are mutually authenticated, the TLS proxy must pass the received client X.509 certificate to the Connect2id server for public key validation, via an agreed HTTP security header.
Here are the instructions in detail:
1. Specify an HTTP header for passing the client X.509 certificate
The client certificate must be passed from the TLS termination proxy to the Connect2id server for final validation of its public key. The simplest way to pass the client certificate is to encode it into a text string (PEM encoded) and insert it as a special new HTTP header into the HTTP request.
To prevent injection attacks the TLS termination proxy must be configured to remove all incoming HTTP headers that have the same name. For extra security, in case the TLS termination proxy gets badly configured and incoming HTTP headers are not sanitised, the header should be given a name that is secret and hard to guess (include a long random string).
Example header to pass the PEM-encoded client certificate from the TLS termination proxy to the Connect2id server:
Sec-Client-X509-Cert-alaeLuL8geiqu3OhOg1Mafa4Ecu9ahsh: -----BEGIN CERTIFICATE-----MIICsDCCAZigAwIBAgIIdF+Wcca7gzkwDQYJKoZIhvcNAQELBQAwGDEWMBQGA1UEAwwNY2FvajdicjRpcHc2dTAeFw0xNzA4MDcxNDMyMzVaFw0xODA4MDcxNDMyMzZaMBgxFjAUBgNVBAMMDWNhb2o3YnI0aXB3NnUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCdrt40Otrveq46K3BzZuds6wDqsP0kZV+C3GdyTQWl53orBRtPIiEh6BauP17Rr19qadh7t4yFBb5thrXwBewseSNEL4j7sB0YoeNwRsmA29Fjfoe0yeNpLixFadL6dz7ej9xW2suPppIO6jA5SYgL6+S42ZlIauCnSQBKFcdP8QRvgDZBZ4A7CmuloRJst7GQzppa+YWR+Zg3V5reV8Ekrkjxhwgd+rMsGahxijY7Juf2zMgLOXwe68y41SGnn+1RwezAhnJgioGiwY2gP7z2m8yNZXhpUiX+KAP2xvYb60wNYOswuqfpya68rSmYT8mQjld1EPR21dBMjRQ8HfUBAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAAIUlqltRlbqiolGETmAUF8AiC008UCUmI+IsnORbHFSaACKW04m1iFH0OlxuAE1ECj1mlTcKb4md6i7n+Fy+fdGXFL73yhlSiBLu7XW5uN1/dAkynA+mXC5BDFijmvkEAgNLKyh40u/U1u75v2SFS+kLyMeqmVxvUHA7qA8VgyHi/FZzXCfEvxK5jye4L8tkAR34x5j5MpPDMfLkwLegUG+ygX+h/f8luKiQAk7eD4C59c/F0PpigvzcMpyg8+SE9loIEuJ9dRaRaTwIzez3QA7PJtrhu9h0TooTtkmF/Zw9HARrO0qXgT8uNtQDcRXZCItt1Qr7cOJyx2IjTFR2rE=-----END CERTIFICATE-----
We recommend you use a random 32 character string for this header. You can use
pwgen utility to generate suitable random strings:
Sec-Client-X509-Cert- prefix is intended to aid debugging.
2. Configure the Connect2id server
Edit the Connect2id server configuration for the client X.509 certificate header:
op.tls.clientX509CertHeader = Sec-Client-X509-Cert-alaeLuL8geiqu3OhOg1Mafa4Ecu9ahsh
Note that the Connect2id server will check if the header name is at least 32 characters long, for the mentioned injection attack prevention. Future versions may also include a randomness check.
Remember to restart your Connect2id server instances for the configuration to take effect.
3. Configure the TLS termination proxy
This configuration is proxy specific. You basically need to setup the TLS proxy to:
Accept self-signed client X.509 certificates;
Remove all HTTP headers with the name used to pass the client certificate to the Connect2id server, in order to block injection attacks;
Insert the PEM encoded certificate into the special HTTP header.
The PEM encoded client certificate must not contain new lines or white space, else processing of the HTTP headers may fail.
Again, remember to sanitise the incoming HTTP headers -- this is super important for security!