Based in Melbourne, Australia.

Developer
Life

Configuring ISAM as a Relying Party using Private Key JWT - OIDC

Configuring ISAM as a Relying Party using Private Key JWT - OIDC

Contents

Overview

In a previous blog post I talked about ISAM (Verify Access) acting as the OpenID Provider (OP) and how it's possible to return custom OAuth tokens to the Relying Partner (RP).

But what if ISAM is acting as the RP?
It's possible to configure ISAM to create and sign a private_key_jwt that is then passed to the Identity Provider (IDP) on the /token request. The IDP is then able to validate the token against a public JWKS endpoint exposed by ISAM, i.e. via a static file or using the same JWKS endpoint for OAuth API Definitions.

Advanced Configuration Mapping Rule

When ISAM acts as the RP, the Federation module allows us to configure a partner with the option to "Use JavaScript for advanced configuration" on the "Advanced Configuration" step. This allows us to select a mapping-rule that can then use customize the request for us.

info

When creating the mapping-rule, ensure that OIDC is selected as the category.

The below example customizes the /token request to the OP by replacing the client_assertion with a jwt-bearer (private_key_jwt) client_assertion_type. This token is signed with a private key, which the OP can validate using the public key exposed on a JWKS endpoint that ISAM makes available.

note

The example uses the token.issue() and token.callSts() functions that has been defined here. These assume you have already configured a STS to issue a token.

const IDP_TOKEN_LIFETIME = 300; // 5 minutes
const NOT_BEFORE = 300; // 5 minutes
operation = stsuu.getContextAttributes().getAttributeValueByNameAndType("operation", "urn:ibm:SAM:oidc:rp:operation");

if (operation = "token"){
clientId = "" + (stsuu.getContextAttributes().getAttributeByNameAndType("client_id", "urn:ibm:SAM:oidc:rp:meta")).getValues()[0];
tokenUrl = "" + (stsuu.getContextAttributes().getAttributeByNameAndType("token_url", "urn:ibm:SAM:oidc:rp:meta")).getValues()[0];

// Create client assertion token.
let RS256 = {}
RS256.keystore = "jwtKeyStore"; // SSL Certificate Database.
RS256.key = "jwtKey"; // Signing Certificate.

now = new Date();
claims = {};
claims.iat = Math.floor(now.getTime() / 1000);
claims.exp = Math.floor((now.getTime() + (1 * IDP_TOKEN_LIFETIME * 1000)) / 1000);
claims.nbf = Math.floor(now.getTime() / 1000 - NOT_BEFORE);
claims.sub = clientId;
claims.jti = "" + java.util.UUID.randomUUID();
claims.iss = clientId;
claims.aud = tokenUrl;

idpToken = token.issue(claims, RS256);

if (idpToken) {
var tokenArr = java.lang.reflect.Array.newInstance(java.lang.String, 1);
tokenArr[0] = idpToken;

// Add client assertion token to STSUU.
var clientAssertion = new com.tivoli.am.fim.trustserver.sts.uuser.Attribute("client_assertion", "urn:ibm:SAM:oidc:rp:token:req:param", tokenArr);
stsuu.addContextAttribute(clientAssertion);
var clientAssertionType = new com.tivoli.am.fim.trustserver.sts.uuser.Attribute("client_assertion_type", "urn:ibm:SAM:oidc:rp:token:req:param", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer");
stsuu.addContextAttribute(clientAssertionType);
} else {
IDMappingExtUtils.traceString("Unable to create client assertion token.");
}
}

Configuring the Federation Partner

There are three key configuration options needed when configuring the federation partner (OP).

  1. The first is on the "Client Credentials" step, here we want to leave the client secret field empty. Adding a secret will result in it being passed in the request to the OP's /token endpoint.

  2. The second, which I mentioned above, is by selecting the OIDC mapping rule in the "Advanced Configuration" step. Select the option to "Use JavaScript for advanced configuration" on this step.

  3. And lastly, which is in the "Scopes" section of creating a new client, is to set the Token Endpoint Authentication Method to client_secret_post. This will allow us to manipulate the /token request to the OP and pass in the Private Key JWT (signed token).

Here are some useful links you can checkout for additional information.

OIDC Discovery Endpoint - Configuring .well-known in ISAM/ISVA

OIDC Discovery Endpoint - Configuring .well-known in ISAM/ISVA

Setting SameSite and Other Cookie Attributes using WebSEAL

Setting SameSite and Other Cookie Attributes using WebSEAL