Configuring the IExpandTokenPlugin plugin

In bearer token authentication, the caller presents a JSON Web Token (JWT). The JWT contains a set of claims. Each claim is a key/value pair that represents information that "the bearer of the token claims to be true". For example, a JWT could contain the following claim, which asserts the identity of the bearer of the token (in the 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.)

For example, suppose Ray Newton is an insured making a request to ClaimCenter. The JWT includes the following.
[
  "sub": "rnewton@email.com",
  "groups": [
    "gwa.prod.cc.Insured"
  ],
  "cc_policyNumbers": [
    "PA-123456"
  ],
 ...
]

Cloud API grants authorization in this way:

  • Based on the groups claim, the caller is given endpoint access as defined in the Insured API role.

  • Based on the cc_policyNumbers claim, the caller is given resource access to resources associated with any claim whose policy has a number of PA-123456.

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:

  1. Create an implementation class

  2. 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.

The default implementation of the method, as provided by Studio, is as follows.
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:

  1. Extract any appropriate lookup values from the original token map

  2. Call the appropriate system of record to retrieve the relevant additional authorization values

  3. 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.

For example, to assign a user to an API role named "Account_Holders" for a production planet, the value added to the expansion map must be:
"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.

For example, the pc_username resource access strategy requires a single resource access ID set to the user's username. If the caller is "aapplegate@acme.com", the value added to the expansion map must be:
"pc_username": "aapplegate@acme.com"
The pc_accountNumbers resource access strategy permits one or more resource access IDs set to the caller's policy numbers. If the caller owns accounts C000123 and C000456, the value added to the expansion map must be:
"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.

The method receives the following token map:
"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:

  1. Extracts the lookup value (kegerston@allrisk.com)

  2. Sends this value to the external producer system

  3. Puts the returned values in an expansion tokens map with a cc_producerCodes claim.

If the external producer system returned the values 100-002541, 100-002542, and 100-002543, the method's expansion map would be:
"cc_producerCodes": [
  "100-002541",
  "100-002542",
  "100-002543"
]
After the plugin has been called, the original token map would look like this:
"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"
]

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

  1. In Studio, navigate to config > plugins > registry.
  2. Right-click the registry node and select New > plugin.
  3. In the Plugin dialog box, provide the following values:
    • Name: IExpandTokenPlugin
    • Interface: IExpandTokenPlugin
  4. Click OK. Studio opens a new IExpandTokenPlugin.gwp tab.
  5. 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).
  6. 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.
  7. To deploy your changes, restart the server.