Edit Page

Token Inline Hook Reference

Early Access

This page provides reference documentation for:

  • JSON objects that are contained in the outbound request from Okta to your external service

  • JSON objects that you can include in your response

This information is specific to the Token Inline Hook, one type of Inline Hook supported by Okta.

See Also

For a general introduction to Okta Inline Hooks, see Inline Hooks.

For information on the API for registering external service endpoints with Okta, see Inline Hooks Management API.

For steps to enable this Inline Hook, see below, Enabling a Token Inline Hook.

About

This type of Inline Hook is triggered when OAuth 2.0 and OpenID Connect (OIDC) tokens are minted by your Okta Custom Authorization Server. Before sending the token to the requester, Okta calls out to your external service, and your service can respond with commands to add custom claims to the token or to modify existing claims.

This functionality can be used to add data that is sensitive, calculated at runtime, or complexly-structured and not appropriate for storing in Okta user profiles. Data added this way is never logged or stored by Okta. As an example, tokens minted for a medical app could be augmented with confidential patient data provided by your external service and not stored in Okta.

In addition to adding custom claims, you can modify or remove an existing custom claim or an OIDC standard profile claim. You can also update how long an access token or an ID token is valid.

This Inline Hook works only when using an Okta Custom Authorization Server, not the built-in Okta Authorization Server.

Objects in the Request from Okta

For the Token Inline Hook, the outbound call from Okta to your external service includes the following objects in its JSON payload:

data.identity

Provides information on the properties of the ID token that Okta has generated, including the existing claims that it contains.

Property Description Data Type
claims Claims included in the token. claims object
lifetime Lifetime of the token. lifetime object

data.access

Provides information on the properties of the access token that Okta has generated, including the existing claims that it contains.

Property Description Data Type
claims Claims included in the token. claims object
lifetime Lifetime of the token. lifetime object
scopes The scopes contained in the token. scopes object

claims

Consists of name-value pairs for each included claim. For descriptions of the claims that can be included, see Okta's OpenID Connect and OAuth 2.0 API reference.

lifetime

Property Description Data Type
expiration Time in seconds until the token expires. Number

scopes

The set of scopes that have been granted. For descriptions of the scopes that can be included, see Okta's OpenID Connect and OAuth 2.0 API reference.

Objects in the Response that You Send

For the Token Inline Hook, the commands and error objects that you can return in the JSON payload of your response are defined as follows:

commands

The commands object is where you can provide commands to Okta. It is where you can tell Okta to add additional claims to the token.

The commands object is an array, allowing you to send multiple commands. In each array element, there needs to be a type property and value property. The type property is where you specify which of the supported commands you want to execute, and value is where you supply an operand for that command.

In the case of the Token hook type, the value property is itself a nested object in which you specify a particular operation, a path to act on, and a value.

Property Description Data Type
type One of the supported commands. String
value Operand to pass to the command. It specifies a particular op to perform. value

Supported Commands

The following commands are supported for the Token Inline Hook type:

Command Description
com.okta.identity.patch Modify an ID token.
com.okta.access.patch Modify an access token.

Note: The commands array should only contain commands that can be applied to the requested tokens. For example, if only an ID token is requested, the commands array shouldn't contain commands of the type com.okta.access.patch.

value

The value object is where you specify the specific operation to perform. It is an array, allowing you to request more than one operation.

Property Description Data Type
op The name of one of the supported ops. String
path Location within the token to apply the operation, specified as a slash-delimited path. When adding, replacing, or removing a claim, this always begins with /claims/ and is followed by the name of the new claim that you are adding. When replacing a token lifetime, the path should always be /token/lifetime/expiration. String
value Value to set the claim to. Any JSON object

List of Supported Ops

Op Description
add Add a claim.
replace Modify an existing claim and update the token lifetime.
remove Remove an existing claim.

error

When you return an error object, it should have the following structure:

Property Description Data Type
errorSummary Human-readable summary of the error. String

Returning an error object causes Okta to return an OAuth 2.0 error to the requester of the token, with the value of error set to server_error, and the value of error_description set to the string that you supplied in the errorSummary property of the error object that you returned.

Sample JSON Payload of a Request

{
  "source": "https://{yourOktaDomain}/oauth2/default/v1/authorize",
  "eventId": "3OWo4oo-QQ-rBWfRyTmQYw",
  "eventTime": "2019-01-15T23:20:47.000Z",
  "eventTypeVersion": "1.0",
  "cloudEventVersion": "0.1",
  "contentType": "application/json",
  "eventType": "com.okta.oauth2.tokens.transform",
  "data": {
    "context": {
      "request": {
        "id": "reqv66CbCaCStGEFc8AdfS0ng",
        "method": "GET",
        "url": {
          "value": "https://{yourOktaDomain}/oauth2/default/v1/authorize?scope=openid+profile+email&response_type=token+id_token&redirect_uri=https%3A%2F%2Fhttpbin.org%2Fget&state=foobareere&nonce=asf&client_id=customClientIdNative"
        },
        "ipAddress": "127.0.0.1"
      },
      "protocol": {
        "type": "OAUTH2.0",
        "request": {
          "scope": "openid profile email",
          "state": "foobareere",
          "redirect_uri": "https://httpbin.org/get",
          "response_mode": "fragment",
          "response_type": "token id_token",
          "client_id": "customClientIdNative"
        },
        "issuer": {
          "uri": "https://{yourOktaDomain}/oauth2/default"
        },
        "client": {
          "id": "customClientIdNative",
          "name": "Native client",
          "type": "PUBLIC"
        }
      },
      "session": {
        "id": "102Qoe7t5PcRnSxr8j3I8I6pA",
        "userId": "00uq8tMo3zV0OfJON0g3",
        "login": "administrator1@clouditude.net",
        "createdAt": "2019-01-15T23:17:09.000Z",
        "expiresAt": "2019-01-16T01:20:46.000Z",
        "status": "ACTIVE",
        "lastPasswordVerification": "2019-01-15T23:17:09.000Z",
        "amr": [
          "PASSWORD"
        ],
        "idp": {
          "id": "00oq6kcVwvrDY2YsS0g3",
          "type": "OKTA"
        },
        "mfaActive": false
      },
      "user": {
        "id": "00uq8tMo3zV0OfJON0g3",
        "passwordChanged": "2018-09-11T23:19:12.000Z",
        "profile": {
          "login": "administrator1@clouditude.net",
          "firstName": "Add-Min",
          "lastName": "O'Cloudy Tud",
          "locale": "en",
          "timeZone": "America/Los_Angeles"
        },
        "_links": {
          "groups": {
            "href": "https://{yourOktaDomain}/00uq8tMo3zV0OfJON0g3/groups"
          },
          "factors": {
            "href": "https://{yourOktaDomain}/api/v1/users/00uq8tMo3zV0OfJON0g3/factors"
          }
        }
      },
      "policy": {
        "id": "00pq8lGaLlI8APuqY0g3",
        "rule": {
          "id": "0prq8mLKuKAmavOvq0g3"
        }
      }
    },
    "identity": {
      "claims": {
        "sub": "00uq8tMo3zV0OfJON0g3",
        "name": "Add-Min O'Cloudy Tud",
        "email": "webmaster@clouditude.net",
        "ver": 1,
        "iss": "https://{yourOktaDomain}/oauth2/default",
        "aud": "customClientIdNative",
        "jti": "ID.YxF2whJfB3Eu4ktG_7aClqtCgjDq6ab_hgpiV7-ZZn0",
        "amr": [
          "pwd"
        ],
        "idp": "00oq6kcVwvrDY2YsS0g3",
        "nonce": "asf",
        "preferred_username": "administrator1@clouditude.net",
        "auth_time": 1547594229
      },
      "token": {
        "lifetime": {
          "expiration": 3600
        }
      }
    },
    "access": {
      "claims": {
        "ver": 1,
        "jti": "AT.W-rrB-z-kkZQmHW0e6VS3Or--QfEN_YvoWJa46A7HAA",
        "iss": "https://{yourOktaDomain}/oauth2/default",
        "aud": "api://default",
        "cid": "customClientIdNative",
        "uid": "00uq8tMo3zV0OfJON0g3",
        "sub": "administrator1@clouditude.net",
        "firstName": "Add-Min",
        "preferred_username": "administrator1@clouditude.net"
      },
      "token": {
        "lifetime": {
          "expiration": 3600
        }
      },
      "scopes": {
        "openid": {
          "id": "scpq7bW1cp6dcvrz80g3",
          "action": "GRANT"
        },
        "profile": {
          "id": "scpq7cWJ81CIP5Qkr0g3",
          "action": "GRANT"
        },
        "email": {
          "id": "scpq7dxsoz6LQlRj00g3",
          "action": "GRANT"
        }
      }
    }
  }
}

Sample JSON Payloads of Responses

This section provides example JSON payloads for the supported operations.

Sample Response to Add a Claim

Use the add operation to add new claims to a token. If you use the add operation and include an existing claim in your response with a different value, that value is replaced. Use the replace operation instead. See Sample Response to Replace an Existing Claim for more information. Attempting to remove a system-specific claim or using an invalid operation results in the entire PATCH failing and errors logged in the token hooks events.

{
  "commands": [
    {
      "type": "com.okta.identity.patch",
      "value": [
        {
          "op": "add",
          "path": "/claims/extPatientId",
          "value": "1234"
        }
      ]
    },
    {
      "type": "com.okta.access.patch",
      "value": [
        {
          "op": "add",
          "path": "/claims/external_guid",
          "value": "F0384685-F87D-474B-848D-2058AC5655A7"
        }
      ]
    }
  ]
}

You can also use the add operation to add new members to existing JSON objects and new elements to existing arrays. For example, you have a JSON object in a claim called employee_profile, and you want to add the department_id member to the claim.

The existing target JSON object:

{  
   "employee_profile":{  
      "employee_id":"1234",
      "name":"Anna"
   }
}

Add department_id by specifying the claim in the path, followed by the name of the object member.

Note: Attempting to add a member within a JSON object that doesn't exist or using an invalid operation results in the entire PATCH failing and errors logged in the token hooks events.

{  
   "commands":[  
      {  
         "type":"com.okta.identity.patch",
         "value":[  
            {  
               "op":"add",
               "path":"/claims/employee_profile/department_id",
               "value":"4947"
            }
         ]
      }
   ]
}   

The resulting JSON object:

{  
   "employee_profile":{  
      "employee_id":"1234",
      "name":"Anna",
      "department_id":"4947"
   }
}

You can also append an element to an array by specifying the name of the array, followed by the index where you want to insert the element in the path. For example, you have an array that contains the user's preferred airports, and you want to add a new airport to the array.

The existing target JSON object:

{  
   "preferred_airports":[  
      "sjc",
      "sfo",
      "oak"
   ]
}
{  
   "commands":[  
      {  
         "type":"com.okta.identity.patch",
         "value":[  
            {  
               "op":"add",
               "path":"/claims/preferred_airports/3",
               "value":"lax"
            }
         ]
      }
   ]
}

The resulting JSON object:

{  
   "preferred_airports":[  
      "sjc",
      "sfo",
      "oak",
      "lax"
   ]
}

This add operation adds lax to the end of the array. Alternatively, you can just specify the array name followed by a hyphen - in the path to append an element at the end of the array.

{  
   "commands":[  
      {  
         "type":"com.okta.identity.patch",
         "value":[  
            {  
               "op":"add",
               "path":"/claims/preferred_airports/-",
               "value":"lax"
            }
         ]
      }
   ]
}

Note: Attempting to add an element within an array that doesn't exist or specifying an invalid index results in the entire PATCH failing and errors logged in the token hooks events.

Sample Response to Replace an Existing Claim

You can modify existing custom claims or OIDC standard profile claims, such as birthdate and locale. You can't, however, modify any system-specific claims, such as iss or ver, and you can't modify a claim that isn't currently part of the token in the request payload. Attempting to modify a system-specific claim or using an invalid operation results in the entire PATCH failing and errors logged in the token hooks events.

For the list of access token reserved claims that you can't modify, see Access Tokens Scopes and Claims. Note that although the aud and sub claims are listed as reserved claims, you can modify those claims in access tokens. You can't modify these claims in ID tokens.

See ID Token Claims for a list of ID token reserved claims that you can't modify.

{
   "commands": [ 
        { 
            "type": "com.okta.identity.patch",
            "value": [ 
                 { 
                     "op": "replace",
                     "path": "/claims/extPatientId",
                     "value": "1234"
                  }
             ] 
         }, 
         { 
             "type": "com.okta.access.patch",
             "value": [
                  { 
                     "op": "replace",
                     "path": "/claims/external_guid",
                     "value": "F0384685-F87D-474B-848D-2058AC5655A7" 
                   }
              ] 
          }
      ]
}

You can also use the replace operation to modify members within JSON objects and elements within arrays. For example, you have a JSON object in a claim called employee_profile, and you want to update the email address of the employee.

The existing target JSON object:

{  
   "employee_profile":{  
      "employee_id":"1234",
      "name":"Anna",
      "email":"anna.v@company.com"
   }
}

Specify the claim in the path, followed by the name of the object member that you want to modify.

Note: Attempting to modify a member within a JSON object that doesn't exist or using an invalid operation results in the entire PATCH failing and errors logged in the token hooks events.

{  
   "commands":[  
      {  
         "type":"com.okta.identity.patch",
         "value":[  
            {  
               "op":"replace",
               "path":"/claims/employee_profile/email",
               "value":"anna@company.com"
            }
         ]
      }
   ]
}

The resulting JSON object:

{  
   "employee_profile":{  
      "employee_id":"1234",
      "name":"Anna",
      "email":"anna@company.com"
   }
}

Similarly, you can replace elements in an array by specifying the array name and the valid index of the element that you want to replace in the path.

Sample Response to Modify Token Lifetime

You can modify how long the access and ID tokens are valid by specifying the lifetime in seconds. The lifetime value must be a minimum of five minutes (300 seconds) and a maximum of 24 hours (86,400 seconds).

{
   "commands": 
     [ 
        { 
            "type": "com.okta.identity.patch",
            "value": [ 
                 { 
                     "op": "replace",
                     "path": "/token/lifetime/expiration",
                     "value": 36000
                  }
             ] 
         }, 
         { 
             "type": "com.okta.access.patch",
             "value": [
                  { 
                     "op": "replace",
                     "path": "/token/lifetime/expiration",
                     "value": 36000 
                   }
              ] 
          }
      ]
}

Sample Response to Remove Token Claims

You can remove existing custom claims or OIDC standard profile claims, such as birthdate or locale. You can't, however, remove any system-specific claims, such as iss or ver, and you can't remove a claim that isn't currently part of the token in the request payload. Attempting to remove a system-specific claim or using an invalid operation results in the entire PATCH failing and errors logged in the token hooks events.

For the list of access token reserved claims that you can't remove, see Access Tokens Scopes and Claims.

See ID Token Claims for a list of ID token reserved claims that you can't remove.

Note: The value property for the remove operation isn't required. If you provide it in the response, it should be set to null. Providing any other value fails the entire PATCH response.

{
   "commands": 
     [ 
        { 
            "type": "com.okta.identity.patch",
            "value": [ 
                 { 
                     "op": "remove",
                     "path": "/claims/birthdate",
                     "value": null
                  }
             ] 
         }, 
         { 
             "type": "com.okta.access.patch",
             "value": [
                  { 
                     "op": "remove",
                     "path": "/claims/external_guid"
                   }
              ] 
          }
      ]
}

You can also use the remove operation to remove members from existing JSON objects and elements from existing arrays. For example, you have an array that contains the user's preferred airports, and you want to remove an airport from the array.

Existing target JSON object:

{  
   "preferred_airports":[  
      "sjc",
      "lax",
      "sfo",
      "oak"
   ]
}

You can remove the element from the array by specifying the array name followed by the index of the element that you want to remove. You don't need to specify a value for the remove operation. But, you can specify null as the value if you want.

Note: Attempting to remove an element within an array that doesn't exist or specifying an invalid value results in the entire PATCH failing and errors logged in the token hooks events.

{  
   "commands":[  
      {  
         "type":"com.okta.identity.patch",
         "value":[  
            {  
               "op":"remove",
               "path":"/claims/preferred_airports/1"
            }
         ]
      }
   ]
} 

The resulting JSON object

{  
   "preferred_airports":[  
      "sjc",
      "sfo",
      "oak"
   ]
}

Similarly, you can remove a JSON object member by specifying the JSON object in the path, followed by the claim member that you would like to remove. For example, you have an employee_profile claim, and you want to remove email from it.

Note: Attempting to remove a member within a JSON object that doesn't exist or using an invalid operation results in the entire PATCH failing and errors logged in the token hooks events.

The existing target JSON object:

{  
   "employee_profile":{  
      "employee_id":"1234",
      "name":"Anna",
      "email":"anna.v@company.com"
   }
}

PATCH command that removes the employee's email:

{  
   "commands":[  
      {  
         "type":"com.okta.identity.patch",
         "value":[  
            {  
               "op":"remove",
               "path":"/claims/employee_profile/email"
            }
         ]
      }
   ]
}

The resulting JSON object:

{  
   "employee_profile":{  
      "employee_id":"1234",
      "name":"Anna"
   }
}

Enabling a Token Inline Hook

To activate the Inline Hook, you first need to register your external service endpoint with Okta using the Inline Hooks Management API.

You then need to associate the registered Inline Hook with a Custom Authorization Server Policy Rule by completing the following steps:

  1. Go to API > Authorization Servers.

  2. Select a Custom Authorization Server from the list.

  3. Select Access Policies and select a policy to use with the hook. In most cases, just pick the Default Policy.

  4. One of the policy's rules needs to trigger the Inline Hook. Click the pencil icon for a rule to edit it. If you only have one rule, edit the Default Policy Rule.

  5. Click the Use this Inline Hook dropdown menu. Any Inline Hooks you have registered are listed. Select the hook you would like to use.

  6. Click Update Rule.

Note: Only one Inline Hook can be associated with each rule.