Configuring ISAM as a Relying Party using Private Key JWT - OIDC
Contents
- Overview
- Advanced Configuration Mapping Rule
- Configuring the Federation Partner
- Additional Information/Links
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.
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.
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).
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.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.
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).
Additional Information/Links
Here are some useful links you can checkout for additional information.