Pre-issue access token action¶
The pre-issue access token action in Asgardeo lets you execute custom logic before issuing an access token.
Asgardeo triggers this action during the OAuth2 token issuance process. You can change the access token or add checks before issuing the token using the action.
You can use this functionality to:
- Add, change, or remove scopes.
- Add, change, or remove audience values.
- Change or remove user attributes incorporated into the access token.
- Add custom claims. You can use string, number, boolean, and string type arrays.
- Update the validity period of the access token.
When your external service modifies an access token, Asgardeo saves the changes as transactional data for the token's active period. In later flows, Asgardeo provides the updated access token to applications, resource servers, and any actions. For example, when your service modifies an access token during the authorization code flow, Asgardeo uses the same updated access token in the refresh token flow.
Note
Currently, this action applies only at the root organization level and is available only for JWT tokens.
It supports the following grant types: authorization code, client credentials, password, and refresh token.
How pre-issue access token action works¶
Configure a pre-issue access token action with your external service endpoint. Asgardeo calls your service and waits for a response whenever a token request arrives. Upon receiving the response, Asgardeo applies any modifications to the access token as specified in the response and then continues with the flow.
The following API contracts defines the request and response structures that your service must adhere to, based on the action version.
Request from Asgardeo¶
| Property | Description |
|---|---|
| requestId |
A unique correlation identifier that associates with the token request received by Asgardeo. |
| actionType | Specifies the action. In this case, |
| event | Contains context information relevant to access token issue flow. Refer event section for details. |
| allowedOperations | Specifies the objects within the event data that your external service can change. Refer allowedOperations section for details. |
event¶
| Property | Description | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| event.request |
This property encapsulates the details of the access token request, including parameters and headers. It provides the following specific properties.
|
||||||||||||||||||||||
| event.tenant | This property shows the root organization (tenant) where Asgardeo processes the token request. | ||||||||||||||||||||||
| event.organization | This property represents the organization which is issuing the access token. | ||||||||||||||||||||||
| event.user | This property contains information about the authenticated user associated with the token request.
|
||||||||||||||||||||||
| event.userStore | This property indicates the user store that manages the user's data. |
||||||||||||||||||||||
| event.accessToken | This property shows the access token that Asgardeo will issue. It contains claims and scopes. Your external service can change these using logic in the pre-issue access token action.
|
||||||||||||||||||||||
| event.refreshToken | This property represents the refresh token associated with the token issuance event. It contains the claims related to the refresh token, such as expires_in. These claims can be modified by your external service during the pre-issue access token action based on custom logic.
|
allowedOperations¶
The allowedOperations property in the context of the pre-issue access token action defines the set of operations that your external service can perform on the access token's claims and on certain claims of the refresh token. This property specifically relates to the event.accessToken and event.refreshToken properties and outlines which attributes let your external service add extra properties, replace values, or remove attributes. The allowedOperations use JSON Patch modification semantics.
In the context of the pre-issue access token action, your external service can change certain claims related to authorization decisions, such as audience (aud), access token validity (expires_in), and scopes (scopes). These claims typically associate with the resource server and influence how access gets granted.
But other standard access token claims, such as the issuer (iss) and token bindings (binding_type), represent the authorization server and play a critical role in authorization decisions. These properties aren't allowed for modification through the action. Use application and organization-level configurations to change these properties and their behaviors.
Additionally, your external service can change any OIDC claims incorporated into the access token.
Here is the example of an allowedOperations object in a request formatted as a JSON payload:
{
"allowedOperations": [
{
"op": "add",
"paths": [
"/accessToken/claims/",
"/accessToken/scopes/",
"/accessToken/claims/aud/"
]
},
{
"op": "remove",
"paths": ["/accessToken/scopes/", "/accessToken/claims/aud/"]
},
{
"op": "replace",
"paths": [
"/accessToken/scopes/",
"/accessToken/claims/aud/",
"/accessToken/claims/expires_in",
"/refreshToken/claims/expires_in"
]
}
]
}
Example request from Asgardeo¶
This example illustrates a request sent to an external service configured as a pre-issue access token action, for an application authorizing a user via the authorization code grant flow.
POST /token HTTP/1.1
Host: localhost
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/json
{
"actionType": "PRE_ISSUE_ACCESS_TOKEN",
"event": {
"request": {
"additionalHeaders": {
"host": [
"localhost:9443"
],
"user-agent": [
"curl/7.79.1"
]
},
"clientId": "1u31N7of6gCNR9FqkG1neSlsF_Qa",
"grantType": "authorization_code"
},
"tenant": {
"id": "-1234",
"name": "carbon.super"
},
"user": {
"id": "e204849c-4ec2-41f1-8ff7-ec1ebff02821",
},
"userStore": {
"id": "UFJJTUFSWQ==",
"name": "PRIMARY"
},
"accessToken": {
"tokenType": "JWT",
"scopes": [
"email",
"groups",
"openid",
"profile",
"roles"
],
"claims": [
{
"name": "iss",
"value": "https://localhost:9443/oauth2/token"
},
{
"name": "client_id",
"value": "1u31N7of6gCNR9FqkG1neSlsF_Qa"
},
{
"name": "aut",
"value": "APPLICATION_USER"
},
{
"name": "expires_in",
"value": 3600
},
{
"name": "aud",
"value": [
"1u31N7of6gCNR9FqkG1neSlsF_Qa"
]
},
{
"name": "subject_type",
"value": "public"
},
{
"name": "sub",
"value": "e204849c-4ec2-41f1-8ff7-ec1ebff02821"
}
]
},
"refreshToken": {
"claims": [
{
"name": "expires_in",
"value": 86400
}
]
}
},
"allowedOperations": [
{
"op": "add",
"paths": [
"/accessToken/claims/",
"/accessToken/scopes/",
"/accessToken/claims/aud/"
]
},
{
"op": "remove",
"paths": [
"/accessToken/scopes/",
"/accessToken/claims/aud/"
]
},
{
"op": "replace",
"paths": [
"/accessToken/scopes/",
"/accessToken/claims/aud/",
"/accessToken/claims/expires_in",
"/refreshToken/claims/expires_in"
]
}
]
}
POST /token HTTP/1.1
Host: localhost
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/json
{
"actionType": "PRE_ISSUE_ACCESS_TOKEN",
"event": {
"request": {
"additionalHeaders": {
"host": [
"localhost:9443"
],
"user-agent": [
"curl/7.79.1"
]
},
"clientId": "1u31N7of6gCNR9FqkG1neSlsF_Qa",
"grantType": "authorization_code"
},
"tenant": {
"id": "-1234",
"name": "carbon.super"
},
"organization": {
"id": "f2604b90-e2e5-4a6c-bc83-0f942e34d20d",
"name": "carbon.super"
},
"user": {
"id": "e204849c-4ec2-41f1-8ff7-ec1ebff02821",
"organization": {
"id": "f2604b90-e2e5-4a6c-bc83-0f942e34d20d",
"name": "carbon.super"
}
},
"userStore": {
"id": "UFJJTUFSWQ==",
"name": "PRIMARY"
},
"accessToken": {
"tokenType": "JWT",
"scopes": [
"email",
"groups",
"openid",
"profile",
"roles"
],
"claims": [
{
"name": "iss",
"value": "https://localhost:9443/oauth2/token"
},
{
"name": "client_id",
"value": "1u31N7of6gCNR9FqkG1neSlsF_Qa"
},
{
"name": "aut",
"value": "APPLICATION_USER"
},
{
"name": "expires_in",
"value": 3600
},
{
"name": "aud",
"value": [
"1u31N7of6gCNR9FqkG1neSlsF_Qa"
]
},
{
"name": "subject_type",
"value": "public"
},
{
"name": "sub",
"value": "e204849c-4ec2-41f1-8ff7-ec1ebff02821"
}
]
},
"refreshToken": {
"claims": [
{
"name": "expires_in",
"value": 86400
}
]
}
},
"allowedOperations": [
{
"op": "add",
"paths": [
"/accessToken/claims/",
"/accessToken/scopes/",
"/accessToken/claims/aud/"
]
},
{
"op": "remove",
"paths": [
"/accessToken/scopes/",
"/accessToken/claims/aud/"
]
},
{
"op": "replace",
"paths": [
"/accessToken/scopes/",
"/accessToken/claims/aud/",
"/accessToken/claims/expires_in",
"/refreshToken/claims/expires_in"
]
}
]
}
Expected response from external service¶
When Asgardeo invokes your external service as part of the pre-issue access token action, it expects a response that adheres to the defined API contract.
This response plays a crucial role in determining how Asgardeo issues or modifies the access token. Here’s a breakdown of the expected response:
The response can have three possible states: SUCCESS, FAILEDand ERROR.
SUCCESS: Indicates that your external service processes the request successfully and for Asgardeo to apply any required state changes or modifications.
FAILED: Represents a selective failure within the token flow due to validation logic or business rules enforced by your external service. Asgardeo returns a 400 (Client Error) response to the application, incorporating the failure message provided by your external service. You must supply an OAuth 2.0-compliant failure message when extending the flow.
ERROR: Indicates a processing failure in your external service, typically caused by server-side issues. Asgardeo returns a 500 (Server Error) response to the application.
Response for SUCCESS state¶
When the external service responds with a 200 status code and a SUCCESS state, it means the service processes the request correctly and completes any requested modifications to the access token or associated data. The response should include details about these modifications, typically in the form of an operations object that outlines the changes made to the token's claims, scopes, or other relevant attributes.
Http Status Code: 200
| Property | Description |
|---|---|
| actionStatus | Indicates the outcome of the request. Set this value to |
| operations | Define an array of operations that your external service performs on the |
Tip
Refer the sample responses for successful access token updates to learn how to construct success responses for different scenarios.
Response for FAILED state¶
When the external service returns a 200 OK status code with a FAILED state, it means the service has intentionally opted to prevent access token issuance. The service makes this decision using specific validation logic or business rules defined by your application's requirements.
The response body must be a JSON object containing the following properties:
Http Status Code: 200
| Property | Description |
|---|---|
| actionStatus | Indicates the outcome of the request. For a failed operation, set this value to |
| failureReason | Provides the reason for failing to issue an access token. Asgardeo maps this value to the error field in the response from the /oauth2/token endpoint.. |
| failureDescription | Offers a detailed explanation of the failure. Asgardeo maps this value to the error_description field in the |
Below is an example of a failed response due to invalid scopes in the access token request.
Response from external service:
HTTP/1.1 200 OK
Content-Type: application/json
{
"actionStatus": "FAILED",
"failureReason": "invalid_scope",
"failureDescription": "Scope platinum_state is invalid"
}
The application that initiates the token request receives the following error response.
Error response to the application:
HTTP/1.1 400
Content-Type: application/json
{
"error": "invalid_scope",
"error_description": "Scope platinum_state is invalid"
}
Response for ERROR state¶
When the external service responds with an ERROR state, it can return an HTTP status code of 400, 401, or 500, indicating either a validation failure or an issue processing the request.
Http Status Code: 400, 401 or 500
| Property | Description |
|---|---|
| actionStatus | Indicates the outcome of the request. Set this value to |
| errorMessage | Describes the cause of the error |
| errorDescription | A detailed description of the error |
If the external service returns an error response (either defined or undefined) or fails to respond entirely, Asgardeo treats this as an error in executing the action. In any of these cases, the application that initiated the token request receives a 500 Internal Server Error.
Below is an example of an error response returned by the service implementing the pre-issue access token action.
Response from external service:
HTTP/1.1 500
Content-Type: application/json
{
"actionStatus": "ERROR",
"errorMessage": "Server error",
"errorDescription": "Error while processing request."
}
The application that initiates the token request receives the following error response.
Error response to the application:
HTTP/1.1 500
Content-Type: application/json
{
"error":”server_error",
"error_description": "Internal Server Error."
}
Note
Currently, the errorMessage or errorDescription from the external service’s ERROR response isn't directly included in the error response sent back to the application.
Conditional invocation of pre-issue access token action¶
Pre-issue access token actions can be conditionally triggered based on configurable rule criteria. The rule configuration currently supports the following fields:
- Application: The specific application that requests the access token.
- Grant Type: The grant type used during the token issuance process.
Each rule field supports the following operators:
- equals
- not equals
You can specify exact values for these fields, such as a specific application associated with a tenant or a particular grant type. You can also combine rules using logical AND and OR operators. This approach gives you flexible and precise control over when to invoke a pre-issue access token action.
The above rule configuration translates logically to:
- The application is Test App and the grant type is client_credentials, or
- The application is Test App, regardless of the grant type.
