IBM Verify

IBM Verify

Join this online user group to communicate across Security product users and IBM experts by sharing advice and best practices with peers and staying up to date regarding product enhancements.

 View Only

OpenBanking: The State Hash Claim

By Leo Farrell posted Tue February 12, 2019 12:00 AM

  
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
0 comments
12 views

Permalink