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 Anthony Ferguson on March 15, 2019

Calling all IBM Tivoli Federated Identity Manager Customers

An open letter to our IBM Tivoli Federated Identity Manager customers,   As part of the IBM Security Access Manager development teams ongoing focus to support our customer base we are hoping to gain a better understanding as to how we can assist our IBM Tivoli Federated Identity Manager customers to migrate to our IBM […]

Continue reading

By nlloyd@us.ibm.com on March 14, 2019

ISAM Advanced Access Control Infomap to run info.js

In the past Level II Support has received Cases asking for various ways to force the running of the info.js script which is needed for AAC device registration.  The Knowledge Center section Configuring the attribute collection service notes to add the URL of info.js to the <head> block in the HTML landing page of your application.  […]

Continue reading

By Scott Exton on March 6, 2019

Hybrid ISAM Environments

IBM Security Access Manager introduced support for Docker a few years ago with the publishing of the IBM Security Access Docker image.  The interest in Docker has recently increased and questions are now being asked around how to run both the appliance and Docker in the same environment.  This is especially useful for customers who have […]

Continue reading