Table of Contents

Mutual TLS (Client Certificate Authentication)

Overview

This guide provides a detailed walkthrough for configuring PhenixID Authentication Services (PAS) to use SAML 2.0 or OIDC/oAuth with TLS/SSL Client Certificate Authentication. This setup enables strong, certificate-based authentication for accessing federated services, leveraging client certificates like SITHS or EFOS for authentication.

Certificate infrastructure and reverse proxy

  • Create a JKS File: Generate a Java KeyStore (JKS) file and import the trusted CA certificates. Save the JKS file in the <phenixid_server>/config directory, noting both the file path and password.
  • Set Up a Frontend HTTPS Server: Install and configure a frontend HTTPS server to handle SSL termination. This server should forward client certificate data to the backend PhenixID Authentication Services (PAS) server.
Note

Communication between the frontend server, load balancer (LB), proxy, and PAS backend can be encrypted, though the example below assumes unencrypted communication.

Reference Documentation:

Example configuration:

Apache Configuration (sample http-ssl.conf):

ProxyPass / http://192.168.1.100/
ProxyPassReverse / http://192.168.1.100/
<Location /authentication/saml/idp/urls/siths>
SSLVerifyClient require
SSLVerifyDepth 10
# initialize the SSL headers to a blank value to avoid http header forgeries
RequestHeader set SSL_CLIENT_CERT ""
RequestHeader set SSL_CLIENT_VERIFY "
# add whatever SSL_* variables needed to pass to web application
RequestHeader set SSL_CLIENT_CERT "%{SSL_CLIENT_CERT}s"
RequestHeader set SSL_CLIENT_VERIFY "%{SSL_CLIENT_VERIFY}s"
RequestHeader add X-Forwarded-Scheme https
</Location>

Configure DynamicAuthenticator for mtls

Add a DynamicAuthenticator with the following configuration:

{
  "id" : "mtlstest",
  "alias" : "mtls",
  "name" : "DynamicAuthenticator",
  "configuration" : {
    "pipeID" : "mtls-pipe",
    "textEntryParameters" : [ ],
    "setSSOParameters" : "true",
    "shouldReroute" : "true",
    "rerouteUrlBase" : "https://yourbaseurl.se",
    "rerouteUrlSuffix" : "mtls",
    "userIdentifierAttribute" : "sAMAccountName"
  }
}

Set this authenticator as entrypoint for your OP, IdP or Internal endpoint.

Here’s an example of how the mtls-pipe configuration might look; please note that it will vary based on your specific use case:

{
  "id": "mtls-pipe",
  "description": "Pipe performing mutual TLS authentication",
  "enabled": "true",
  "valves": [{
   "name": "CertificateExtractorValve",
   "enabled": "true",
   "config": {
    "cert": "{{request.SSL_CLIENT_CERT}}"
   }
  },{
   "name": "PropertyAddValve",
   "enabled": "true",
   "config": {
    "name": "shouldRemove",
    "value": "true"
   }
  },{
   "name": "CertificateValidatorValve",
   "enabled": "true",
   "config": {
    "cert": "{{request.SSL_CLIENT_CERT}}",
    "trust_store_path": "/config/trust.jks",
    "trust_store_password": "{enc}v9nwPLvpcwre9Bvoy/UxdKn2B6r8kHIErGB6AD30hEE=",
    "trust_store_type": "JKS"
   }
  },{
   "name": "FlowFailValve",
   "enabled": "true",
   "config": {
    "message": "guides.authentication.common.failed_authentication",
    "exec_if_expr": "!flow.firstItem().getPropertyValue('cert_status', 'BAD').equalsIgnoreCase('GOOD')"
   }
  },{
   "name": "LDAPSearchValve",
   "enabled": "true",
   "config": {
    "connection_ref": "<your connection_ref>",
    "base_dn": [
     "DC=example,DC=com"
    ],
    "scope": "SUB",
    "size_limit": "0",
    "filter_template": "serialNumber={{item.cert_serial}}",
    "attributes": "*",
    "escape": "all"
   }
  },{
   "name": "ItemRemoveValve",
   "enabled": "true",
   "config": {
    "item_include_expr": "item.getPropertyValue('shouldRemove', 'false').equals('true')"
   }
  },{
   "name": "FlowFailValve",
   "enabled": "true",
   "config": {
    "message": "guides.authentication.common.failed_authentication",
    "exec_if_expr": "flow.isEmpty()"
   }
  }]
 }

Note that you could also do CRL and/or OSCP verification of the certificate, please se dokumentation for CertificateValidatorValve

Steps to Verify mTLS Client Certificate Authentication Configuration

Test SSL Termination and Certificate Prompt:

Access the configured URI (e.g., https://front-end-domain/authentication/saml/idp/login) and confirm that:

  • front-end server prompts for a client certificate.
  • Verify that the front-end server forwards the SSL headers to PAS.

Check PAS Logs for Certificate Extraction and Validation:

  • Ensure that the CertificateExtractorValve in PAS successfully extracts the client certificate.
  • Confirm that the CertificateValidatorValve validates the certificate against the JKS trust store without errors.

Verify LDAP Lookup:

  • Check that the LDAPSearchValve performs a lookup using the certificate’s attributes and retrieves the expected user record.

Test Authentication Success and Failure:

  • Complete a successful authentication flow and verify that PAS establishes a session with the correct user attributes.
  • Attempt access with an invalid certificate to ensure PAS logs the appropriate error and denies access.

These steps verify that SSL termination, certificate validation, and user authentication are correctly configu red in your mTLS setup with PAS.