IBM Verify Identity Access does not support
"s_hash" out-of-the-box. However, it can be calculated and added as claims by adding the following
code snippet to pre_token mapping rules. See https://www.ibm.com/blogs/security-identity-access/openbanking-the-state-hash-claim/ for
more
information./*
FAPI - S_HASH
*/
importClass(Packages.java.util.Base64);
var request_type = null;
var grant_type = null;
var response_type = null;
// The request type - if none available assume 'resource'
var tmp = stsuu.getContextAttributes().getAttributeValuesByNameAndType("request_type", "urn:ibm:names:ITFIM:oauth:request");
if (tmp != null && tmp.length > 0) {
request_type = tmp[0];
} else {
request_type = "resource";
}
// The grant type
tmp = stsuu.getContextAttributes().getAttributeValuesByNameAndType("grant_type", "urn:ibm:names:ITFIM:oauth:body:param");
if (tmp != null && tmp.length > 0) {
grant_type = tmp[0];
}
// The response type
tmp = stsuu.getContextAttributes().getAttributeValuesByName("response_type");
if (tmp != null && tmp.length > 0) {
response_type = tmp[0];
}
var state = null;
if (request_type == "authorization" && response_type != null && response_type.indexOf("id_token") > -1) {
// When id_token to be produced at /authorize
state = stsuu.getContextAttributes().getAttributeValueByName("state");
} else if (request_type == "access_token" && grant_type == "authorization_code") {
// When id_token to be produced at /token
var code = stsuu.getContextAttributes()
.getAttributeValueByNameAndType("code", "urn:ibm:names:ITFIM:oauth:body:param");
var token = OAuthMappingExtUtils.getToken(code);
if (token != null) {
state = OAuthMappingExtUtils.getAssociation(token.getStateId(), "state");
}
}
if (state != null) {
// Need to hash based on algorithm
// The hash algorithm to use is dictated by the signing algorithm of JWT
var alg = stsuu.getContextAttributes()
.getAttributeValueByNameAndType("signing.alg", "urn:ibm:oidc10:jwt:create");
// For now only SHA-256 and SHA-512 are supported natively by ISAM.
// Consider using KJUR or similar if SHA384 is needed.
var hash = null;
if (alg != null) {
if (alg.endsWith("256")) {
hash = OAuthMappingExtUtils.SHA256Sum(state);
} else if (alg.endsWith("384")) {
hash = null; // Not supported!
} else if (alg.endsWith("512")) {
hash = OAuthMappingExtUtils.SHA512Sum(state);
}
}
if (hash != null && hash.length > 0) {
var state_hash = Base64.getUrlEncoder().withoutPadding().encodeToString(hash.splice(0, hash.length/2));
var attr = new com.tivoli.am.fim.trustserver.sts.uuser.Attribute("s_hash", "urn:ibm:jwt:claim", state_hash);
stsuu.addAttribute(attr);
}
}
/*
FAPI - S_HASH
*/
As part of FAPI conformance, response type code is not permitted. Therefore incoming request
with response type code throws an unsupported error page. This can be achieved by including the
following snippet in pre_token mapping
rules./*Disallow Code Flow*/
var response_type= null;
if (request_type="authorization"){
temp_attr = stsuu.getContextAttributes().getAttributeValuesByNameAndType("response_type", "urn:ibm:names:ITFIM:oauth:query:param");
if (temp_attr != null && temp_attr.length > 0) {
response_type = temp_attr[0];
} else {
temp_attr = stsuu.getContextAttributes().getAttributeValuesByNameAndType("response_type", "urn:ibm:names:ITFIM:oauth:body:param");
if (temp_attr != null && temp_attr.length > 0) {
response_type = temp_attr[0];
IDMappingExtUtils.traceString("response_type :::"+response_type );
}
}
if ("code" == response_type) {
//IDMappingExtUtils.throwSTSException("Code Flow Disallowed");
OAuthMappingExtUtils.throwSTSCustomUserPageException("Unsupported response type code.",400,"invalid_request");
}
}
/*Disallow Code Flow*/
As part of FAPI conformance, only claims passed in request object is used and returned. This
rule ensures that when state is passed in request parameter, the appliance does not take it into
consideration during the flow by removing it from the stsuu in the pre_token mapping
rule./*Disallow State in Request Param*/
var reqParam_state = stsuu.getContextAttributes().getAttributeValueByNameAndType("state","urn:ibm:names:ITFIM:oauth:query:param");
if (reqParam_state != null){
var x = stsuu.getContextAttributes().removeAttributeByNameAndType("state","urn:ibm:names:ITFIM:oauth:query:param");
}
/*Disallow State in Request Param*/