---
title: Entitlement grant with custom approvers workflow example
description: Example entitlement workflow with custom approvers pulled from entitlement glossary attributes
component: pingoneaic
page_id: pingoneaic:identity-governance:administration/example-workflow-entitlement-grant-custom-approvers
canonical_url: https://docs.pingidentity.com/pingoneaic/identity-governance/administration/example-workflow-entitlement-grant-custom-approvers.html
llms_txt: https://docs.pingidentity.com/pingoneaic/llms.txt
docs_for_agents: https://developer.pingidentity.com/build-with-ai/docs-for-agents.md
keywords: ["workflows", "use cases", "examples", "custom approvers", "entitlement grant"]
section_ids:
  assumptions: Assumptions
  example: Example
  create-custom-glossary-property: "Task 1: Create a custom glossary property"
  create-workflow-with-custom-approvers: "Task 2: Create a workflow with custom approvers"
---

# Entitlement grant with custom approvers workflow example

In this example, an administrator wants to create a basic entitlement grant workflow that uses a custom list of approvers in the Approval node.

Administrators need to carry out the following tasks:

* [Create a custom glossary property](#create-custom-glossary-property)

* [Create an entitlement grant workflow with custom approvers](#create-workflow-with-custom-approvers)

## Assumptions

* You have designated an end user or a test user who can approve the request.

## Example

### Task 1: Create a custom glossary property

The initial task is to create a custom entitlement glossary property, `Approvers`, that lets an administrator set a custom list of approvers.

1. In the Advanced Identity Cloud admin console, click Governance > Glossary.

2. Click Entitlement and then [icon: add, set=material, size=inline] Entitlement Glossary Item.

3. In the Add Entitlement Glossary Item modal, enter the following, and click Save.

   | Field                  | Description                                                                       |
   | ---------------------- | --------------------------------------------------------------------------------- |
   | Name                   | Enter a label for the entitlement glossary item. For example, `approvers`.        |
   | Display Name           | Enter a display name for the entitlement glossary item. For example, `Approvers`. |
   | Description (optional) | Enter a general description for the glossary item.                                |
   | Type                   | Select User.                                                                      |
   | Multi-Valued           | Click Multi-Valued.                                                               |
   | Enumerated Values      | Leave disabled.                                                                   |

### Task 2: Create a workflow with custom approvers

Create a new workflow called `Basic Entitlement Grant Custom Approvers`.

![An example of an entitlement grant workflow using custom approvers.](../_images/governance-entitlement-grant-workflow-custom-approvers.png)

* 1 Use a Script node to perform a context check for the request.

  > **Collapse: Click to display the Request Context Check script**
  >
  > ```js
  > var content = execution.getVariables();
  > var requestId = content.get('id');
  > var context = null;
  > var skipApproval = false;
  > var lineItemId = false;
  > try {
  >   var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
  >   if (requestObj.request.common.context) {
  >     context = requestObj.request.common.context.type;
  >     lineItemId = requestObj.request.common.context.lineItemId;
  >     if (context == 'admin') {
  >       skipApproval = true;
  >     }
  >   }
  > }
  > catch (e) {
  >   logger.info("Request Context Check failed "+e.message);
  > }
  >
  > logger.info("Context: " + context);
  > execution.setVariable("context", context);
  > execution.setVariable("lineItemId", lineItemId);
  > execution.setVariable("skipApproval", skipApproval);
  > ```

* 2 Use an IF/ELSE node and name it `Context Gateway`. If `skipApproval==true`, route it to the `Auto Approval` node. If `skipApproval==false`, route it to the `Approval Task` node.

* 3 Use a Script node for the `Auto Approval` task.

  > **Collapse: Click to display the Auto Approval script**
  >
  > ```js
  > var content = execution.getVariables();
  > var requestId = content.get('id');
  > var context = content.get('context');
  > var lineItemId = content.get('lineItemId');
  > var queryParams = {
  >   "_action": "update"
  > }
  > var lineItemParams = {
  >   "_action": "updateRemediationStatus"
  > }
  > try {
  >   var decision = {
  >       "decision": "approved",
  >       "comment": "Request auto-approved due to request context: " + context
  >   }
  >   openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
  > }
  > catch (e) {
  >   var failureReason = "Failure updating decision on request. Error message: " + e.message;
  >   var update = {'comment': failureReason, 'failure': true};
  >   openidm.action('iga/governance/requests/' + requestId, 'POST', update, queryParams);
  >
  > }
  > ```

* 4 Use a Script node to create an approval task with custom approvers.

  > **Collapse: Click to display the Approval Task properties with custom approvers script**
  >
  > ```js
  > (function() {
  >     var content = execution.getVariables();
  >     var requestId = content.get('id');
  >     var entitlementId = null;
  >     var users = [];
  >
  >     try {
  >       var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
  >       entitlementId = requestObj.request.common.entitlementId;
  >     }
  >     catch (e) {
  >       failureReason = "Validation failed: Error reading request with id " + requestId;
  >     }
  >     try{
  >       var glossary = openidm.action('iga/governance/resource/' + entitlementId +'/glossary', 'GET', {}, {})
  >       let approvers = glossary.approvers
  >       for(var i = 0; i < approvers.length; i++){
  >         var userId = approvers[i];
  >         users.push({
  >           "id": userId, "permissions": {"approve": true, "reject": true, "forward": true, "modify": true, "comment": true}
  >         })
  >
  >       }
  >
  >     }
  >     catch (e){
  >       failureReason = "Validation failed: Error reading request with id " + requestId;
  >     }
  >
  >     if(users.length > 0){
  >       return users;
  >     }
  >     else {
  >       // default approver logic
  >     }
  > })()
  > ```

* 5 Use the Script node to validate the entitlement grant.

  > **Collapse: Click to display the Entitlement Grant Validation script**
  >
  > ```js
  > logger.info("Running entitlement grant request validation");
  >
  > var content = execution.getVariables();
  > var requestId = content.get('id');
  > var failureReason = null;
  > var applicationId = null;
  > var assignmentId = null;
  > var app = null;
  > var assignment = null;
  > var existingAccount = false;
  >
  > try {
  >   var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
  >   applicationId = requestObj.application.id;
  >   assignmentId = requestObj.assignment.id;
  > }
  > catch (e) {
  >   failureReason = "Validation failed: Error reading request with id " + requestId;
  > }
  >
  > // Validation 1 - Check application exists
  > if (!failureReason) {
  >   try {
  >     app = openidm.read('managed/alpha_application/' + applicationId);
  >     if (!app) {
  >       failureReason = "Validation failed: Cannot find application with id " + applicationId;
  >     }
  >   }
  >   catch (e) {
  >     failureReason = "Validation failed: Error reading application with id " + applicationId + ". Error message: " + e.message;
  >   }
  > }
  >
  > // Validation 2 - Check entitlement exists
  > if (!failureReason) {
  >   try {
  >     assignment = openidm.read('managed/alpha_assignment/' + assignmentId);
  >     if (!assignment) {
  >       failureReason = "Validation failed: Cannot find assignment with id " + assignmentId;
  >     }
  >   }
  >   catch (e) {
  >     failureReason = "Validation failed: Error reading assignment with id " + assignmentId + ". Error message: " + e.message;
  >   }
  > }
  >
  > // Validation 3 - Check the user has application granted
  > if (!failureReason) {
  >   try {
  >     var user = openidm.read('managed/alpha_user/' + requestObj.user.id, null, [ 'effectiveApplications' ]);
  >     user.effectiveApplications.forEach(effectiveApp => {
  >       if (effectiveApp._id === applicationId) {
  >         existingAccount = true;
  >       }
  >     })
  >   }
  >   catch (e) {
  >     failureReason = "Validation failed: Unable to check existing applications of user with id " + requestObj.user.id + ". Error message: " + e.message;
  >   }
  > }
  >
  > // Validation 4 - If account doesn't exist, provision it
  > if (!failureReason) {
  >   if (!existingAccount) {
  >     try {
  >       var request = requestObj.request;
  >       var payload = {
  >         "applicationId": applicationId,
  >         "startDate": request.common.startDate,
  >         "endDate": request.common.endDate,
  >         "auditContext": {},
  >         "grantType": "request"
  >       };
  >       var queryParams = {
  >         "_action": "add"
  >       }
  >
  >       logger.info("Creating account: " + payload);
  >       var result = openidm.action('iga/governance/user/' + request.common.userId + '/applications' , 'POST', payload,queryParams);
  >     }
  >     catch (e) {
  >       failureReason = "Validation failed: Error provisioning new account to user " + request.common.userId + " for application " + applicationId + ". Error message: " + e.message;
  >     }
  >   }
  > }
  >
  > if (failureReason) {
  >   logger.info("Validation failed: " + failureReason);
  > }
  > execution.setVariable("failureReason", failureReason);
  > ```

* 6 Use the Script node to reject the request.

  > **Collapse: Click to display the Reject Request script**
  >
  > ```js
  > logger.info("Rejecting request");
  >
  > var content = execution.getVariables();
  > var requestId = content.get('id');
  >
  > logger.info("Execution Content: " + content);
  > var requestIndex = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
  > var decision = {'outcome': 'denied', 'status': 'complete', 'decision': 'rejected'};
  > var queryParams = { '_action': 'update'};
  > openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
  > ```

* 7 Use an IF/ELSE node and name it `Validation Gateway`. If `validationFlowSuccess==true`, route it to the `Auto Provisioning` node. If `validationFlowFailure==false`, route it to the `Entitlement Grant Validation Failure` node.

* 8 Use the Script node to run auto provisioning.

  > **Collapse: Click to display the Auto Provisioning script**
  >
  > ```js
  > logger.info("Auto-Provisioning");
  >
  > var content = execution.getVariables();
  > var requestId = content.get('id');
  > var failureReason = null;
  >
  > try {
  >   var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
  >   logger.info("requestObj: " + requestObj);
  > }
  > catch (e) {
  >   failureReason = "Provisioning failed: Error reading request with id " + requestId;
  > }
  >
  > if(!failureReason) {
  >   try {
  >     var request = requestObj.request;
  >     var payload = {
  >       "entitlementId": request.common.entitlementId,
  >       "startDate": request.common.startDate,
  >       "endDate": request.common.endDate,
  >       "auditContext": {},
  >       "grantType": "request"
  >     };
  >     var queryParams = {
  >       "_action": "add"
  >     }
  >
  >     var result = openidm.action('iga/governance/user/' + request.common.userId + '/entitlements' , 'POST', payload,queryParams);
  >   }
  >   catch (e) {
  >     failureReason = "Provisioning failed: Error provisioning entitlement to user " + request.common.userId + " for entitlement " + request.common.entitlementId + ". Error message: " + e.message;
  >   }
  >
  >   var decision = {'status': 'complete', 'decision': 'approved'};
  >   if (failureReason) {
  >     decision.outcome = 'not provisioned';
  >     decision.comment = failureReason;
  >     decision.failure = true;
  >   }
  >   else {
  >     decision.outcome = 'provisioned';
  >   }
  >
  >   var queryParams = { '_action': 'update'};
  >   openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
  >   logger.info("Request " + requestId + " completed.");
  > }
  > ```

* 9 Use the Script node to process an entitlement grant validation failure.

  > **Collapse: Click to display the entitlement grant validation failure**
  >
  > ```js
  > var content = execution.getVariables();
  > var requestId = content.get('id');
  > var failureReason = content.get('failureReason');
  >
  > var decision = {'outcome': 'not provisioned', 'status': 'complete', 'comment': failureReason, 'failure': true, 'decision': 'approved'};
  > var queryParams = { '_action': 'update'};
  > openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
  > ```

|   |                                                                                                                                                                                                                                                       |
| - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | Download the JSON file for this workflow [here](../_attachments/workflows/workflowUIbasicEntitlementGrantCustomApprovers.json).Learn more about importing or exporting workflows in [workflow editor canvas](workflow-configure.html#orch-ui-canvas). |
