---
title: Entitlement grant workflow example
description: Example entitlement grant workflow with privilege validation and manager approval requirements
component: pingoneaic
page_id: pingoneaic:identity-governance:administration/example-entitlement-grant-workflow
canonical_url: https://docs.pingidentity.com/pingoneaic/identity-governance/administration/example-entitlement-grant-workflow.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", "entitlement grant"]
section_ids:
  assumptions: Assumptions
  example: Example
---

# Entitlement grant workflow example

In this example, an administrator wants to create an entitlement grant workflow that:

* An entitlement owner must approve the request. If an administrator sends a request, the request is auto-approved.

* If approved, check if the entitlement is marked as `privileged`.

  |   |                                                                                                                                                                                                                           |
  | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | Companies can define what `privileged` means in the glossary. However, usually, a `privileged` entitlement gives administrative rights to sensitive data, such as view access to quarterly reports before public release. |

* If the entitlement is privileged or null, the end user's manager must approve the request.

## Assumptions

* Each entitlement has an entitlement owner. An entitlement owner is a user identity designated to manage the entitlement.

* You create a boolean [entitlement glossary attribute](glossary.html#create-entitlement-attribute) , `isPrivileged`. This attribute is populated for each entitlement.

* Your end users have a manager assigned to them. An administrator populates this property and isn't modifiable by the end user.

## Example

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

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

  > **Collapse: Click to display the request context check script**
  >
  > ```js
  > /*
  > Script nodes are used to invoke APIs or execute business logic.
  > You can invoke governance APIs or IDM APIs.
  > Learn more in Manage workflows.
  >
  > Script nodes should return a single value and should have the
  > logic enclosed in a try-catch block.
  >
  > Example:
  > try {
  >   var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
  >   applicationId = requestObj.application.id;
  > }
  > catch (e) {
  >   failureReason = 'Validation failed: Error reading request with id ' + requestId;
  > }
  > */
  > 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 to set the context gateway.

* 3 Use the Script node to run an auto approval:

  > **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 Using an Approval node, the entitlement owner must approve the request.

* 5 Use a Script node to check the value of the entitlement glossary attribute `isPrivileged` and set the outcome.

  > **Collapse: Click to display the entitlement privileged script**
  >
  > ```js
  > var content = execution.getVariables();
  > var requestId = content.get('id');
  > var requestObj = null;
  > var entId = null;
  > var entGlossary = null;
  > var entPriv = null;
  >
  > //Check entitlement exists and grab entitlement info
  > try {
  >   requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
  >   entId = requestObj.assignment.id;
  > }
  > catch (e) {
  >   logger.info("Validation failed: Error reading entitlement grant request with id " + requestId);
  > }
  > //Check glossary for entitlement exists and grab glossary info
  > try {
  >   entGlossary = openidm.action('iga/governance/resource/' + entId + '/glossary', 'GET', {}, {});
  >   // Sets entPriv based on the glossary contents, if present, otherwise defaults to true
  >   entPriv = (entGlossary.hasOwnProperty("isPrivileged")) ? entGlossary.isPrivileged : true;
  >   //Sets entPriv based on glossary contents, if present, otherwise defaults to false
  >   //entPriv = !!entGlossary.isPrivileged;
  >   execution.setVariable("entPriv", entPriv);
  > }
  > catch (e) {
  >   logger.info("Could not retrieve glossary with entId " + entId + " from entitlement grant request ID " + requestId);
  > }
  > ```

* 6 Use a switch node to route outcomes based on the script. If the outcome is:

  * `privileged` (`entPriv==true`): An additional Approval node requires the end user's manager to approve the request.

  * `notPrivileged`(entPriv==false\`): An additional approval isn't required.

* 7 If the required approvals are met, the Script node runs a validation check.

  > **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);
  > ```

  If any Approval node has the `Reject` outcome, a Script node denies 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);
  > ```

* 8 If the `If/else` node outcome is:

  * `validationFlowSuccess`: A Script node provisions the application to the end user.

    > **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.");
    > }
    > ```

  * `validationFlowFailure`: A Script node doesn't provision the application to the end user.

    > **Collapse: Click to display the validation failure script**
    >
    > ```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/wfEntitlementExampleIsPrivileged.json).For information on how to import or export workflows, learn more in [workflow editor canvas](workflow-configure.html#orch-ui-canvas). |
