Consuming JWT userinfo response
Consuming JWT userinfo response as IBM Verify Identity Access relying party
IBM Verify Identity Access (IVIA) Federation module acts as a OpenID Relying party, it can consume only JSON format userinfo response.
This article goes through steps required for a IVIA Relying party to consume a JWT format userinfo response.
Pre-requisites
- IBM Verify Identity Access configured as OIDC Relying party.
Details required from the OpenID Provider
- .well-known endpoint or userinfo endpoint
- JWT Signing Algorithm
- JWKS URL
- JWT Encryption Algorithm and Key Transport Algorithm
Verify Identity Access Configuration
- Login as admin user to the Verify Identity Access local management interface.
- Navigate to Federation -> Secure Token Service
- Configure a Template with Default JWT Module (Validate Mode) and Default STSUU(Issue Mode).
- Configure an STS Chain with the template created in the previous step. Configure the Lookup tab and Properties tab with JWT Signing and JWT Encryption settings.
- Save and deploy the pending changes.
-
Navigate to Federation -> Mapping rule. Edit the OIDCRP mapping rule and copy the following snippet.
importPackage(Packages.com.tivoli.am.fim.trustserver.sts); importPackage(Packages.com.tivoli.am.fim.trustserver.sts.uuser); importPackage(Packages.com.tivoli.am.fim.trustserver.sts.utilities); importPackage(Packages.com.ibm.security.access.httpclient); importClass(Packages.com.tivoli.am.fim.fedmgr2.trust.util.LocalSTSClient); IDMappingExtUtils.traceString("oidc_rp mapping rule called with stsuu: " + stsuu.toString()); /* * Construct a basic identity made up of iss and sub */ var iss = stsuu.getAttributeContainer().getAttributeValueByName("iss"); var sub = stsuu.getAttributeContainer().getAttributeValueByName("sub"); /* * This code builds a principal name from the iss and sub fields of the id_token. If * this user does not exist in the IVIA registry, either modify to map to a * local user that is in the registry, or change the EAI authentication * settings of the federation runtime to use PAC authentication. To use PAC * authentication, modify the following Federation -> Advanced Configuration: * * poc.signIn.credResponseHeader = am-eai-pac */ stsuu.setPrincipalName(iss + "/" + sub); /* * Attributes from id_token come as attributes. * Copy those attributes that you want to be built into the credential to the AttributeList. * You can add to this list if you know what is in the id_token you expect. * Only those attributes with values are copied. */ var attrNames = [ // these are standard claims "given_name", "family_name", "name", "email", "access_token" ]; var finalAttrs = []; for (var i = 0; i < attrNames.length; i++) { var attr = stsuu.getAttributeContainer().getAttributeByName(attrNames[i]); if (attr != null) { finalAttrs.push(attr); } } stsuu.clearAttributeList(); /* * Add back in the final attributes */ for (var i = 0; i < finalAttrs.length; i++) { stsuu.addAttribute(finalAttrs[i]); } let token = stsuu.getContextAttributes().getAttributeValueByName("access_token"); /* * Also pull these from context attributes (these are not available in the id_token) */ var contextAttrNames = [ "access_token", "expires_in", "scope" ]; for (var i = 0; i < contextAttrNames.length; i++) { var attr = stsuu.getContextAttributes().getAttributeByName(contextAttrNames[i]); if (attr != null) { stsuu.addAttribute(attr); stsuu.getContextAttributes().removeAttribute(attr); } } //IDMappingExtUtils.traceString("oidc_rp mapping rule finished with new stsuu: " + stsuu.toString()); var headers = new Headers(); headers.addHeader("Authorization", "Bearer "+token); var endpoint = null; var httpsTrustStore = "rt_profile_keys"; var clientKeyStore = null; var clientKeyAlias = null; endpoint = "https://www.myidp.ibm.com/isam/sps/oauth/oauth20/userinfo"; /* hr will be a com.ibm.security.access.httpclient.HttpResponse */ IDMappingExtUtils.traceString("endpoint: " + endpoint + " httpsTrustStore: " + httpsTrustStore ); var hr = HttpClientV2.httpGet(endpoint, headers, httpsTrustStore, null, null, clientKeyStore, clientKeyAlias); if(hr.getCode() == 200){ IDMappingExtUtils.traceString(" body" + hr.getBody()); var body = hr.getBody(); var base_token = IDMappingExtUtils.stringToXMLElement('<wss:BinarySecurityToken xmlns:wss="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" wss:EncodingType="http://ibm.com/2004/01/itfim/base64encode" wss:ValueType="urn:com:ibm:JWT">' + body+ '</wss:BinarySecurityToken>'); var res = LocalSTSClient.doRequest("http://schemas.xmlsoap.org/ws/2005/02/trust/Validate", "urn:appliesto", "urn:issuer", base_token, null) var assertionValid = (res.errorMessage == null); if (!assertionValid) { OAuthMappingExtUtils.throwSTSUserMessageException("Invalid Assertion. Authentication failed [" + res.errorMessage + "]."); } var assertion_stsuu = new STSUniversalUser(); assertion_stsuu.fromXML(res.token); IDMappingExtUtils.traceString(" jsonToken" + assertion_stsuu.toString()); var jsonObj = JSON.parse(assertion_stsuu.getContextAttributes().getAttributeValueByName("claim_json")); IDMappingExtUtils.traceString(" json.sub" + jsonObj["sub"]); } -
Navigate to Federation -> Federations. Edit the OpenID Connect Relying Party federation. [block:image]
{
"images": [
{
"image": [
"https://files.readme.io/7a1710a936ee54e93005e987dd85a26e061693f9fa5681b5fd394af347590b7c-federation.png",
"7a1710a936ee54e93005e987dd85a26e061693f9fa5681b5fd394af347590b7c-federation.png",
1648,
700,
"#e2e3e3",
null,
"693f8ae987e9fff75c17ef1f"
]
}
]
}
[/block]
.
* Navigate to Identity Mapping -> Use JavaScript transformation for identity mapping. [block:image]
{
"images": [
{
"image": [
"https://files.readme.io/c4a64b3667abdf100e99eccf26d92a6081b9c1a633d8da78bed6976f8dfe4e6d-federation2.png",
"c4a64b3667abdf100e99eccf26d92a6081b9c1a633d8da78bed6976f8dfe4e6d-federation2.png",
1648,
829,
"#c6c6d1",
null,
"693f8ae9cd9793ced4b7f871"
]
}
]
}
[/block]* Select the identity mapping rule **OIDCRP**. [block:image]{
"images": [
{
"image": [
"https://files.readme.io/d616f24dfbc08a04a69da3cd5691aa8edf7b68f4663a5f8cc59a1b29da11cd04-federation3.png",
"d616f24dfbc08a04a69da3cd5691aa8edf7b68f4663a5f8cc59a1b29da11cd04-federation3.png",
1648,
823,
"#efefef",
null,
"693f8aea2ec185f997f779e8"
]
}
]
}
[/block]* Save and deploy pending changes. -
Navigate to Federation -> Federations. Select the federation and click Partners. [block:image]
{
"images": [
{
"image": [
"https://files.readme.io/435907ea451cb4710e2b6fb165067b60040f0c18a8b0698a5696abc7381a53e6-partner.png",
"435907ea451cb4710e2b6fb165067b60040f0c18a8b0698a5696abc7381a53e6-partner.png",
1648,
700,
"#e2e3e3",
null,
"693f8aea9001f2c55989c341"
]
}
]
}
[/block]* Select the partner and edit. * Navigate to Scope configuration and uncheck Perform userinfo request automatically [block:image]{
"images": [
{
"image": [
"https://files.readme.io/681880c0debacc4c41eef31d264a5d0c501f2c449f1aad2311149a823badfaa6-partner1.png",
"681880c0debacc4c41eef31d264a5d0c501f2c449f1aad2311149a823badfaa6-partner1.png",
1648,
813,
"#1a2ea7",
null,
"693f8aea9001f2c55989c356"
]
}
]
}
[/block]
.
* Save and deploy pending changes.
Updated 12 days ago
