The vast majority of the work in developing this PIP was done by my colleague Scott Andrews. Thanks for sharing Scott! Find more of his work here:
https://ibm.biz/securityintegration
Building from the example PIP in my article here: ISAM JavaScript Policy Information Points here is a PIP that extracts the OAuth values of scope and supplies them to the CBA engine as a multi valued attribute. Note: This mechanism is dependent on the use of the OAuth-Auth mechanism (as defined here: OAuth Authentication and Sessions)
The PIP is necessary for the scope attribute as the attribute that is defined in the ISAM credential is supplied as a single string “scope1,scope2,scope3” that is comma separated. This PIP will tokenize them and supply them as a proper multivalued attribute for easy policy authoring. The untokenized Scope attribute is available already, and it’s defined as: oauthScopeSubject.
It also extracts the OAuth Client ID which can be useful in other OAuth focused authorization policies.
One example of using the client ID attribute:
Only the iOS client can access these API’s while the Android application should be blocked.
This client ID is defined in the API Definition page:
Step 1) Create two new CBA Attributes:
Name: OAuth Scope
Identifier: urn:ibm:security:iam:oauth:scope
Issuer: OAuthPIP
Category: Subject
Data Type: String
Matcher: exact_match
Type: Policy
Name: OAuth ClientID
Identifier: urn:ibm:security:iam:oauth:client:id
Issuer: OAuthPIP
Category: Subject
Data Type: String
Matcher: exact_match
Type: Policy
Note: The Issuer should match the name you define when creating the JavaScript PIP in the next step.
If you wanted to use these attributes in a Risk Score calculation, you could also select the Type “Risk”.
Step 2) Create the JavaScript PIP:
Start with the standard imports:
importPackage(com.tivoli.am.rba.extensions); importClass(Packages.com.tivoli.am.rba.attributes.AttributeIdentifier);
As per the JavaScript PIP guide, there are two main functions, hasAttribute:
function hasAttribute (requestedAttribute, category) { PluginUtils.trace("oauthscope_pip_rile.hasAttribute(): entry"); PluginUtils.trace("oauthscope_pip_rile.hasAttribute(): Looking for " + requestedAttribute + " in " + category); // The 'instanceName' global variable should match the issuerId // configured for the attributes. var issuerId = instanceName; var pipIssued = false; if (issuerId.equals(requestedAttribute.getIssuer())) { pipIssued = true; } PluginUtils.trace("oauthscope_pip_rile.hasAttribute(): exit: " + requestedAttribute.getURI() + " --> returning " + pipIssued); return pipIssued; }
and getAttributes:
function getAttributes (context, requestedAttribute, category) { PluginUtils.trace("oauthscope_pip_rile.getAttributes(): entry: " + requestedAttribute + " --> " + category); /** * In case our PIP serves more than 1 attribute, let's still check * for the one we're looking for */ if ("urn:ibm:security:iam:oauth:scope".equals(requestedAttribute.getURI())) { /** * Get the oauthScopeSubject attribute. Note if we are using the * EAS instead of oauth-auth in WebSEAL, we would instead get the * oauthScopeResource attribute and lookin the RESOURCE attribute * not the SUBJECT. */ var oauthScopeSubjectIdentifier = new AttributeIdentifier( "urn:ibm:security:subject:oauthScope", Attribute.DataType.STRING, null); var oauthScopeSubject = context.getAttribute(Attribute.Category.SUBJECT, oauthScopeSubjectIdentifier); if (oauthScopeSubject != null && oauthScopeSubject.length > 0) { PluginUtils.trace("oauthscope_pip_rile.getAttributes(): " + "Found scopes: " + oauthScopeSubject[0]); /** * Try a cast so we don't try and do it on an Object data type * otherwise you get a Java Object exception. */ var stringScopeCast = String(oauthScopeSubject[0]); //Turn our static string into a multi valued attribute. Make an // assumption of no whitespace. var oauthScopes = stringScopeCast.split(",") /** * Create the new attribute identifier to populate it back * into the context. * * Instance name is the name of the PIP, so we can use this *but* if * we have a PIP that is the issuer for multiple issuer IDs, * we couldn't use it as the hasAttribute would have checked against * 1 or more and then manually returned true. */ var oauthScopeAttribute = new AttributeIdentifier( "urn:ibm:security:iam:oauth:scope", Attribute.DataType.STRING, instanceName); context.addAttribute(oauthScopeAttribute, oauthScopes); PluginUtils.trace("oauthscope_pip_rile.getAttributes(): " + "adding urn:ibm:security:iam:oauth:scope " + oauthScopes); } else { PluginUtils.trace("oauthscope_pip_rile.getAttributes(): " + "No oauthScopeSubject found!"); } } if ("urn:ibm:security:iam:oauth:client:id" .equals(requestedAttribute.getURI())) { /** * Retrieve the oauth_token_client_id from the XACML passed from * WebSEAL to RTSS. You can find a list of additional attributes you * could use by looking in the pdweb.rtss. * For example - * access_token * client_type * scope (though already an attribute which is populated from * urn:ibm:security:subject:oauthScope which is also sent) * urn:oasis:names:tc:xacml:1.0:action:action-id (though already in * the attribute list as the 'action' which is the HTTP Method) */ var oauthClientIdIdentifier = new AttributeIdentifier( "oauth_token_client_id", Attribute.DataType.STRING, null); var oauthClientId = context.getAttribute(Attribute.Category.SUBJECT, oauthClientIdIdentifier); if (oauthClientId != null && oauthClientId.length > 0) { PluginUtils.trace("oauthscope_pip_rile.getAttributes(): " + "Found oauth_token_client_id: " + oauthClientId[0]); var oauthClientIdAttribute = new AttributeIdentifier( "urn:ibm:security:iam:oauth:client:id", Attribute.DataType.STRING, instanceName); context.addAttribute(oauthClientIdAttribute, [oauthClientId[0]]); PluginUtils.trace("oauthscope_pip_rile.getAttributes(): " + "adding urn:ibm:security:iam:oauth:client:id " + [oauthClientId[0]]); } else { PluginUtils.trace("oauthscope_pip_rile.getAttributes(): " + "No oauth_token_client_id found!"); } } PluginUtils.trace("oauthscope_pip_rile.getAttributes(): exit"); }
Save in your favorite editor, and create and upload your PIP
Name: OAuthPIP
Description: Parses the scope and ClientID OAuth attributes and makes them available for simple CBA policies
Type: JavaScript
Script: <Upload your file>
Step 3) Use your attribute in your CBA policy and profit!