Co-authored by Adrian Rinaldi Sasmita.
When implementing OpenBanking and following the foundation implementers draft , one of the requirements is to include several additional claim values. One of the claim values is s_hash
the goal of this claim is to ensure the id_token
returned in the authorization code flow matches the request to /authorize
triggered by the TPP(Relying party).
Adding a s_hash
claim to ISAM is possible using JavaScript mapping rule. The snippets below show how its possible.
Note: ISAM 9.0.6.0 only natively supports SHA-256 and SHA-512 in mapping rules, if SHA-384 is needed (For RS/ES384 algorithms) using a third party javascript library is needed.
Add this snippet to the post-mapping rule, it saves the ‘state’ value to be used when generating an id_token
in the request to /token
for the authorization code flow.
var request_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";
}
if (request_type == "authorization") {
// store the state value against the grant
var state = stsuu.getContextAttributes().getAttributeValueByName("state");
if (state != null) {
OAuthMappingExtUtils.associate(state_id, "state", state);
}
}
Add this snippet to the pre-mapping rule, it checks that whenever state is available and we are going to generate an id_token
, then we calculate the hash based on JWT signing algorithm take the upper half and base64 URL encoded it. (As defined by the last table in this section). It then assigns it as a new JWT claim 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);
}
}
This covers one of the many requirements which OpenBanking adds to a traditional OpenID Connect provider. Read more about PSD2 and Open Banking in this post.
#ISAM