JavaScript Mapping rule reference
JavaScript mapping rule
This document covers all the interfaces available for mapping rule JavaScript.
1. STSUniversalUser
The general rule of STSUniversalUser is that, the authenticated user claims are available under the AttributeContainer section and request parameters are available under the ContextAttribute section.
| Return Type | Method | Description | Arguments |
|---|---|---|---|
| AttributeContainer | getAttributeContainer() | Return the AttributeContainer section. | |
| AttributeContainer | getContextAttributes() | Return the ContextAttribute section. | |
| addAttribute(attr) | Add attribute into AttributeContainer section. | Attribute | |
| addContextAttribute(attr) | Add attribute into ContextAttribute section. | Attribute | |
| getAttributeValueByName(name) | Retrieve attribute from AttributeContainer section. | string | |
| setPrincipalName(name) | Set principal name. | string | |
| string | getPrincipalName() | Retrieve principal name. | |
| string | toString() | Stream STSUniversalUser to JSON string. |
1.1. Attribute
| Return Type | Method | Description |
|---|---|---|
| string | getName() | Return attribute's name. |
| string | getType() | Return attribute's type. |
| any | getValue() | Return attribute's value. |
| any[] | getValues() | Return attribute's values. |
1.2. AttributeContainer
| Return Type | Method | Description | Arguments |
|---|---|---|---|
| Attribute | getAttributeByName(name) | Return attribute that matches the name that was provided. | string |
| Attribute[] | getAttributeByType() | Return attributes that match the type that was provided. | string |
| Attribute | getAttributeByNameAndType(name, type) | Return attribute that matches the name and type that were provided. | string, string |
| any | getAttributeValueByName(name) | Return first value of the attribute that matches the name that was provided. | string |
| any[] | getAttributeValuesByName(name) | Return all values of the attribute that match the name that was provided. | string |
| any | getAttributeValueByNameAndType(name, type) | Return first value of the attribute that matches the name and type that were provided. | string, string |
| any[] | getAttributeValuesByNameAndType(name, type) | Return all values of the attribute that match the name and type that were provided. | string |
| any[] | setAttributeObject(attr) | Set attribute into the attribute container. | Attribute |
| any[] | setAttribute(name, type, values) | Create an attribute in the attribute container with the value that was provided. | string, string, any |
| Attribute | removeAttributeByNameAndType(name, type) | Remove attribute based on name and type that were provided. | string, string |
| Boolean | removeAttribute(attr) | Remove the specified attribute from the container. | Attribute |
2. Client and definition
In the mapping rule javascript, Client and Definition objects
are available under oauth_client and oauth_definition, respectively.
3. PreToken mapping rule
Pre-token mapping rule is used to enrich the tokens, meaning that it produces claims that are output in the id_token or /userinfo endpoint.
It also produces claims that are presented when tokens are introspected at the /introspect endpoint.
This approach is a slightly different than what is in IVIA.
In the JavaScript context, two JS map objects are displayed: tokenData and idtokenData.
tokenData and idtokenData are global variables available in the mapping rule, they are used for the purpose of grant enrichment.
tokenData is used to add claims to the /introspect response, essentially the access token.
idtokenDatais used to add claims to the id_token and to enrich the userinfo response.
tokenData and idtokenData can be assigned a name-value pair.
The advantage of this approach is the claim can be a complex object and no longer limited by STSUniversalUser string data type only.
Example usage:
var hok = {
"fingerprint#256": "aalweuaadg27ifafw8a2"
}
var grps = ["admin", "user"];
tokenData.cnf = hok;
tokenData.groups = grps;
3.1. Attribute mappings
In Definition, a user can define attribute mappings. Before the pre-token mapping rule is called, all attribute mappings are resolved, and the data (if any)
is available in the AttributeContainer section of the STSUniversalUser object.
3.2. Requested claims
To be able to do claim mapping, the user needs to know what claims are requested. According to OIDC specification, the claims can be requested by using scope values or requested by using claims parameter.
To make this process easier, the system considers both parameters and displays a claims object of type RequestedClaims
that has the following interface:
| Return Type | Method | Description | Arguments |
|---|---|---|---|
| string[] | getIDTokenEssentialClaims() | Return ID token essential claims. | |
| string[] | getIDTokenVoluntaryClaims() | Return ID token voluntary claims. | |
| string[] | getUserInfoEssentialClaims() | Return user information essential claims. | |
| string[] | getUserInfoVoluntaryClaims() | Return user information voluntary claims. | |
| string[] | getAllClaims() | Return all claims. | |
| string[] | getIDTokenClaimValues(name) | Return values associated with an ID token claim. | string |
| string[] | getUserInfoClaimValues(name) | Return values associated with a user information claim. | string |
For example, given scope=openid+email+phone and claims parameter as follows:
{
"userinfo": {
"given_name": { "essential":true },
"nickname": { "essential": false, "value": "Joe" },
"email": { "essential": true },
"http://example.info/claims/groups":null
},
"id_token": {
"given_name": { "essential": false },
"auth_time": { "essential": true },
"acr": { "values": [ "urn:mace:incommon:iap:gold", "urn:mace:incommon:iap:silver" ] }
}
}
Based on the previous example:
claims.getIDTokenEssentialClaims()returns["auth_time"]claims.getAllClaims()returns["acr", "nickname", "email", "http://example.info/claims/groups", "phone_number", "phone_number_verified", "auth_time", "email_verified","given_name"].claims.getIDTokenClaimValues("acr")returns["urn:mace:incommon:iap:gold", "urn:mace:incommon:iap:silver"]claims.getUserInfoClaimValues("nickname")returns["Joe"]
4. PostToken mapping rule
Post-token mapping rule is the last chance to manipulate the response.
Similar to pre-token mapping rule, in the JavaScript context, two JS map objects displayed: tokenData and idtokenData.
The tokenData object contains the claim for introspect and the idtokenData object contains the claim for id_token/userinfo that were done in the pre-token mapping rule.
User can manipulate extra parameters or extra headers in the response. For that purpose, two JS map objects are displayed: paramsOverride and headersOverride.
The paramsOverride value can be of complex type because it can go to the query string, fragment, or response body.
The headersOverride value must be kept as string because it goes to the response header.
Example usage:
headersOverride["x-fapi-corr-id"] = "gsdu2-22y2haw-23nafa-afw";
5. Extra mapping rules
Due to a different code structure, in IBM Verify Identity Access OIDC Provider(IVIAOP) mapping rules are intended for specific purposes.
5.1. ROPC user authentication
In IVIA, the user authentication for ROPC is done in the pre-token mapping rule. In the IVIAOP, the mapping rule ropc.js performs the task.
The username and password that are received from the request are available in STSUniversalUser ContextAttribute. When the user is authenticated, the claims that are related to the user are set into the JS map object userData.
Example usage:
var username = stsuu.getContextAttributes().getAttributeValueByName("username");
var password = stsuu.getContextAttributes().getAttributeValueByName("password");
if (username == "peter" && password == "secret") { // Authenticate user via LDAP or HTTP call-out
userData.uid = "prabbit"; // This will be the `sub` of the token
userData.given_name = "peter";
userData.family_name = "rabbit";
userData.preferred_username = "[email protected]";
} else {
OAuthMappingExtUtils.throwSTSInvalidGrantMessageException("Invalid user or password.", "Either user or password is not valid.");
}
5.2. Dynamic client registration metadata customization
In IVIA, the pre-token mapping rule is also used to manipulate the dynamic client registration payload for the following use cases:
- Setting the defaults for metadata that are not specified in the incoming payload. For example, if
grant_typesis not specified, the default isauthorization_code. - Substitute metadata values that the OIDC provider does not support or wants to enforce. For example, the OIDC provider might want to enforce the
token_endpoint_auth_methodtoprivate_key_jwtonly. - Further metadata validation. For example, in OpenBanking specification, some metadata needs to be bound by metadata inside the software statement. Other examples are to check software statement issuer, expiry, or other attributes.
- Throws an
invalid_client_metadataerror for metadata values that the OIDC provider does not like.
In IVIAOP, this goes to separate javascript file that can be configured in the provider.yml.
Definition object should be available under oauth_definition context.
Each client metadata received is available as attributes under ContextAttribute section.
Example usage:
// Setting default example
var grant_types = stsuu.getContextAttributes().getAttributeValuesByName("grant_types");
if (grant_types == null) {
stsuu.addContextAttribute(new Attribute("grant_types", "urn:ibm:names:ITFIM:oauth:body:param", "authorization_code"));
}
// Substitute metadata value example
var attr = stsuu.getContextAttributes().getAttributeByName("token_endpoint_auth_method");
if (attr != null) {
stsuu.getContextAttributes().removeAttribute(attr);
}
stsuu.addContextAttribute(new Attribute("token_endpoint_auth_method", "urn:ibm:names:ITFIM:oauth:body:param", "private_key_jwt"));
// Further metadata validation
var ss = stsuu.getContextAttributes().getAttributeValueByName("software_statement");
if (ss != null) { // Software statement exists
var iss = stsuu.getContextAttributes().getAttributeValueByName("iss");
if (iss != "http://openbankingdirectory.com") {
OAuthMappingExtUtils.throwSTSCustomUserMessageException("Unexpected software statement issuer.", 400, "invalid_client_metadata");
}
}
6. Differences between IVIAOP and IVIA-mapping rules
6.1. Differences in purposes
In IVIA, the pre-token and post-token mapping rules can be interpreted as user customization before and after the default implementation that is done in OAuth20TokenModule. Therefore, the user authentication for the ROPC flow and the id_token claims that need to be resolved, must be done inside pre-token mapping rule before the token can be generated. Because the state_id, also called the grant_id, is available only after token is generated, the association of extra data happens at post-token. Also, post-token is used to manipulate the final result, for example, in the introspection and userinfo endpoints. Although technically the manipulation can be done at pre-token because the default implementation produces only a minimal response that unlikely needs to be overwritten.
In IVIAOP, as explained in PreToken Mapping Rule, PostToken Mapping Rule, and Additional Mapping Rules, each mapping rule can have different purpose. Therefore, some refactoring is needed.
- ROPC user authentication goes to a specific mapping rule.
- Introspect enrichment is done in
pre-tokeninstead ofpost-token. Userinfoenrichment is done together withid_tokenin thepre-token.- Dynamic Registration defaults, overrides, and further validation go to another mapping rule.
Also, things that currently are done in the mapping rules are now available OOTB or through configuration. For examples:
- The enforcement that authorization code can be used only once.
- Filtering of scopes
- Enforcement of
jtiuniqueness - Validation of various JWTs
6.2. Differences in objects
Some of the differences are:
- Definition object is displayed by default as
oauth_definition. - Java
ListandMapare replaced with a JS list and object, so some interfaces that are available as part of that Java might no longer be there. - The introduction of new objects such as
claims,userData,tokenData,paramsOverride.
Updated 12 months ago
