Managing custom entitlements or Bring Your Own (BYO) entitlements using Okta Identity Governance (OIG) Entitlement Management

Introduction

Okta Identity Governance (OIG) Entitlement Management feature supports managing entitlements out of the box for these provisioning-enabled apps in the Okta Integration Network (OIN). This list will grow with time, however it is also possible to manage entitlements to applications not in this list using its APIs. This blog post takes a look at how this can be done. This article assumes familiarity with Okta’s Workforce Identity Cloud platform including the Okta Admin console, Okta Workflows and OIG. This article does not cover the basics of the Entitlement Management capability itself, readers are advised to read this article for an introduction. This article specifically deals with how to implement similar Entitlement Management capabilities for applications not in the provisioning-enabled list using its APIs. Though this article uses Okta Workflows for processing event hooks, it is not required to do so. You can use your own custom-built and self-hosted event hooks, however using Okta Workflows does simplify things as it is a no-code platform and the workflows built by you are hosted by Okta. In addition, Okta Workflows is offered alongside OIG as a bundle making it a convenient and simpler solution option.

In OIG, entitlements can be managed using Entitlement policies that assign entitlements to users using Okta Expression Language or using Entitlement bundles which are requested by users using OIG Access Requests. This article covers both of these scenarios in the context of custom or BYO entitlements.

Configuration/set up

As a first step, we need to create the application in Okta. This article uses a custom SAML application. Note that not all applications support Entitlement Management, for example, bookmark and SWA apps do not support Entitlement Management at the time of writing this article. Refer to the limitations section in the Entitlement Management documentation. In addition, the actual SAML configuration has not been done for this example, as we won’t be testing the SSO capability, but for an actual production application, this is assumed to be configured and working. The Governance Engine needs to be enabled in the General tab of the application configuration as shown in this screenshot. Also, take note of the prerequisite mentioned in the screenshot.

Once the Governance Engine is enabled, we will be able to see the new Governance tab.

The Governance tab contains Entitlements, Entitlement bundles and entitlement policies. They will initially be empty. Let’s create some entitlements to start with. You can create entitlements directly from this Governance tab in the admin UI or using the OIG APIs. In a BYO entitlement scenario, this is typically done using the OIG APIs and Okta Workflows, where an Okta workflow would discover the entitlements in the application (using the application’s APIs to retrieve entitlements) and import those entitlements in Okta using the OIG APIs. We will use Postman in this article to create some dummy entitlements using the OIG APIs. You can view the API reference documentation for the OIG APIs at https://developer.okta.com/docs/api/iga/.

The API calls in the screenshots below create some dummy license and role entitlements. We will use these entitlements throughout this article in entitlement policies, bundles and access reviews to understand how BYO entitlements can be managed.

The entitlement values array highlighted in the screenshots has an externalValue field that uniquely identifies the entitlement in the application and is retrieved from the application, typically using the application’s APIs. For this article, I have come up with some dummy (but unique) values for this field. Okta generates a unique Id for the entitlement and also a unique Id for each of the entitlement values, which you will find in the response to these API calls. The screenshot below shows the response to the API call that created the license entitlements for illustration.

Once these entitlements are created using the APIs, we can see them in the Governance tab of the application.

As mentioned before, these entitlements could have been created directly in the UI using the Add entitlement button we see in the screenshot, but APIs are typically used to import custom entitlements from target applications into Okta at scale.

Now that we have imported the entitlements into Okta, let us create a couple of entitlement policy rules to assign these entitlements to users. We can create entitlement policy rules in the Policy tab. There is a default entitlement policy, to which we can add rules using the Add rule button. These rules use Okta Expression language to assign entitlements to users. In this article, I use two simple rules, one for admins and one for regular users. The first rule checks a user profile attribute to assign entitlements to admin users and the second rule is set to true for illustration purposes, it serves as a catch-all rule that always evaluates to true and hence applies to all users. You would need to configure these rules to model your business rules for assigning entitlements to users.

When we edit the policy to add rules, it goes to draft state and we need to apply the policy to activate it.

The next step is to assign users to this application, like we usually would in Okta. When users are assigned to this application, the entitlement policy rules would get evaluated and entitlements would be assigned to users based on these rules. Thus, users can be assigned entitlements based on entitlement policy rules. However, there is another way in which users can get entitlements – through entitlement bundles. Entitlement bundles, as the name suggests, are bundles of entitlements, and users would request these entitlement bundles as part of OIG Access Requests. (Note that entitlement bundles cannot be assigned through entitlement policy rules, they need to be requested as part of OIG Access Requests and also Access Requests cannot grant individual entitlements like entitlement policy rules do, they can only grant entitlement bundles. These are limitations in the platform at the time of writing this article). For now, let us create a couple of entitlement bundles to be used in access requests later.

I have created two entitlement bundles, one for admin users and one for regular users. These bundles grant the same entitlements as the entitlement policy rules, but are used just to illustrate how BYO entitlements can be managed when entitlement bundles are used.

Now that we have entitlements, bundles and policies set up, let us use these to understand the different ways by which entitlements can be granted to users in Okta and how Okta can provision these entitlements to users in the target application in each of these scenarios.

Assigning entitlements to users – different scenarios

Entitlement policies

Let us start with how entitlements can be assigned to users through entitlement policy rules. In order to do so, we need to assign users to the application. I will use two users for testing – Gusto Simpson whose title attribute is set to “Admin” and another user – Shell Simpson whose title attribute is empty.

Let us assign Gusto Simpson to this application like we usually would, but with the governance engine enabled, we can select Policy or Custom values for the entitlement assignment method when assigning the user to the application. (We can, of course, assign groups to the application as we usually would, but I assign individual users in this article)

Once the user is assigned, we can see the Entitlement set to Policy in the Assignments tab for the user. This indicates that the entitlements for this user have been assigned by Policy.

When we click on the 3 dots and select View entitlements, we can see all the entitlements of the user. In this case, all of them are assigned by the entitlement policy, hence the source is Policy. (A user can have entitlements coming from multiple sources such as Policy and Access Requests, we look at this scenario later in the article).

One thing to note is that both the entitlement policy rules were evaluated for this user, even though the first rule was a match! Entitlement policy rules are evaluated differently when compared to Okta authentication policy rules, as the evaluation does not stop when a rule is matched, it goes on to evaluate all the rules and entitlements for the user are assigned from all matching rules.

When entitlements are assigned to a user, the event resource.user_entitlements.update is logged in the Okta System log.

If we look into the DebugContext, we can see a GrantId, GrantAction and GrantSource for this entitlement grant.

Now that the entitlements from the policy have been assigned to the user in Okta, we need to propagate these entitlements to the target application. We can do this using an event hook that subscribes to this event. Event hooks can be implemented using Okta Workflows or custom-built and self-hosted. I am using an Okta Workflow to implement the event hook in this article. I have also set up event hook filtering to filter the resource.user_entitlements.update event by application, so that my event hook is called only when the event is fired for this application and not for other applications in my Okta tenant. This article does not get into the plumbing required to set up an event hook, if you need details on how to set up an event hook, how to use an Okta Workflow as an event hook, how to set up event hook filtering etc, please go through the related links.

Let us look at the Okta Workflow used to implement the event hook. The workflow looks like this (divided into 2 screenshots for readability).

At a high level, the workflow does the following

    • Reads the GrantId from the DebugContext.

    • Calls the GetGrant OIG API using the GrantId with the ?include=full_entitlements query parameter to get the grant details, including the entitlements granted by the grant.

    • Obtains the userId and applicationId from the response of the GetGrant API. The userId is in the targetPrincipal.externalId field and the applicationId is in the target.externalId field in the response to the GetGrant API.

    • It then calls the Get Principal Entitlements OIG API filtered by the userId and applicationId. This returns the principal entitlements of the user for this application.

    • After this, the Workflow needs to call the relevant APIs of the target application to sync/provision these principal entitlements into the target application. This depends on the APIs exposed by the application in question for provisioning entitlements and is not shown in the Workflow.

Note that this article does not go over creating users in the application when users are assigned to the application in Okta, updating user profile attributes etc. These can be done by calling the application’s APIs. This article discusses only what is involved in the provisioning of entitlements in the application.

Let us try to understand what happens in the workflow in a bit more detail.

The response to the GetGrant API is shown below.

The highlighted sections in the screenshot show the applicationId, userId and the array of entitlements granted by this grant. In this case, the entitlements array has two elements, one for licenses and one for roles. In each of these entitlements, there is an array of values with 2 elements in each value array (for the 2 licenses and 2 roles respectively).

The workflow then uses the applicationId and the userId to call the GetPrinicipalEntitlements API. The response to this API is shown below.

This call returns the full set of entitlements the user has in this application. In this case, this is the same as the entitlements returned by the GetGrant API that we covered before, but it is not always the case. This is because the GetPrincipalEntitlements API returns not just the entitlements from this grant, but also from other active grants that the user may have (for example, a user may have multiple active grants, one from a policy and others from one or more entitlement bundles, we will cover this scenario later in this article). Hence it is recommended to use the principal entitlements as the source of truth to provision entitlements in the target application. This will become more clear later when we look at an example of a user that has multiple active grants.

At this point, the workflow should call the target application’s APIs to provision the entitlements returned by the GetPrincipalEntitlements API response. This would entail removing the entitlements not in the list of the user’s principal entitlements and adding the entitlements in this list in the target application using the target application’s APIs. In order to do this, the application needs to expose APIs to retrieve the entitlements for a user, add an entitlement for a user and remove an entitlement for a user. Most applications that provide APIs to manage entitlements should expose these capabilities via APIs. (As an example, Microsoft 365 provides Graph APIs to get all licenses for a user, assign a license to a user and remove a license from a user, and likewise for roles).

Also note that when we assigned the user to the application earlier, we selected the entitlement assignment method as Policy. We can also select Custom for the entitlement assignment method. If we do so, we need to pick and choose the entitlements to assign to the user and the entitlements will not be assigned by the entitlement policy rules. This would then generate the same event type in the Okta system log (with a GrantSource of CUSTOM instead of POLICY), which can be processed by the same workflow to provision those entitlements in the target application. However, Organizations would typically use entitlement policy rules to assign entitlements to users as these rules represent the business rules for the Organization that govern which users should get what entitlements.

Now before we look at the next method of assigning entitlements to users (entitlement bundles), let’s see what would happen when there is a change in policy rules (such as adding new rules, changing or deleting existing rules etc). Let us see an example of how user’s entitlements are affected by a policy change and how our workflow would handle those changes.

Let’s edit the entitlement policy rule so that regular users get only the basic license, not the app user role. We remove the role entitlement from this rule by clicking the trash icon, then save the rule and apply the policy.

The modified policy rule looks like this.

Let’s verify that the user’s role entitlement has been updated in the app assignment. We can see that the App User role has been removed.

This change generates the same system log event type in Okta again with a GrantAction of ALLOW like the last time.

Let’s look at the execution history of the workflow that runs again in response to this event. The GetGrant API call is highlighted in the screenshot below.

Below is the response from the GetGrant API call. We can see that the App User role has been removed from the list of entitlements in the grant due to the entitlement policy change that we made.

The response from the GetPrincipalEntitlements API would return the same set of entitlements.

Lastly, when users are unassigned from the application (either individually or by un-assigning a group from the application), this would also generate the same event type in the Okta system log, which would be processed by the workflow, but in this case, the principal entitlements of the user would be empty (as Okta removes all the entitlements of the user for the application when the user is unassigned from the application). This is shown below, and in this case, the workflow needs to implement the logic to remove all the entitlements for the user in the application by calling the application’s APIs (not included in this article).

Now let’s look at the next method of assigning entitlements to users, which is through entitlement bundles using OIG Access Requests. (Note that we revert the policy rule to what it was before, i.e., add the App User role back to the policy rule that grants entitlements for regular users).

Entitlement bundles

Remember that we have already created two entitlement bundles in the Configuration/set up section of this article. Before we start using entitlement bundles, let’s first assign a regular user (non-admin with an empty title) to the application before the user gets entitlements from an entitlement bundle. This will cause the policy to assign some entitlements to the user first, which will allow us to test the scenario where a user has multiple active grants (from both policies and entitlement bundles).

The user Shell Simpson has been assigned to the app and she gets these entitlements through the entitlement policy rules as she is a regular user.

We have a request type in Okta Access Requests to request access to the admin entitlement bundle, which looks like this.

This is a standard request type, but for the “Grant access to entitlement bundle” action selected in the screenshot. This is a new type of Action available to use in request types to assign an entitlement bundle to a user. This request type requires manager approval before the user can be granted the admin entitlement bundle.

Shell requests access to this entitlement bundle through Okta Access Requests and her manager approves it. This is standard Okta Access Requests functionality and is not covered in detail in this article. Please refer to Okta Access Requests for an overview. After manager approval, Shell is granted the admin entitlement bundle, and her entitlement type changes to Custom in the assignment (as she now has entitlements granted outside of the entitlement policy). She has entitlements sourced from both the entitlement policy as well as the Access Request as shown below.

When Shell is granted the admin entitlement bundle, the same event type is logged in the Okta system logs (resource.user_entitlements.update), which again triggers our workflow. The DebugContext of the event looks a bit different this time.

The event again has a GrantId, but the GrantSource is ENTITLEMENT_BUNDLE instead of POLICY. Let’s look at the execution history of our workflow. The response to the GetGrant API call (with the ?include=full_entitlements query parameter) is highlighted below. We can see that the grantType is ENTITLEMENT-BUNDLE and the entitlementBundleId is now available in the response.

The entitlements array in the GetGrant API response contains the entitlements granted through this entitlement bundle. We can see that the grant in this particular system log event is specific to the entitlement bundle and does not cover the entitlements that Shell has been granted by the entitlement policy, which is why the GetGrant API response for this grantId does not contain the other entitlements granted through the entitlement policy. However, when we take a look at the response of the GetPrincipalEntitlements API call, we can see all the entitlements that Shell has, both from the entitlement policy as well as from the entitlement bundle. Highlighted below is the call to the GetPrincipalEntitlements API and its response. And as mentioned before, the workflow needs to have the logic to update the entitlements in the target application via its APIs (not included in this article) using the user’s principal entitlements as the source of truth. That would then provision the entitlements the user was granted through this bundle in the target application.

Shell, in fact has two active grants, one from the Entitlement policy and another from the Entitlement bundle. We can call the List All Grants API filtered by the application and user to see all the entitlement grants a user has for an application. The response to this API call is shown below.

We can see that there are two active grants each with a unique grantId returned by this API call, the first one is of grantType POLICY and the second one is of grantType ENTITLEMENT-BUNDLE (which also has the entitlementBundleId). The Get Grant API can be called with each of these grantIds (with the include=full_entitlements query parameter) to see the entitlements granted by each of these grants, if needed. Note that a user can also have more than one entitlement bundle, each with its own active grant. Thus, it is possible for a user to have many active grants.

Before we conclude entitlement bundles, let’s update an entitlement bundle to see how it affects the entitlements of a user who has been granted the bundle. Let’s update the Admin entitlement bundle in the Okta Admin UI to remove the Premium license entitlement by clicking on the trash icon shown below and then save the bundle.

If we look at Shell’s entitlement assignment now, we can see that the Premium License entitlement has been removed due to the change we made.

This again generates the same event type in the Okta system log with GrantAction ALLOW and GrantSource ENTITLEMENT_BUNDLE.

If we look at the execution history of our workflow that processed this event, we can see the response to the GetGrant API call.

We see that the entitlements array now does not include the Premium license entitlement, as it has been removed from the entitlement bundle. The response to the GetGrant API call for this grant includes only the Super Admin role entitlement. However, we cannot find out what entitlement was removed by looking at this grant. It should now be clear why it is recommended to use the user’s principal entitlements as the source of truth to update the entitlements in the target application. If we use the entitlements from the GetGrant API call to make this update, we wouldn’t know that the Premium license entitlement needs to be removed in the application. (We also cannot take the approach of removing all the entitlements not present in this grant, as that would remove the entitlements from other active grants from other entitlement bundles and the entitlement policy). Thus, using the user’s principal entitlements as the source of truth to update the entitlements in the target application is reliable for all scenarios, as it includes the user’s entitlements from all active grants. In this scenario, the list of principal entitlements would not have the Premium license entitlement and hence, our workflow using that as the source of truth needs to remove that entitlement in the target application.

Let us now look at the last scenario – Access Certifications. (Note that we add the Premium license entitlement back to the Admin entitlement bundle before continuing further).

Access Certifications

In this section, we will create an access certification campaign to review users’ entitlements in the application. We will cover the scenario when a reviewer revokes a user’s entitlements acquired through an entitlement bundle and through a policy and how this can be remediated in the application.

This article does not cover access certification campaigns in detail, you can refer to the production documentation or other blog articles. Let’s create an access certification campaign to review user’s entitlements in the application and set the remediation rules to remove access from the user when the reviewer revokes access. This will then attempt to remove the entitlements from the user when a reviewer revokes those entitlements.

The reviewer is set to the user’s manager. After launching the campaign, let’s log in as the reviewer to perform the review. Marge Simpson is configured as the manager for Shell Simpson. The below image shows the manager user profile attributes for Shell Simpson

Let’s log in as Marge Simpson and go to the Okta Access Certification Reviews dashboard and view the pending reviews.

Here, Marge will be able to view and review the entitlements each user has for the application. When Marge selects the row with the entitlement bundle, she can see the entitlements that Shell has acquired from the bundle and all of her active entitlements (coming from all active grants).

Once the entitlement bundle is revoked, there are a few events logged in the Okta system log – one for the access certification review decision and another for the access certification review remediation. The access certification review remediation is successful, which means the entitlement bundle has been removed from the user (as we configured the campaign to remove access from the user when the reviewer revokes access). As the user’s entitlements have been updated, this also logs the user entitlement updated successfully event in the system log.

When we expand the event, we can see that the GrantAction this time is DENY and GrantSource is ENTITLEMENT_BUNDLE.

Looking at the execution history of our workflow triggered by this event, we see in the response to the GetGrant API call that the action is set to DENY, and this time, the entitlements array contains the entitlements that were denied or revoked.

We can have logic in the Workflow to check if the action is DENY and if so, remove the entitlements in the entitlements array of the GetGrant API response from the target application by calling the application’s APIs. However, the logic that we have in the workflow currently will work as-is, as the user’s principal entitlements will not have the revoked entitlements and since the workflow is set to use that as the source of truth to update the entitlements in the application, these revoked entitlements would be removed in the application.

We can see in the response to the GetPrincipalEntitlements API call in the flow execution history that the user’s principal entitlements contain the Basic license and the App User role as expected (as the other two entitlements were revoked).

Now let’s see what happens when a reviewer revokes an entitlement granted by a Policy instead of revoking an entitlement bundle.

As Marge Simpson, let’s revoke the Basic License entitlement for Shell Simpson that has been granted by the entitlement policy.

After revoking the entitlement, if we look at the closed reviews for the access certification campaign, we can see that Okta could not remove the entitlement for the user in response to the reviewer revoking this entitlement, and it has been marked for manual remediation. This is because the entitlement has been assigned by Policy.

In the Okta system logs, we can see that the access certification review decision (REVOKE) was processed successfully, however the access certification review remediation was skipped, unlike the last time where it was successful, which is why manual remediation is required. This is by virtue of the entitlement being assigned by Policy.

This time, the user entitlement updated successfully event was not logged as the user’s entitlement was not removed.

It is important to review entitlements granted through all sources (Policy, Custom & entitlement bundles) and organizations are often required to for audit and compliance purposes, however when an entitlement granted through a policy is revoked, it is better to remediate it manually. Policy grants reflect an organization’s business rules and if a user was granted an entitlement by a policy which needs to be revoked, the policy rules need to be reviewed for any errors that granted the entitlement in the first place. And if the admin chooses to modify the policy rules to revoke the entitlement, that would log the user entitlement updated successfully event in the system log, which would be processed by our workflow to revoke the entitlement in the target application (we covered this scenario before in this article).

We did not cover access reviews for entitlements assigned by selecting Custom as the entitlement assignment method, but that would work the same way as entitlements granted by entitlement bundles. When a reviewer revokes a custom entitlement, that would generate the same event type in the system log, which would trigger our workflow to revoke the entitlement in the target application.

Conclusion

In this article, we went over how entitlements can be managed for applications for which Okta Identity Governance’s Entitlement Management capability is not supported out-of-the-box in the Okta Integration Network. We looked at different ways how entitlements can be assigned such as entitlement policy, custom & entitlement bundles and how we can automate provisioning entitlements in the target application for each of these scenarios. We also looked at how updates to entitlements triggered by changes to entitlement policy rules or entitlement bundles or updating custom entitlements can be propagated to the target application. Finally, we looked at how revocation of entitlements by unassigning users from applications or through access reviews can be propagated to the target application. Thus, we can implement similar Entitlement Management capabilities for custom applications as what Okta supports out-of-the-box for a limited number of OIN apps. This can also be implemented using the enhanced SCIM 2.0 support for Entitlement Management, however this article covered how we can implement this using Okta event hooks and Okta Workflows.

6 thoughts on “Managing custom entitlements or Bring Your Own (BYO) entitlements using Okta Identity Governance (OIG) Entitlement Management

      1. SS – Unfortunately Sathish is no longer with Okta and we don’t have the Workflows used in this article.

Leave a Reply