1.2.2. Mutual TLS token binding
RFC8705 describes a mechanism for binding access tokens to Mutual TLS (mTLS) client authentication certificates. It requires that a client certificate’s SHA256 thumbprint matches a JWT token or token introspection confirmation x5t#S256 certificate thumbprint.
For example, see JWT Certificate Thumbprint Confirmation Method and Confirmation Method for Token Introspection sections of RFC8705.
MTLS token binding supports a holder of key concept, and can be used to confirm that the current access token was issued to the current authenticated client who presents this token.
When you use both mTLS and OIDC bearer authentication mechanisms, you can enforce that the access tokens must be certificate bound with a single property, after configuring your Quarkus endpoint and Quarkus OIDC to require the use of mTLS.
For example:
quarkus.oidc.auth-server-url=${your_oidc_provider_url}
quarkus.oidc.token.binding.certificate=true
quarkus.oidc.tls.tls-configuration-name=oidc-client-tls
quarkus.tls.oidc-client-tls.key-store.p12.path=target/certificates/oidc-client-keystore.p12
quarkus.tls.oidc-client-tls.key-store.p12.password=password
quarkus.tls.oidc-client-tls.trust-store.p12.path=target/certificates/oidc-client-truststore.p12
quarkus.tls.oidc-client-tls.trust-store.p12.password=password
quarkus.http.tls-configuration-name=oidc-server-mtls
quarkus.tls.oidc-server-mtls.key-store.p12.path=target/certificates/oidc-keystore.p12
quarkus.tls.oidc-server-mtls.key-store.p12.password=password
quarkus.tls.oidc-server-mtls.trust-store.p12.path=target/certificates/oidc-server-truststore.p12
quarkus.tls.oidc-server-mtls.trust-store.p12.password=password
The above configuration is sufficient to require that OIDC bearer tokens are bound to the client certificates.
Next, if you need to access both mTLS and OIDC bearer security identities, consider enabling Inclusive authentication with quarkus.http.auth.inclusive=true.
Now you can access both MTLS and OIDC security identities as follows:
package io.quarkus.it.oidc;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import org.eclipse.microprofile.jwt.JsonWebToken;
import io.quarkus.security.Authenticated;
import io.quarkus.security.credential.CertificateCredential;
import io.quarkus.security.identity.SecurityIdentity;
@Path("/service")
@Authenticated
public class OidcMtlsEndpoint {
@Inject
SecurityIdentity mtlsIdentity;
@Inject
JsonWebToken oidcAccessToken;
@GET
public String getIdentities() {
var cred = identity.getCredential(CertificateCredential.class).getCertificate();
return "Identities: " + cred.getSubjectX500Principal().getName().split(",")[0]
+ ", " + accessToken.getName();
}
}