Access and Authentication

OpenBanking: The state hash claim

Share this post:

OpenBanking: The state hash claim

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 

Click here to rate this article

Rate this article :

Software Engineer - IBM Security Access Manager

More stories
By Martin Schmidt on May 17, 2019

Modernizing your B2C Portal Security – A thoughtful approach

As we have described the situation that many of our customers are in today, and our proposal for a better future state, we come to realize that for many, this transition is a journey, and a single big bang transition is not practical for many.  This blog entry will outline an approach to start such […]

Continue reading

By Craig Pearson on May 16, 2019

IBM Verify : MMFA Mapping Rules to Determine Device Registration

This article demonstrates how to configure a pre-token mapping rule for MMFA in ISAM which can prevent authenticator registration when certain undesirable conditions are detected.  For example: Unsupported app or OS version The device is jailbroken Enforce users to register with a customer authenticator app Below are the registration attributes included in the request payload […]

Continue reading

By Martin Schmidt on May 4, 2019

Modernizing your B2C Portal Security – Desired End State

Proposition: As we have seen in part one of this series, managing customer identities for a portal can be a challenge and distraction for the business.  In this part of the series we will outline how a modernized solution for a portal security can simplify operations and free your team up to focus on the […]

Continue reading