Configuring the IExpandTokenPlugin plugin
sub
claim, which identifies the
"subject"):[
"sub": "rnewton@email.com",
...
]
Cloud API uses information in the JWT to determine the authorization to grant to the caller. This typically involves two types of information:
-
Some information in the JWT identifies the API roles to assign to the caller. This determines the level of endpoint access the caller has.
-
Some information in the JWT identifies the caller's resource access IDs. This determines the level of resource access the caller has. (In other words, this determines which specific resources that caller can access.)
[
"sub": "rnewton@email.com",
"groups": [
"gwa.prod.pc.Account_Holder"
],
"pc_accountNumbers": [
"C000143542"
],
...
]
Cloud API grants authorization in this way:
-
Based on the
groups
claim, the caller is given endpoint access as defined in theAccount_Holder
API role. -
Based on the
pc_accountNumbers
claim, the caller is given resource access to resources associated with any account whose account number is C000143542.
The structure and contents of a JWT vary based on the type of caller. But, for every type of caller using bearer token authentication, the JWT either contains the caller's API roles and resource access IDs, or it contains information used to determine the caller's API roles and resource access IDs.
The authorization information that is placed into a JWT can come from the IdP. It can also come from the caller application itself, provided it is a scope value that the caller application has already registered with Guidewire Hub. Cloud API also supports the ability to add PolicyCenter-specific authorization information after the JWT has been received but before authorization is determined. This is done by the IExpandTokenPlugin plugin.For more overview information on JWTs and how the IExpandTokenPlugin plugin interacts with the information flow, see Constructing JWTs.
Implementing the IExpandTokenPlugin plugin
To implement the IExpandTokenPlugin plugin, you must do the following:
-
Create an implementation class
-
Register the plugin
Creating an IExpandTokenPlugin implementation class
The class that implements the IExpandTokenPlugin plugin must meet the following requirements:
-
It must implement
gw.api.modules.rest.framework.v1.plugin.security.IExpandTokenPlugin
-
It must specify an override of the
getTokenExpansions
method
The getTokenExpansions method
When a Cloud API call using bearer token authentication is received, PolicyCenter extracts the information from the JWT into a "token map". Then, it calls the
getTokenExpansions
method. This method returns a "token
expansions map" which contains the key/value pairs to add to the initial token map,
or to override in the initial token map.
-
If the token expansions map specifies a claim that is not in the original token map, Cloud API adds it to the original token map.
-
If the token expansions map specifies a claim that is already in the original token map, Cloud API replaces the original claim with the expansions claim. Thus, if a given claim must have both values from the JWT and values retrieved from the external system, this method must merge the two sets into a single claim.
override function getTokenExpansions(map : Map<String, Object>) : Map<String, Object> {
return map
}
The method receives the original token map in the map
object, which contains all the key/value pairs from the JWT as received from the
caller.
The method must do the following:
-
Extract any appropriate lookup values from the original token map
-
Call the appropriate system of record to retrieve the relevant additional authorization values
-
Construct a "token expansions" map return value that specifies all claims to add to the original token map, and all claims already in the original token map that must be replaced
The method cannot return null. If there are no required changes, return an empty map.
Formats for values in the token expansions map
For internal users, there is no need to specify API roles in either the JWT or the token expansions map. API roles are retrieved by querying the database for the user roles assigned to the user. For more information, see OAuth2 authorization code flow: Internal users.
For external users, API roles must be specified in either the JWT or the token expansions map. When they are specified in the expansions map:
-
The key must be set to "groups".
-
The value must be of type List<String>, where each string has the following format:
-
It starts with "gwa.<planetclass>.pc.", where <planetclass> is set to either "prod", "preprod", or "lower".
-
It ends with the Cloud API role name.
-
"groups": [
"gwa.prod.pc.Account_Holders"
]
Resource access IDs
For both internal and external users, resource access IDs must be specified in either the JWT or the token expansions map. When they are specified in the expansions map:
-
The key must be set to the name of the resource access strategy. This must be one of the following:
- pc_username
- pc_accountNumbers
-
If the resource access strategy requires a single resource access ID, the key's value must be set to that ID.
-
If the resource access strategy permits one or more resource access IDs, the key's value must be set to an array storing the IDs.
"pc_username": "aapplegate@acme.com"
"pc_accountNumbers": [
"C000123",
"C000456"
]
Performance considerations
This plugin is called during Cloud API authentication. Guidewire recommends that insurers confirm that the SLA with their authorization system of record is sufficient for such a heavily used case.
Guidewire recommends against adding more than 1000 elements in a List or Array that is the value for a key. Such a large number of entries can result in performance issues when GenericCenter passes queries to the database that contain filtering logic with more than 1000 values.
The getTokenExpansions method example: producer codes
For callers using the producerCodes access strategy, suppose you store producer codes
in an external producer system. In order to identify the correct producer codes to
grant to a caller, the external system must have uniquely identifying information
about the caller, such as the value in the caller's sub
claim.
"sub": "kegerston@allrisk.com",
"scp": [
"cc_producerCodes",
"tenant.acme",
"project.default",
"planet_class.prod"
],
"groups": [
"gwa.prod.cc.Producer"
],
The method then does the following:
-
Extracts the lookup value (kegerston@allrisk.com)
-
Sends this value to the external producer system
-
Puts the returned values in an expansion tokens map with a
cc_producerCodes
claim.
"cc_producerCodes": [
"100-002541",
"100-002542",
"100-002543"
]
"sub": "kegerston@allrisk.com",
"scp": [
"cc_producerCodes",
"tenant.acme",
"project.default",
"planet_class.prod"
],
"groups": [
"gwa.prod.cc.Producer"
],
"cc_producerCodes": [
"100-002541",
"100-002542",
"100-002543"
]
Example implementation
package gw.acme.rest.internal.pc.dgc.plugin
uses gw.api.modules.rest.framework.v1.plugin.security.IExpandTokenPlugin
uses javax.annotation.Nonnull
class ExpandTokenDGCPlugin implements IExpandTokenPlugin {
@Nonnull
override function getTokenExpansions(map : Map<String, Object>) : Map<String, Object> {
//Map to be merged to original one
var dgcMap = new HashMap<String, Object>()
dgcMap.put("groups", {"gwa.dev.cc.Producer"})
dgcMap.put("cc_producerCodes", {"100-002541"})
dgcMap.put("cc_producerCodes", {"100-002542"})
dgcMap.put("cc_producerCodes", {"100-002543"})
return dgcMap
}
}
Register the IExpandTokenPlugin plugin
About this task
The base configuration does not include a registry entry for the IExpandTokenPlugin plugin. You must add it manually. For more information on registering plugins, see the Configuration Guide.
Procedure
- In Studio, navigate to .
- Right-click the registry node and select .
-
In the Plugin dialog box, provide the following
values:
- Name: IExpandTokenPlugin
- Interface: IExpandTokenPlugin
- Click OK. Studio opens a new IExpandTokenPlugin.gwp tab.
- In the upper left corner of the tab, click the plus symbol (+). Then select either Add Gosu Plugin (to register the plugin with a Gosu implementation class) or Add Java Plugin (to register the plugin with a Java implementation class).
- On the right side, add a value to the Gosu Class field or the Java Class field that identifies the class that implements the plugin.
- To deploy your changes, restart the server.