Certificate-bound access tokens

Dealing with compromised Bearer tokens

OAuth Bearer tokens are used to access protected resources. They are often used to offer sufficient proof to gain access through the use of scopes or finer-grained details in claims, such as authorization_details (Ref: Rich authorization request). This implies that if an unauthorized actor or system gains access to the Bearer token, they can impersonate the user (or system) and get access to the protected resources. There is no way for a resource server to verify that the sender of the Bearer token is legitimate as long as the token is valid.

A solution is to require the use of Proof-of-Possession Tokens that allows a resource server to verify that the Bearer token is being used by a legitimate client. Certificate-bound access tokens are an example of such tokens.

Certificate-bound or Mutual TLS sender-constrained tokens

Certificate-bound access tokens (sometimes also called Mutual TLS sender-constrained tokens) are bound to the underlying mutual TLS connection between the client and the authorization server (like IBM Security Verify). As part of the OAuth 2.0 grant flow, the underlying connection to the token issuance endpoint is secured using mutual TLS. After a successful transport connection is established, the authorization server encodes the thumbprint of the client certificate and stores this in the authorization grant as part of the "confirmation" claim (cnf). This is then made available as part of token introspection response or embedded within a JWT-formatted access token.

The process is illustrated in the flow below. The application (client) initiates an authorization code flow via the browser to obtain an authorization code and then uses that to request for a token.

2918

The following shows an example of an introspection response. The payload includes the confirmation claim.

{
  "active": true,
  "aud": [
    "6344df61-2fee-4429-9557-6b2979a138f7"
  ],
  "client_id": "6344df61-2fee-4429-9557-6b2979a138f7",
  "cnf": {
    "x5t#S256": "Rvc6LtXrtcjJsf0zZacc2MCETnUOWu59cz3H4ohh4-o"
  },
  "exp": 1679717794,
  "grant_id": "8fa20f0e-d98f-4659-8a55-bfa46293d7ac",
  "iat": 1679714193,
  "iss": "https://harbinger.verify.ibm.com/oauth2",
  "nbf": 1679714193,
  "scope": "profile openid",
  "sub": "671000CCGT",
  "token_type": "bearer",
  "token_use": "access_token"
}

Now that the token has been issued, it can be used as a Bearer token to access a protected resource.

Using the sender-constrained token

When the client accesses a protected resource API authorized using the Bearer token, it is now required to use the same client certificate to establish a mutual TLS connection. This enforcement occurs at the resource endpoint (or at the API gateway/proxy, where the TLS connection terminates).

2197

The API (or gateway) introspects the token (if it is not a JWT) and does the following:

  1. Generate the encoded thumbprint: The value is a Base64URL-encoded RFC4648 SHA-256 hash (a.k.a., thumbprint, fingerprint, or digest) of the DER encoding of the X.509 certificate.
// Importing crypto module
const {X509Certificate,createHash} = require('crypto');

// PEM-encoded X.509 certificate, usually extracted from the request object
const pem = '...';

// Getting object of a PEM-encoded X.509 Certificate. 
const x509 = new X509Certificate(pem);

// Compute the thumbprint hash
const thumbprintHash = createHash('sha256').update(x509.raw).digest('base64url');
  1. Introspect the Bearer token or validate the JWT (if formatted in this manner).

  2. Extract the cnf.x5t#s256 value and compare with the thumbprint hash computed in step 1. If they match, perform other authorization decisions, such as comparing scopes granted, etc.

Conclusion

Certificate-bound access tokens add a strong layer of assurance by requiring proof of possession through the use of the certificate used to establish a Mutual TLS connection. They mitigate the misuse of tokens by unauthorized parties. Unauthorized parties include bad actors, resource APIs with access to the token that re-use it to access other endpoints, etc. Mutual TLS client authentication and certificate-bound access tokens together are suitable for environments with higher security requirements, such as Open Banking ecosystems.

Applications clients defined on IBM Security Verify through OAuth 2.0 Dynamic Client Registration or the admin console can be configured to require Mutual TLS to issue certificate-bound access tokens. See more details in the OpenID Connect application connector.

💎

Vivek Shankar, IBM Security