State management

The state_id parameter in the STSUniversalUser module is used as a key to store or retrieve state information for each invocation of the trust chain of an OAuth flow.

Advance Access Control provides sample mapping rules. These sample mapping rules use state management API and are applicable to OAuth 2.0 protocols. You can get the sample mapping rules from the File downloads section.

OAuth 2.0

OAuth 2.0 tokens, such as grants, access tokens, and refresh tokens, have a state_id parameter that is used in Security Token Service mapping rules. The state_id parameter maintains state between associated Security Token Service calls in an OAuth 2.0 flow.

The OAuth 2.0 mapping rule uses the state_id as the key to issue an authorization grant. The key is used to add the token storage time to a cache. The storage time is then retrieved from the cache during a request for a protected resource.

Figure 1 shows a section of the sample JavaScript mapping rule for OAuth 2.0.
Figure 1. OAuth 2.0 JavaScript sample code with state management
...
var request_type = null;
var grant_type = null;

// The request type - if none available assume 'resource'
temp_attr = stsuu.getContextAttributes().getAttributeValuesByNameAndType("request_type", "urn:ibm:names:ITFIM:oauth:request");
if (temp_attr != null && temp_attr.length > 0) {
        request_type = temp_attr[0];
} else {
        request_type = "resource";
}

// The grant type
temp_attr = stsuu.getContextAttributes().getAttributeValuesByNameAndType("grant_type", "urn:ibm:names:ITFIM:oauth:body:param");
if (temp_attr != null && temp_attr.length > 0) {
        grant_type = temp_attr[0];
}

/* The following demonstrates the use of the state management API.
 *
 *      request_type = 'authorization' ==> Store the UTC time of the request into a cache
                                   with state_id as key [authorization_code, implicit]
 *      request_type = 'access_token' && grant_type = 'client_credentials' ==> Store the UTC time of the request 
                                   into a cache with state_id as key [client_credentials]
 *      request_type = 'access_token' && grant_type = 'password' ==> Store the UTC time of the request into a cache
                                   with state_id as key [password]
 *      request_type = 'resource' ==> Retrieve the stored time and put it into an attribute named recovered_state
 *
 *      It also stores the flow type we are in be used later to detect if this is a client_credentials two-legged flow or not.
 */
if (request_type == "authorization" || (request_type == "access_token" && 
                                   ( grant_type == "client_credentials" || grant_type == "password" ))) {
        var curr_utc_time = "State storage time was: " + IDMappingExtUtils.getCurrentTimeStringUTC();
        IDMappingExtUtils.getIDMappingExtCache().put(state_id, curr_utc_time, 1000);
} else if (request_type == "resource") {
        var recovered_state = IDMappingExtUtils.getIDMappingExtCache().get(state_id);

        if (recovered_state != null) {
                var state_arr = java.lang.reflect.Array.newInstance(java.lang.String, 1);
                state_arr[0] = recovered_state;
                stsuu.addContextAttribute(new Attribute("recovered_state",
                                                   "urn:ibm:names:ITFIM:oauth:response:attribute", state_arr));
        }
}
...