---
title: Temporal entitlement grant workflow example
description: Example temporal entitlement workflow with scheduled start and end dates using wait nodes
component: pingoneaic
page_id: pingoneaic:identity-governance:administration/example-workflow-basic-entitlement-grant-temporal
canonical_url: https://docs.pingidentity.com/pingoneaic/identity-governance/administration/example-workflow-basic-entitlement-grant-temporal.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", "temporal access", "temporary access", "entitlement grant"]
section_ids:
  assumptions: Assumptions
  example: Example
  create-workflow-with-wait-node: "Task: Create a workflow with the Wait node"
---

# Temporal entitlement grant workflow example

Identity Governance supports temporal workflows, which let you schedule when a user's access begins and ends. For example, you can grant a contractor access to an application that starts on their first day and automatically ends when their contract expires.

To build these time-based workflows, you use the Wait node to pause the workflow until the specified start or end date has been established.

Administrators need to carry out the following task:

* [Create an entitlement grant workflow with the Wait node](#create-workflow-with-wait-node)

## Assumptions

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

## Example

### Task: Create a workflow with the Wait node

Create a new workflow called `Basic Entitlement Grant Temporal`.

![An example of an entitlement grant workflow with wait node.](../_images/governance-example-entitlement-grant-workflow-temporal.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 enableWait = false;
  > var enableEndWait = false;
  > var skipApproval = false;
  > try {
  >     // Read request object
  >     var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {});
  >     if (requestObj.request.common.context) {
  >         context = requestObj.request.common.context.type;
  >         if (context == 'admin') {
  >             skipApproval = true;
  >         }
  >     }
  >     if (requestObj.request.common.startDate){
  >         enableWait = true;
  >     }
  >     if (requestObj.request.common.endDate){
  >         enableEndWait = true;
  >     }
  > }
  > catch (e) {
  >     logger.info("Request Context Check failed " + e.message);
  > }
  >
  > logger.info("Context: " + context);
  > execution.setVariable("context", context);
  > execution.setVariable("enableWait", enableWait);
  > execution.setVariable("enableEndWait", enableEndWait);
  > execution.setVariable("skipApproval", skipApproval);
  > ```

* 2 Use an IF/ELSE node to set the context gateway.

* 3 Use a 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 skipApproval = content.get('skipApproval');
  > var queryParams = {
  >     "_action": "update"
  > }
  > try {
  >     var decision = {
  >         "decision": "approved",
  >     }
  >     if(skipApproval){
  >         decision.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 If a manual approval is required, use an Approval node for the entitlement owner to approve the request.

* 5 Using a Switch node to check if the request has a specified start date.

* 6 If a future start date exists, use a Wait node to pause the workflow until that date is reached.

* 7 If the Approval node has the `Reject` outcome, use a Script node to deny the request.

  > **Collapse: Click to display the reject request script**
  >
  > ```js
  > logger.info("Rejecting request");
  >
  > var content = execution.getVariables();
  > var requestId = content.get('id');
  >
  > // Complete request as rejected
  > 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 Use a Script node to run 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 the 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) {
  >       var err = e.javaException;
  >         err = JSON.parse(err.detail);
  >         var message = err && err.body ? err.body.response : e.message;
  >         failureReason = "Validation failed: Error provisioning new account to user " + request.common.userId + " for application " + applicationId + ". Error message: " + message;
  >     }
  >   }
  > }
  >
  > if (failureReason) {
  >   logger.info("Validation failed: " + failureReason);
  > }
  > execution.setVariable("failureReason", failureReason);
  > ```

* 9 Use the If/Else node to process validation success or failure.

* 10 Use the Script node to provision the entitlement.

  > **Collapse: Click to provision the entitlement**
  >
  > ```js
  > logger.info("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,
  >       "auditContext": {},
  >       "grantType": "request",
  >       "requestId": requestObj.id,
  >     };
  >     var queryParams = {
  >       "_action": "add"
  >     }
  >
  >     var result = openidm.action('iga/governance/user/' + request.common.userId + '/entitlements' , 'POST', payload,queryParams);
  >   }
  >   catch (e) {
  >     var err = e.javaException;
  >         err = JSON.parse(err.detail);
  >         var message = err && err.body ? err.body.response : e.message;
  >         failureReason = "Provisioning failed: Error provisioning entitlement to user " + request.common.userId + " for entitlement " + request.common.entitlementId + ". Error message: " + message;
  >   }
  >
  >   var decision = {'status': 'complete', 'decision': 'approved'};
  >   if (failureReason) {
  >     decision.outcome = 'not provisioned';
  >     decision.comment = failureReason;
  >     decision.failure = true;
  >     execution.setVariable('enableEndWait', false);
  >   }
  >   else {
  >     decision.outcome = 'provisioned';
  >   }
  >
  >   var queryParams = { '_action': 'update'};
  >   openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
  >   logger.info("Request " + requestId + " completed.");
  > }
  > ```

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

  > **Collapse: Click to view the script for 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);
  > ```

* 12 Use a switch node to check if there's an end date. If there's an end date, run a removal request. If there's no end date, complete the workflow.

* 13 Use a Script node to create a removal request.

  > **Collapse: Click to process the removal request**
  >
  > ```js
  > logger.info("Create Removal Request");
  >
  > 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 = "Create Removal Request failed: Error reading request with id " + requestId;
  > }
  >
  > if(!failureReason){
  >     try{
  >         var request = requestObj.request;
  >         var newRequestPayload = {
  >             "common":{
  >                 "context": {
  >                     "type": "admin"
  >                 },
  >                 "entitlementId": request.common.entitlementId,
  >                 "userId": request.common.userId,
  >                 "endDate": request.common.endDate,
  >                 "justification": "Request submitted automatically to remove access granted by request: " + requestId
  >             }
  >         };
  >         var queryParam = {
  >             '_action': "publish"
  >         }
  >         openidm.action('iga/governance/requests/entitlementRemove', 'POST', newRequestPayload, queryParam)
  >     }catch(e){
  >         logger.warn('Create Removal Request failed to create')
  >     }
  > }
  > ```

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