Connect2id server 11.0: PKI mTLS client authentication, JARM, client secret management updates

The first Connect2id server release in 2021 is also a major one, covering PKI client authentication and JARM from the FAPI security profile, and also providing new client secret management functionality for those OAuth 2.0 clients that still rely non-private key authentication when obtaining their tokens.

PKI mutual TLS client authentication

In HTTPS the server presents an X.509 certificate to let the client verify its identity. During the TLS handshake in HTTPS the client has the option to also submit a certificate (or multiple certificates). If client and server accept the certificate of the other this results in mutual TLS authentication (mTLS).

Mutual TLS has been a standard method for authenticating clients in web services or users in web applications. In 2020 it was also officially adopted in OAuth 2.0, with the publication of the OAuth 2.0 mTLS profile for client authentication and certificate bound access tokens (RFC 8705).

The mTLS profile specifies two variants of client authentication with a certificate:

  • self_signed_tls_client_auth -- Lightweight method that doesn't rely on a certificate authority (CA) participating in a public key infrastructure (PKI), but on simple public key registration instead.

    The client generates an RSA or EC key pair and creates a simple X.509 certificate for the public key signed with the private one (self-signed certificate). The public key is then registered with the server, in JWK format. In token and other requests the server validates the client certificate by simply checking the certificate public key against the one previously registered for the client. If they match the request is allowed to proceed, if not the response is a 401 Unauthorized error code.

    This method has been supported since Connect2id server 6.12, released in August 2017.

  • tls_client_auth -- The client certificate is validated for being issued by a trusted CA, according to the standard certificate chain validation procedure from X.509 PKI.

    This method becomes supported now in Connect2id server 11.0.

When a client is being registered for PKI client authentication, besides specifying tls_client_auth as the authentication method, the expected certificate subject must also be specified, so that the Connect2id server can link the client_id to it.

POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json

{
  "redirect_uris"              : [ "https://client.example.org/callback" ],
  "token_endpoint_auth_method" : "tls_client_auth",
  "tls_client_auth_subject_dn" : "cn=MyApp,ou=clients,dc=example,dc=org"
}

More information about registering clients for mTLS is available in the registration how-to.

To handle client certificates, self-signed or CA-issued, the HTTPS network point that terminates the TLS for the Connect2id server must be appropriately configured. Due to limitations of popular TLS termination proxy software, such as Nginx and Apache HTTPd, it's not possible to have proper validation of CA-issued client certificates while also accepting certificates that are self-signed. Because of that, and to prevent configuration errors that may compromise security, the Connect2id server op.token.authMethods configuration for setting the enabled methods can either include tls_client_auth or self_signed_tls_client_auth, but not both simultaneously. If there is demand to support both methods in a OAuth 2.0 server deployment we did some initial investigation how to achieve that, by redesigning the modules in Nginx and Apache HTTPd responsible for the client certificate validation.

Note, the access tokens issued to a client authenticated with mTLS will be sender-constrained. When introspected by the resource server they will also contain a thumbprint (SHA-256 hash) of the client certificate in cnf -> x5t#S256:

{
  "iss": "https://demo.c2id.com",
  "sub": "[email protected]",
  "exp": 1493726400,
  "nbf": 1493722800,
  "cnf": {
           "x5t#S256": "bwcK0esc3ACC3DB2Y5_lESsXE8o9ltc05O89jdN-dg2"
         }
}

If the resource server is going to receive such tokens it can be configured to require clients to present their client certificate in every HTTPS request. By hashing the received certificate and comparing it to the thumbprint in the access token the resource server receives strong assurance that it's being called by the legitimate client to which the Connect2id server issued the token, and not some party that may have obtained a leaked or stolen token. The bearer property of regular OAuth 2.0 tokens thus no longer holds, because the token is now cryptographically bound to the client's certificate as well.

To access the resource the client thus needs to possess:

  1. The access token;
  2. The client certificate used at the token endpoint;
  3. The private key for the certificate, which may be kept in a HSM or other secure storage preventing extraction.

The mod_oauth2 for Apache HTTPd has recently introduced support for validating client certificate bound access tokens according to RFC 8705. There are chances its sister ngx_oauth2_module might add that as well. The two modules support introspection of self-contained (JWT signed by the Connect2id server) as well as identifier-based access tokens (with a call to the introspection endpoint). Commercial support from the maintainer for those OAuth modules can be purchased through ZmartZone.

JARM

The OAuth 2.0 extension for JWT-secured authorisation responses (JARM) was developed in the FAPI working group, to give authorisation responses extra security and a counter-measure against a class of attacks called mix-up attacks, and thus a stronger guarantee that the authorisation code is coming from the legitimate OAuth 2.0 server.

Prior to JARM the alternative was to use the response_type=code id_token parameter, causing the server to issue an ID token, which acts as a detached signature of the code by means of the c_hash JWT claim. To cover the state parameter FAPI introduced the new s_hash ID token claim.

A third "cheaper" alternative to guard against mix-up attacks, which doesn't use cryptography, is to return the OAuth 2.0 server identity (iss) in the authorisation response, as described in the recent draft-ietf-oauth-iss-auth-resp-00, supported by the Connect2id server since v10.2.

JARM greatly simplifies things for FAPI compliant applications and does away with the need to return an ID token in the front-channel.

A client can trigger JARM by including the response_mode=jwt parameter in the authorisation request:

https://demo.c2id.com/c2id-login?
 response_type=code
 &scope=openid%20email
 &client_id=123
 &state=g75qdPutq9MVsJVo6r1Z2P1exuXLNrM2-53Dcumth_w
 &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
 &response_mode=jwt

The Connect2id server will return the usual authorisation response parameters, but they will be packaged into a JWT signed with the RS256 JWS algorithm (the default algorithm for JARM).

https://client.example.org/cb?
 response=eyJraWQiOiJDWHVwIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwOlwvXC8xMjcuMC
 4wLjE6ODA4MFwvYzJpZCIsImF1ZCI6IjAwMDEyMyIsImNvZGUiOiJsQkRCOTFNVlEwZFE5aVRlZDFQ
 SFR3LjlaMWJsSmZnTlNUcHh0Z3dxT05aRnciLCJzdGF0ZSI6Imc3NXFkUHV0cTlNVnNKVm82cjFaMl
 AxZXh1WExOck0yLTUzRGN1bXRoX3ciLCJleHAiOjE2MTMwNTgzNjh9.GRDq1--nDFhI6XwaXSBkof4
 IkneTQZlEacMwtRf2_cs_LvK1H3JUKeJj-jLzi9lShL2eS8mghtdDj7YFbHXRRhf_Kh1Nx9GRHYOfJ
 yuk4hY5chYgm2C3Fr7DNfPTHEhjrAlgLLPAsihio4VBefI_BYNTWr85fZqJaohMeB85ACGvkjObPh0
 qKX9a7aa4sBHfGLYyRwiGtkpDil0opeHzr0N37jhLYcnFhFYOZxgQNKBp5LK_dNWM2XJPqvf9SJwoJ
 0_fh_dphG0831TZgHxlz8g6WBwPPpPZFbRiSkhGvCjO2DMmdOutjA6T6TlOnjNNCt4xpk5J_SXyAfy
 2t1Za4A

Example JWT header, indicating the ID of the Connect2id server RSA key used to sign the JWT:

{
  "kid" : "CXup",
  "alg" : "RS256"
}

Example JWT claims, containing the mandatory iss, aud and exp in JARM, plus the usual authorisation response parameters:

{
  "aud"   : "000123",
  "code"  : "lBDB91MVQ0dQ9iTed1PHTw.9Z1blJfgNSTpxtgwqONZFw",
  "iss"   : "https://demo.c2id.com",
  "state" : "g75qdPutq9MVsJVo6r1Z2P1exuXLNrM2-53Dcumth_w",
  "exp"   : 1613058368
}

The client can be registered for a different JWS algorithm for JARM, or even to have the JWT additionally encrypted. If the client is explicitly registered for a JARM JWS algorithm all responses to it will be returned in a JWT, regardless of the requested response_mode.

The exact set of supported JWS and JWE algorithms can be configured and will be advertised in the usual place, the Connect2id server metadata.

If you use the OAuth 2.0 / OpenID Connect SDK for your client applications we have examples how to validate and process authorisation responses with JARM.

Client secret store codec

A new plugin interface (SPI) is made available for applying encryption or hashing of client secrets before committing them to the database.

The codec can also be used to import client secrets with custom encodings, such as BCrypt, when migrating OAuth 2.0 clients to the Connect2id server.

A future version of the Connect2id server may add a default encryption codec for the client secrets.

Seamless client secret rollover

When updating a client's registration where a client_secret was issued, the secret may be refreshed as well. For a high traffic client this may mean a temporary rejection of requests to the token endpoint, before the new secret value gets applied on the client-side.

Starting with this release the Connect2id server will provide a time window of 30 minutes during which the previous client_secret value will continue to be accepted in all places where it's required.

Upgrading

Database

The database schemas were updated to support the new client metadata fields for PKI client authentication and JARM.

If you use an RDBMS backend database, such as MySQL, the Connect2id server will automatically add the new required table columns when a instance with v11.0 starts up.

If you use an LDAP backend, check the instruction in the release notes below for how to upgrade the schema.

If you use DynamoDB, which is essentially schema-less, nothing is required. This also applies to deployments using Redis as cache / object store.

OAuth 2.0 / OpenID Connect SDK

The underlying OpenID Connect SDK and the Nimbus JOSE+JWT library were upgraded to new major versions.

If you have devised your own SPI plugins it's recommended that you rebuild them against the new dependencies, and update the code if necessary. You can find more information the release notes below and in our blog post.

Download

Standard Connect2id server edition

Apache Tomcat package with Connect2id server 11.0: Connect2id-server.zip

SHA-256: 42d32a7349aaa34ec78a8f02fe1f4540134ec54fcd78af9fcd71bff0256e4d8c

Connect2id server 11.0 WAR package: c2id.war

SHA-256: 70859d52cef5e15862d6ae1b86352590b0be548bccdef643658d43050cc63adc

Multi-tenant edition

Apache Tomcat package with Connect2id server 11.0: Connect2id-server-mt.zip

SHA-256: 6b8f36887d1661cee1bd568362572fd94c12352c62f8c579aed6f6d45802b41c

Connect2id server 11.0 WAR package: c2id-multi-tenant.war

SHA-256: b79ca2625f13a7c68ede000e37f50329935e64273091b2e586935d86049b8771

Questions?

Contact Connect2id support.


Release notes

11.0 (2021-02-09)

Summary

  • Supports OAuth 2.0 client authentication with a client X.509 certificate issued by a trusted Certificate Authority (CA), as specified in OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens (RFC 8705), section 2.2.

    When registering a client for the "tls_client_auth" method the "tls_client_auth_subject_dn" metadata parameter must be set to the expected subject distinguished name (DN) of the client certificate. Other client metadata parameters defined in RFC 8705 for identifying the certificate subject are not presently supported.

    The client certificate is to be validated at a terminating TLS reverse proxy which must pass a successfully validated certificate to the Connect2id server in the HTTP security header set by the existing "op.tls.clientX509CertHeader" configuration property.

    Note, due to limitations of the commonly available TLS termination software, configuring simultaneous validation of CA-issued client certificates as well as acceptance of self-signed client certificates is normally not possible. Because of that a Connect2id server deployment can be configured to support either "tls_client_auth" or "self_signed_tls_client_auth" from RFC 8705, but not both.

  • Supports the JWT-secured authorisation response mode (JARM). An OAuth 2.0 client can utilise JARM to receive signed and optionally encrypted authorisation responses. All standard response modes in JARM are supported: "query.jwt", "fragment.jwt", "form_post.jwt" and the "jwt" shorthand.

    A client can request an RS256 signed authorisation response by setting the optional "response_mode" authorisation request parameter to "jwt" or a more specific value, such as "query.jwt". If the client is registered with an "authorization_signed_response_alg" metadata parameter all authorisation responses will be signed with the specified JWS algorithm, even if there is no explicit request for JARM in the "response_mode" authorisation request parameter. If the client is also registered with the "authorization_encrypted_response_alg" and "authorization_encrypted_response_enc" metadata parameters the signed authorisation response will be additionally encrypted.

    See Financial-grade API: JWT Secured Authorization Response Mode for OAuth 2.0 (JARM), draft 02 from 2018-10-17.

  • Adds a codec plugin interface (SPI) for persisting client secrets in a encrypted, hashed or otherwise encoded form. The codec interface also enables import of OAuth 2.0 client registrations via the custom "preferred_client_secret" metadata field where the secret is passed in a hashed form, for example using the BCrypt, SCrypt, Argon2 or another hash algorithm.

  • Supports seamless "client_secret" rollover. After an update of a client's secret via the client registration endpoint the previous secret will remain valid for client authentication purposes for a period of 30 minutes. HMAC-secured ID tokens hints ("id_token_hint" with JWS HS256, HS384 or HS512) will also be checked against the previous replaced "client_secret".

  • Upgrades the OAuth 2.0 / OpenID Connect SDK to major release 9.x which in turn upgrades to Nimbus JOSE+JWT 9.x. The objective of the Nimbus JOSE+JWT 9.0 release was to shade the JSON Smart dependency and make it optional. Plugged SPI implementations that rely on Nimbus JOSE+JWT 8.x and earlier interfaces and classes may be affected and should be recompiled / rebuilt and if necessary, modified.

  • Upgrades the schemas of backend RDBMS and LDAPv3 stores to support the client metadata fields required for "tls_client_auth" and JARM. See the configuration section below for more information.

Configuration

  • /WEB-INF/oidProvider.properties

    • op.authz.responseModes -- Adds support for the "query.jwt", "fragment.jwt", "form_post.jwt" and "jwt" (shorthand) response modes from JARM.

    • op.authz.responseJWSAlgs -- New configuration property, sets the accepted JWS algorithms for signed OAuth 2.0 authorisation responses (JARM). Supported JWS algorithms: HS256, HS384, HS512, RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384 and ES512.

    • op.authz.responseJWEAlgs -- New configuration property, sets the accepted JWE algorithms for encrypted OAuth 2.0 authorisation responses (JARM). Note, encryption is always applied after signing. Supported JWE algorithms: RSA-OAEP-256, RSA-OAEP (use no longer recommended), RSA1_5 (use no longer recommended), ECDH-ES, ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW and dir.

    • op.authz.responseJWEEncs -- New configuration property, sets the accepted JWE content encryption methods for encrypted OAuth 2.0 authorisation responses (JARM). Supported JWE methods: A128CBC-HS256, A192CBC-HS384, A256CBC-HS512, A128GCM, A192GCM and A256GCM

    • op.token.authMethods -- Adds support for "tls_client_auth", PKI client authentication where the client must include a CA-issued client X.509 certificate in requests. Note, the "tls_client_auth" and "self_signed_tls_client_auth" methods cannot be enabled simultaneously.

    • op.tls.clientX509CertHeader -- The existing Connect2id server configuration property for specifying an HTTP header name for receiving validated client X.509 certificates from the TLS proxy will also apply to the new "tls_client_auth" method. The configuration property was originally introduced in Connect2id server 6.12 to facilitate the "self_signed_tls_client_auth" method.

  • /WEB-INF/infinispan-*-{mysql|postgres95|sqlserver|h2}.xml

    • Adds new "tls_client_auth_subject_dn", "tls_client_auth_san_dns", "tls_client_auth_san_uri", "tls_client_auth_san_ip", "tls_client_auth_san_email", "authorization_signed_response_alg", "authorization_encrypted_response_alg" and "authorization_encrypted_response_enc" columns to the "clients" table. In existing Connect2id server deployments with an SQL RDBMS the server will automatically add the new columns (with an appropriate default value) on startup.
  • /WEB-INF/infinispan-*-ldap.xml

    • Adds new "oauthTLSClientAuthSubjectDN", "oauthTLSClientAuthSANDNS", "oauthTLSClientAuthSANURI", "oauthTLSClientAuthSANIP", "oauthTLSClientAuthSANEmail", "oauthAuthorizationResponseJWSAlg", "oauthAuthorizationResponseJWEAlg" and "oauthAuthorizationResponseJWEEnc" attributes to the "oauthClientMetadata" object class. Connect2id server deployments with an LDAP v3 backend database (such as OpenLDAP or OpenDJ) need to update the LDAP schema manually to version 1.15 see https://bitbucket.org/connect2id/server-ldap-schemas/src/1.15/ , the OpenLDAP schema diff https://bitbucket.org/connect2id/server-ldap-schemas/diff/ src/main/resources/oidc-client-schema-openldap.ldif?at=1.15 &diff1=c8ba0c6a092c409e43b9efe7360cd76a460a2b95 &diff2=cb3676cefe8bbccbcdb4352cc707a53ef53ae28a and the OpenDJ schema diff https://bitbucket.org/connect2id/server-ldap-schemas/diff/ src/main/resources/oidc-client-schema-opendj.ldif?at=1.15 &diff1=c8ba0c6a092c409e43b9efe7360cd76a460a2b95 &diff2=cb3676cefe8bbccbcdb4352cc707a53ef53ae28a
  • /WEB-INF/oidcClientInfoMap.json -- File removed, switched to programmatic configuration.

Web API

  • /.well-known/openid-configuration, /.well-known/oauth-authorization-server

    • response_modes_supported -- Will include the supported OAuth 2.0 response modes for JARM if enabled -- "query.jwt", "fragment.jwt", "form_post.jwt" and "jwt".

    • authorization_signing_alg_values_supported -- New optional JSON array listing the supported JWS algorithms for signed OAuth 2.0 authorisation responses (JARM).

    • authorization_encryption_alg_values_supported -- New optional JSON array listing the supported JWE algorithms for encrypted OAuth 2.0 authorisation responses (JARM).

    • authorization_encryption_enc_values_supported -- New optional JSON array listing the supported JWE content encryption methods for encrypted OAuth 2.0 authorisation responses (JARM).

  • /clients

    • Supports the "authorization_signed_response_alg", "authorization_encrypted_response_alg" and "authorization_encrypted_response_enc" client metadata parameters from JARM.

    • Supports registration of clients for PKI mutual-TLS client authentication ("tls_client_auth") with the "tls_client_auth_subject_dn" metadata parameter used to set the expected subject DN in the client's certificate.

    • Updating a "client_secret" will cause the previous value to remain valid for client authentication purposes for another 30 minutes, to facilitate seamless rollover.

SPI

  • Upgrades the Connect2id server SDK to com.nimbusds:c2id-server-sdk:4.27.1

  • com.nimbusds.openid.connect.provider.spi.secrets.ClientSecretStoreCodec -- New Service Provider Interface (SPI) for encoding OAuth client secrets before persisting them to storage. Can be used to symmetrically encrypt (e.g. with AES) or to hash secrets (e.g. with SCrypt, BCrypt, Argon2) before committing them to storage. Note, OAuth clients registered for "client_secret_jwt" authentication where the secret must be available in plaintext to perform HMAC must not be hashed. This also applies to secrets which may otherwise require the plain secret to be available for decoding, for example to facilitate symmetric encryption of ID tokens or UserInfo.

    The supplied SecretCodecContext provides access to the Connect2id server JWK set to retrieve any configured symmetric keys for the client secret encryption, as well as the client metadata to determine the registered client authentication method.

    Implementations must be thread-safe.

Resolved issues

  • The Connect2id server should also include the previous replaced client_secret when validating an id_token_hint secured with JWS HS256, HS384 and HS512 (issue server/12).

  • Adds missing persistence for the "software_version" client metadata field in LDAP stores (iss #623).

  • The Connect2id server must not redirect back to an OAuth 2.0 client with an otherwise redirectable authorisation error if no "redirect_uri" was set in the original plain OAuth 2.0 authorisation request and the client has more than one "redirect_uri" registered (issue server/630).

  • Revises Connect2id server error reporting on invalid a "request_uri" and "request" JWT in a authorisation request. Errors due to the JWT claims including a "sub" (subject) claim that equals the "client_id" will be reported to the client with an "invalid_request" code, instead of resulting in a non-redirecting error. Errors due to a JWT that cannot be decrypted will also be reported to the client with an "invalid_request_object" code, instead of resulting in a non-redirecting error (issue server/631).

  • Caches single-tenant static OP / AS metadata to increase performance (iss server/627).

Dependency changes

  • Upgrades to com.nimbusds:c2id-server-sdk:4.27.1

  • Upgrades to com.nimbusds:oauth2-oidc-sdk:9.1

  • Upgrades to com.nimbusds:nimbus-jose-jwt:9.5

  • Upgrades to com.nimbusds:c2id-server-ldap-schemas:1.15

  • Updates to com.nimbusds:oauth2-authz-store:16.4.2

  • Updates to com.nimbusds:oidc-session-store:14.2.2

  • Updates to OpenSAML 3.4.6.

  • Updates to BouncyCastle 1.68

  • Updates to Infinispan 9.4.21.Final

  • Updates to DropWizard Metrics 4.1.17

  • Updates to org.jooq.pro-java-8:jooq:3.14.2

  • Updates to org.mariadb.jdbc:mariadb-java-client:2.7.1

  • Updates to org.postgresql:postgresql:42.2.18

  • Updates to com.microsoft.sqlserver:mssql-jdbc:8.4.1.jre11

  • Updates to Log4j 2.14.0

  • Updates to commons-io:commons-io:2.8.0

  • Updates to com.amazonaws:aws-java-sdk-bundle:1.11.936