# Reassign Object Owners Using IdentityNow Workflows

**URL:** <https://developer.sailpoint.com/discuss/t/reassign-object-owners-using-identitynow-workflows/22371>\
**Category:** Community Blog\
**Tags:** workflows, sailpoint-identity-security\
**Created:** [December 8, 2023, 3:15pm UTC](https://developer.sailpoint.com/discuss/t/reassign-object-owners-using-identitynow-workflows/22371 "2023-12-08T15:15:33Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![colin\_mckibben](https://sea1.discourse-cdn.com/sailpoint/discuss/user_avatar/developer.sailpoint.com/colin_mckibben/32/37182_2.png) [@colin\_mckibben](https://developer.sailpoint.com/discuss/u/colin_mckibben)\
**Post date:** [December 8, 2023, 3:15pm UTC](https://developer.sailpoint.com/discuss/t/reassign-object-owners-using-identitynow-workflows/22371/1 "2023-12-08T15:15:33Z")

</div>

![header-image](https://global.discourse-cdn.com/sailpoint/original/2X/4/4155c4802c472681473e1aa593ad9ec51c1894dd.png)

 

# Introduction

Object ownership in IdentityNow refers to identities that own sources, roles, access profiles, workflows, and more. Object ownership is an important concept in IdentityNow as it identifies the person who is responsible for managing the object, which may involve tasks like manually provisioning entitlements and accounts or certifying access on a source. When an identity changes roles within a company or leaves the company, this creates a scenario where they may no longer be the appropriate owner of one or more of these objects. It is important to proactively reassign the owner of these objects to reduce risk and avoid untimely delays in governance operations.

IdentityNow provides a robust set of APIs that can be used to modify the owner of many of these objects. This blog posts demonstrates how to change the owner for the following items.

- Sources
- Roles
- Access Profiles
- Entitlements
- Identity Profiles
- Governance Groups
- Workflows

> **Applications (Apps)** are not officially supported at this time because the public version of the API is not yet ready. Once there is a public version of the Apps API, we can include them in this list.

Object reassignment can be solved using a programming language of your choice, but I want to demonstrate how Workflows and Forms can be used to accomplish the same task within IdentityNow.

# Understanding the options for looping

## Loop Limits

Before we implement the workflows needed to solve this use case, let’s discuss how we are going to approach this problem and the limitations we need to consider. The first hurdle we will run into trying to implement this in a single workflow is the limit of 100 items for loops. While this limit might not be a problem for certain objects, like sources or identity profiles (who owns more than 100 sources? 😅), other objects, like roles and access profiles could easily exceed that limit. Therefore, we need to plan for a scenario where we need to iterate over more than 100 items to make this a robust solution. Loops is viable for certain objects, like workflow reassignment, but loops will not be a viable solution for others. Therefore, we must look at the alternative iteration method of [recursive workflows](https://developer.sailpoint.com/discuss/t/recursive-workflows-in-identitynow/16235).

## Synchronous recursion

[Synchronous recursion](https://developer.sailpoint.com/discuss/t/recursive-workflows-in-identitynow/16235/1#synchronous-recursion-6) is configured to run synchronously, which means the recursion will process each item in the list in the order in which they are received. For example, if the list `[1,2,3]` is provided to the recursive workflow, it will process `1` first, then `2` , and finally `3`. Most of the object types can utilize synchronous recursion, and the resulting workflow will usually be very simple to build and understand. The only caveat to this approach is that it is much slower than asynchronous recursion since each workflow needs to finish before executing the next workflow in the list.

```mermaid
    flowchart TD
    Z[Invoke workflow with previous and new owner ID] --> A
    A[External Trigger] --> B
    B[Get a source owned by previous owner] --> C{If source was found}
    C -->|no| D[End workflow]
    C -->|yes| E[Change source owner to new owner]
    E --> F
    F[Invoke this workflow with previous and new owner ID again] --> A

```

Synchronous recursion will **not** work if you use the [search API](https://developer.sailpoint.com/idn/api/v3/search-post) to get the list of objects to be reassigned. This is because the search API has a latency between when an action is taken on an object and when the updated data is synced into the search database. If you attempt to use the search API to support synchronous recursion, you may end up in a scenario where the recursion attempts to reassign an object that has already been reassigned, which may result in errors or a significant increase in execution time as it waits for the search database to update.

## Asynchronous recursion

Asynchronous recursion isn’t possible for the the specific use case of object reassignment. A standard recursive workflow requires us to pass the list of data that needs to be processed to each iteration of the recursion. Because of the way inline variables work, you cannot reference arrays in inline variables. This is a problem because the workflow must know two things: The details of the object to reassign, and the ID of the new owner to assign it to.

Synchronous recursion works because we can simply pass the previous and new owner ID to each iteration of recursion, and we can use an operational API, like list sources, to get the next item in the list of objects to reassign within the workflow rather than relying on the items to be passed into the External Trigger as an array. Asynchronous recursion cannot work this way, and we must provide the full array of items to work on to the External Trigger. Since asynchronous recursion requires the full array of items in the trigger payload, we cannot add any context variables, like new owner ID, which would require inline variables and therefore would not work.

You can read more about the [cons of recursion](https://developer.sailpoint.com/discuss/t/recursive-workflows-in-identitynow/16235#cons-5) and why this nuance of inline variables matters. Just know that for now we must use synchronous recursion to solve this use case.

# Creating the form

Before we implement our workflows, let’s create the form that will be sent to the identity’s manager. This form will ask the manager to provide a new owner of the objects. Start by navigating to the Forms dashboard and creating a new form.

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/5/5c8d58e910d0eacd5bb66c7acba1f784c293234a.png)

Next, create a `Text Field` with the following configuration:

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/9/9d1f9ae2e30045407febb6a93298bdca05136f83.png)

Apply the changes and then click on the form settings button. Navigate to “Inputs” and create the following input. This input will allow our workflow to supply the name of the previous owner that left the company.

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/2/20f53b32e24346108044125bd6ecab9c071ea6cf.png)

Click on “Conditions” and create the following condition. This will disable the previous owner text field so the recipient of the form knows that it can’t be modified and is only there for informational purposes.

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/5/54c0fb82ee0b6741e24ff7bda251b5e842660997.png)

Exit the form settings menu and add a “Select Field” to the form with the following details. This will allow the form recipient to select a new identity to assign the objects to.

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/c/c1ad33e0335a6cb4b8f8c4d22c07aace7986ad49.png)

Make sure you save the form, and then go to the Workflows dashboard to create a new workflow.

# Creating the reassignment workflows

Many of the object types that support reassignment follow very similar steps. Rather than go into detail on how to implement reassignment for each object type, I will cover two scenarios that should allow you to complete the reassignment workflows for all the object types.

## Reassign sources, roles, access profiles, and entitlements

This method will require a separate workflow that will be invoked by the main workflow. It will also require a non-search API that can filter the results by `owner.id`. For example, [list sources](https://developer.sailpoint.com/idn/api/v3/list-sources), [list access profiles](https://developer.sailpoint.com/idn/api/v3/list-access-profiles), [list roles](https://developer.sailpoint.com/idn/api/v3/list-roles), and [list entitlements](https://developer.sailpoint.com/idn/api/beta/list-entitlements) can all be reassigned since they support the `owner.id` filter param.

To demonstrate this method, create a new workflow called “Reassign Sources” and add the “External Trigger” as the first step. Generate a “New Access Token” and save the “Client ID”, “Client Secret”, and “Client URL” somewhere safe so you can reference them later. This external trigger will expect the following input to be provided when it is invoked:

```json
{
    "previousOwnerId": "1de880867624cbd7017642d8c8c81f67",
    "newOwnerId": "3bd180867624cbd7017642d8c8c9ffca"
}

```

`previousOwnerId` is the identity ID of the identity that left the company, and `newOwnerId` is the identity ID of new owner of the sources.

Next, add an “HTTP Request” action beneath the trigger. This action will be used to fetch the first source owned by the `reassignFrom` identity using the [list sources](https://developer.sailpoint.com/idn/api/v3/list-sources) endpoint. Configure it as follows.

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/4/40eff1c91b14c7591b80aa4b7a720d559f8ea7e3.png)

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/f/f895b94c5f902046c569bc076c7513baa5c4fe2e.png)

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/9/9ff5f7a8719dd143931fc70d988186a59cd7fe8d.png)

- **Token URL** is in the following format: `https://{tenant}.api.identitynow.com/oauth/token`
- **Client ID and Client Secret** are the obtained from your personal access token. See [this guide](https://developer.sailpoint.com/idn/api/authentication#generate-a-personal-access-token) for more information on generating a PAT.
- **Request URL** is `https://{tenant}.api.identitynow.com/v3/sources?filters=owner.id%20eq%20%22{{$.trigger.previousOwnerId}}%22&limit=1`
- Leave the **Request Content Type** empty

After the HTTP Request, we need to check if a source was returned or not. This comparison operator will determine how we proceed with execution. If an item was returned, then we reassign the owner and execute this same workflow again to see if there is another source to reassign. If there was no item returned, then there are no more sources to reassign and we can end the recursive loop. Configure the comparison operator as follows.

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/9/9ccd75b986872894e70f27ce1477fa3419f0efdb.png)

If this comparison evaluates to `True` then we need to reassign the source owner using an HTTP Request action to call the [source update endpoint](https://developer.sailpoint.com/idn/api/v3/update-source). Add a new HTTP Request action beneath the “True” branch of the comparison operator, and configure it as follows.

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/6/69d17e0740dee63cd859311bdb91f66965cafe7a.png)

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/c/c6e28f6f36350a58b750998e1ef8f02984b44155.png)

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/c/c9385726f215c55cd2dbe4851b42dcb2145969c2.png)

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/9/9623494fea26cbf271bc9291be6478cffe420db6.png)

- The Authentication section should be setup exactly like the first HTTP Request.
- **Request URL** is `https://{tenant}.api.identitynow.com/v3/sources/{{$.hTTPRequest.body[0].id}}`
- **Request Body** is `[{"op":"replace","path":"/owner","value":{"id":"{{$.trigger.newOwnerId}}"}}]`

The last step in this workflow is to invoke this workflow again to reassign any remaining sources that the identity was an owner of. This is the “recursive” part of the workflow where it will invoke itself to mimic looping. To invoke this same workflow, create one final HTTP Request action beneath the “HTTP Request 1” action and configure it as follows.

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/2/2f241dcffb462319352997c389a03696641a67f4.png)

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/0/05d10d83645bbfce9e1684ae8b4dee234c5b8589.png)

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/6/6819b18ed9220230cf6a195dd10aae0cfc420e9e.png)

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/8/8ccf3f92c195c2ab1a4565f6ef6d189123f0f4e9.png)

- **Token URL** will be the same as the other two HTTP Requests.
- **Client ID and Client Secret** will be the values you saved when generating the access token for the External Trigger. This will **not** be your PAT credentials.
- **Request URL** will be the URL that you saved when generating the access token for the External Trigger. It should look similar to this: `https://devrel.api.identitynow.com/beta/workflows/execute/external/c79e0079-562c-4df5-aa73-xxxxxxxxxx`
- **Request Body** will be the exact same information that was received by the External Trigger.

Once all steps are configured, your finished source reassignment workflow should look like this.

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/3/375b866acf4b0a116421054cd536d5c241929b15.png)

To implement access profiles, roles, and entitlements, simply duplicate the “Reassign Sources” workflow for each and modify the URLs accordingly. You will also need to generate a new access token for the External Trigger for each and update the last HTTP Request to use the new client credentials and URL.

## Reassign identity profiles

Unlike “Reassign Sources”, the identity profiles endpoint doesn’t support filtering by `owner.id`. This complicates things, and it makes recursion impossible. However it is still possible to implement this without recursion and using regular loops. Before we can proceed, you must determine the upper range of identity profiles that you can have in your environment. For example, let’s assume you will never have more than 150 identity profiles in your environment. This may seem like a very high number, but it will allow me to demonstrate how to use pagination to feed the loops data in 100 item increments.

To demonstrate this method, create a new workflow called “Reassign Identity Profiles” and add the “External Trigger” as the first step. Generate a “New Access Token” and save the “Client ID”, “Client Secret”, and “Client URL” somewhere safe so you can reference them later. This external trigger will expect the following input to be provided when it is invoked:

```json
{
    "previousOwnerId": "1de880867624cbd7017642d8c8c81f67",
    "newOwnerId": "3bd180867624cbd7017642d8c8c9ffca",
    "offset": 0
}

```

- `previousOwnerId` is the identity ID of the identity that left the company
- `newOwnerId` is the identity ID of new owner of the sources.
- `offset` is the pagination offset that will be used to fetch the next 100 items for the loop.

Since [list identity profiles](https://developer.sailpoint.com/idn/api/v3/list-identity-profiles) doesn’t support the `owner.id` filter param, we must invoke the appropriate number of HTTP Request calls to meet our maximum, in this case 150. These invocations will happen in the main workflow, so we don’t need to worry about them quite yet. Instead, this workflow will handle the steps for fetching the next 100 items from the supplied offset and reassigning each object accordingly. Add a single HTTP Request below the External Trigger, and configure it accordingly:

- Add your PAT details to the authentication section. This is detailed in the “Reassigning Sources” section above.
- Set the **Request URL** to `https://{tenant}.api.identitynow.com/v3/identity-profiles?limit=100&offset={{$.trigger.offset}}&sorters=name`. Replace `{tenant}` with your tenant name. This will get 100 items from the offset provided in the trigger input.

Next, add a loop below the HTTP Request and configure it as follows:

- **Loop Input** is `$.hTTPRequest.body`
- **Loop Context** is `$.trigger`

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/7/7add6d59dbf0c1387ce0b441049f13297e7f758c.png)

Inside the loop, add a Compare Strings operator, and configure it as follows:

- **Value 1** is `$.loop.loopInput.owner.id`
- **Comparison Operator** is “Equals”
- **Value 2** should be a “Choose Variable” with `$.loop.context.previousOwnerId` as the value.

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/f/f00e9cf45b9f598085c1d47b0975fee09eba11e8.png)

Setup the two branches as follows.

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/5/58ab9f4c653fcf387704685f0532566032bc9e9c.png)

HTTP Request 1 should be configured as follows to allow it to update the identity profile to the new owner.

- Configure the authentication the same as the first HTTP Request.
- **Request URL** is `https://{tenant}.api.identitynow.com/beta/identity-profiles/{{$.loop.loopInput.id}}`. Replace `{tenant}` with your tenant name.
- **Method** is “PATCH”
- **Request Body** is:

```json
[
  { 
    "op":"replace",
    "path":"/owner",
    "value": {
      "id":"{{$.loop.context.newOwnerId}}"
    }
  }
]

```

The final workflow should look like this.

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/9/918f6623906f1a330989b0aa8078fb5cc5c76437.png)

To invoke this workflow from the main workflow, simply add the appropriate number of HTTP Requests to the main workflow to cover the maximum number of identity profiles your environment can have. If your confident your environment won’t have more than 150, then the first HTTP Request will send this payload to the External Trigger of this workflow.

```json
{
  "previousOwnerId": "{identity ID}",
  "newOwnerId": "{identity ID}",
  "offset": 0
}

```

This will allow the first invocation of the workflow to retrieve and process the first 100 identity profiles.

The second HTTP Request will advance the offset by 100 so the workflow can retrieve and process the next 100 items.

```json
{
  "previousOwnerId": "{identity ID}",
  "newOwnerId": "{identity ID}",
  "offset": 100
}

```

Just keep sending HTTP Requests and advancing the offset by 100 until you reach your desired limit. This is a brute force approach to the problem, but given the fact that there should not be many identity profiles it is very feasible to do this.

## Reassigning governance groups

Reassigning governance groups works the same as identity profiles. You must determine the upper limit for the number of governance groups you expect to have in your tenant, and then invoke the workflow for each set of 100 governance groups (determined by the `offset`) until you reach that limit. Use [list governance groups](https://developer.sailpoint.com/idn/api/beta/list-workgroups) to get each page of 100 governance groups, and use [update governance group](https://developer.sailpoint.com/idn/api/beta/patch-workgroup) to change the owner. If you are certain that identities will never have more than 100 governance groups, then you can skip the pagination using list governance groups and instead make a single API call to the search API. The query you will use is as follows.

```json
{
    "indices": [
        "identities"
    ],
    "query": {
        "query": "2c9180867624cbd7017642d8c8c81f67"
    },
    "queryResultFilter": {
        "includes": [
            "owns.governanceGroups"
        ]
    }
}

```

This will produce the following response:

```json
[
    {
        "owns": {
            "governanceGroups": [
                {
                    "name": "Test Group",
                    "id": "7b7a4d82-fad4-46ec-8d5a-842843d09f0e"
                },
                {
                    "name": "Test Group 2",
                    "id": "12538ecf-60d0-44b4-9273-d1ba578ef384"
                }
            ]
        },
        "_type": "identity",
        "type": "identity",
        "_version": "v7"
    }
]

```

You can then loop over the `governanceGroups` to quickly reassign them. This strategy of using the search API to reassign objects that will not have more than 100 items for a given identity can also be used for entitlements, sources, access profiles, and roles.

## Reassigning workflows

Reassigning workflow owners is a rather simple affair and does not require pagination or recursion. Since workflows are limited to 100 objects per tenant at this time, a single loop can handle the reassignment. As with the other reassignment workflows, begin by creating a new workflow called “Reassign Workflows” and add an External Trigger. Generate a new access token for the trigger and save the details somewhere safe. This trigger will accept the following payload.

```json
{
  "previousOwnerId": "{identity ID}",
  "newOwnerId": "{identity ID}"
}

```

Next, add an HTTP request that will invoke the following GET endpoint, replacing `{tenant}` with your tenant name.

`https://{tenant}.api.identitynow.com/beta/workflows`

Next, add a loop to the workflow and configure it as follows:

- **Loop Input** is `$.hTTPRequest.body`
- **Context** is `$.trigger`

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/c/c2b07f31cb0c1867b61df6767c0e221c64d5b182.png)

Inside the loop, add a Compare Strings operator, and configure it as follows:

- **Value 1** is `$.loop.loopInput.owner.id`
- **Comparison Operator** is “Equals”
- **Value 2** should be a “Choose Variable” with `$.loop.context.previousOwnerId` as the value.

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/f/f00e9cf45b9f598085c1d47b0975fee09eba11e8.png)

Setup the two branches as follows.

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/5/58ab9f4c653fcf387704685f0532566032bc9e9c.png)

HTTP Request 1 should be configured as follows to allow it to update the identity profile to the new owner.

- Configure the authentication the same as the first HTTP Request.
- **Request URL** is `https://{tenant}.api.identitynow.com/beta/workflows/{{$.loop.loopInput.id}}`. Replace `{tenant}` with your tenant name.
- **Method** is “PATCH”
- **Request Body** is:

```json
[
  { 
    "op":"replace",
    "path":"/owner",
    "value": {
      "id":"{{$.loop.context.newOwnerId}}",
      "type": "IDENTITY"
    }
  }
]

```

The final workflow should look like this.

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/9/918f6623906f1a330989b0aa8078fb5cc5c76437.png)

When invoking this workflow from the main workflow, simply provide the previous and the new owner ID in the payload.

```json
{
  "previousOwnerId": "{identity ID}",
  "newOwnerId": "{identity ID}"
}

```

# Creating the main workflow

The main workflow will most likely be triggered by Identity Attributes changed event where the lifecycle state has changed to a leaver value, like “terminated”. It’s always a good idea to add a trigger filter to avoid invoking workflows for events that you don’t want to process. For this trigger, we will add the following filter so we only execute this workflow when an identity is terminated.

`$.changes[?(@.attribute == "cloudLifecycleState" && @.newValue == "terminated")]`

Your trigger should look like this.

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/0/00fb57da815c87507aa57ef168f9f243ec5b1f4e.png)

Next, add a Get Identity action below the trigger. Configure this action to get the details of the terminated identity.

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/a/a73f66114741a1c07ad93fe14ead1e186825cdfd.png)

This trigger and Get Identity will provide us with the name and ID of the terminated identity and their manager, which we will use to send the form we created earlier to the manager. Add a “Form” action beneath the trigger, and configure it as follows.

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/2/2a553689f4ebf214ba6f62e810fea9b6d0bec36a.png)

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/6/6b7c3a6b24e9b74873ae080432253969eacec1d3.png)

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/c/cae41815d1a1cc7b2ada283c0e25c6d7408574d2.png)

Once the manager submits the form, the workflow will resume with the identity of the new owner. The next step is to begin invoking the External Trigger of each reassignment workflow to start processing the reassignment.

## Invoke source, entitlement, access profile, and role reassignments

Source, entitlement, access profile, and role reassignments will each have their own separate workflow that will need to be invoked by their External Trigger. To invoke each of these reassignment workflows, simply. add an HTTP Request for each one after the Form action and configure it as follows.

- **Authentication Type** is “OAuth 2.0 - Client Credentials Grant”
- **Token URL** is `https://{tenant}.api.identitynow.com/oauth/token`. Replace `{tenant}` with your tenant name.
- **Client ID** is the client ID generated from the External Trigger for the particular workflow you are invoking.
- **Client Secret** is the client secret generated from the External Trigger for the particular workflow you are invoking.
- **Request URL** is the URL generated from the External Trigger for the particular workflow you are invoking.
- **Method** is “POST”
- **Request Content Type** is “JSON”
- **Request Body** is

```json
{
  "previousOwnerId":"{{$.trigger.identity.id}}",
  "newOwnerId": "{{$.form.formData.newOwner}}"
}

```

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/9/9b57d6025f11bf7c5e871215ea9b36d326d9a6dc.png)

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/e/e9f45c2f23ffea7b6544985b0ce82235764f5fc6.png)

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/7/7a17a25b834acfc70198695bfe060917ab8569c2.png)

If you are reassigning all four object types, then you should have four HTTP Requests. Your workflow will look like this so far.

 ![image](https://global.discourse-cdn.com/sailpoint/original/2X/c/caf1e8013915cc19c1a57a65a9cdbe453a6090c5.png)

## Invoke identity profiles reassignment

To invoke the identity profiles reassignment workflow, add an HTTP Request action and configure it to invoke the External Trigger of the identity profiles reassignment workflow. The payload for should be as follows:

```json
{
  "newOwnerId": "{{$.form.formData.newOwner}}",
  "previousOwnerId": "{{$.trigger.identity.id}}",
  "offset": 0
}

```

If your organization can have more than 100 identity profiles, then copy this action as many times as necessary to reach the limit of your org. For example, if your org may have up to 300 identity profiles, copy this action twice and increase each offset by 100. The payloads for each copy would look like this.

```json
{
  "newOwnerId": "{{$.form.formData.newOwner}}",
  "previousOwnerId": "{{$.trigger.identity.id}}",
  "offset": 100
}

```

```json
{
  "newOwnerId": "{{$.form.formData.newOwner}}",
  "previousOwnerId": "{{$.trigger.identity.id}}",
  "offset": 200
}

```

## Invoke governance groups reassignment

Invoking the governance group reassignment workflow is the same as invoking the identity profiles reassignment workflow. You must determine up front how many governance groups you expect to have in your tenant in order to know how many HTTP Requests to create to invoke the reassignment workflow. For example, if your tenant will never have more than 250 governance groups, then you will need three HTTP Requests, which will be configured the same as identity profiles above. The only difference is that you must configure the HTTP Request to use the client credentials for your governance group reassignment workflow.

## Invoke workflows reassignment

Invoking the workflows reassignment workflow is exactly the same as for sources, roles, access profiles, and entitlements. Configure a single HTTP Request to use the credentials of the External Trigger for the workflows reassignment workflow, and send a POST request with the following request body.

```json
{
  "newOwnerId": "{{$.form.formData.newOwner}}",
  "previousOwnerId": "{{$.trigger.identity.id}}"
}

```

---

<div class="post-metadata">

**Author:** ![cassidiopia](https://sea1.discourse-cdn.com/sailpoint/discuss/user_avatar/developer.sailpoint.com/cassidiopia/32/13198_2.png) [@cassidiopia](https://developer.sailpoint.com/discuss/u/cassidiopia)\
**Post date:** [December 13, 2023, 5:41pm UTC](https://developer.sailpoint.com/discuss/t/reassign-object-owners-using-identitynow-workflows/22371/2 "2023-12-13T17:41:49Z")

</div>

@colin_mckibben This is pretty cool, thanks for building and sharing. Just curious, do you know about the roadmap to add HTTP response handling into Workflows? Currently, if there isn’t a 2\*\* response, the Workflow fails. Some API endpoints return data with 4\*\* responses and would like to know when IDN can handle those.

---

<div class="post-metadata">

**Author:** ![tburt](https://sea1.discourse-cdn.com/sailpoint/discuss/user_avatar/developer.sailpoint.com/tburt/32/8984_2.png) [@tburt](https://developer.sailpoint.com/discuss/u/tburt)\
**Post date:** [December 13, 2023, 9:13pm UTC](https://developer.sailpoint.com/discuss/t/reassign-object-owners-using-identitynow-workflows/22371/3 "2023-12-13T21:13:20Z")

</div>

Hello Nicholas. We have a backlog roadmap item to handle this by allowing admins to specify the action/activity when an error is returned, i.e. Continue On Error as opposed to existing/failing. I cannot commit to a given date for now but would you mind submitting some additional details around how you would want to handle the response?

Also could you add comments and votes to this IDEA:  
[https://ideas.sailpoint.com/ideas/GOV-I-1912](https://ideas.sailpoint.com/ideas/GOV-I-1912)

---

<div class="post-metadata">

**Author:** ![cassidiopia](https://sea1.discourse-cdn.com/sailpoint/discuss/user_avatar/developer.sailpoint.com/cassidiopia/32/13198_2.png) [@cassidiopia](https://developer.sailpoint.com/discuss/u/cassidiopia)\
**Post date:** [December 13, 2023, 10:00pm UTC](https://developer.sailpoint.com/discuss/t/reassign-object-owners-using-identitynow-workflows/22371/4 "2023-12-13T22:00:56Z")

</div>

Thanks @tburt! I actually don’t know that this idea would meet my needs exactly. I would want to be able to receive the response code and any response body (if one exists) and be able to carry on the workflow based on data. I have one use case that can just move on when the response is not a 2\*\* (it currently just fails) and another that would need to assess the response body, which contains “No users found.” I did vote that one, as it would be useful in itself. Thanks again.

---

<div class="post-metadata">

**Author:** ![tburt](https://sea1.discourse-cdn.com/sailpoint/discuss/user_avatar/developer.sailpoint.com/tburt/32/8984_2.png) [@tburt](https://developer.sailpoint.com/discuss/u/tburt)\
**Post date:** [December 14, 2023, 8:48pm UTC](https://developer.sailpoint.com/discuss/t/reassign-object-owners-using-identitynow-workflows/22371/5 "2023-12-14T20:48:26Z")

</div>

@cassidiopia

The response codes do/should live in the execution log of the workflow today (again caveat on whether or not the application returns the response details). The issue is that most 400 errors are not something that would typically require a retry. Things like bad request, unauthorized, forbidden, etc… are not something we would want to issue a retry for. We do, however, already handle some of the 500 error types as retry natively on the backend. Again things that make sense like Service Unavailable, Gateway Timeout, etc… are automatically retried.

Having said all of that, I believe the real value add would be to allow admins the ability to configure how they want the workflow to proceed when some of these errors are hit. For example you could configure the “Continue on error” option and pass the 401 “Unauthorized” error into a follow on comparison and send an email notifying someone as opposed to exiting the workflow. This is the AHA idea referenced above.

Again, the execution logs will pick up and capture any response codes if the application returns that response detail.

---

<div class="post-metadata">

**Author:** ![cassidiopia](https://sea1.discourse-cdn.com/sailpoint/discuss/user_avatar/developer.sailpoint.com/cassidiopia/32/13198_2.png) [@cassidiopia](https://developer.sailpoint.com/discuss/u/cassidiopia)\
**Post date:** [December 14, 2023, 9:00pm UTC](https://developer.sailpoint.com/discuss/t/reassign-object-owners-using-identitynow-workflows/22371/6 "2023-12-14T21:00:53Z")

</div>

Ahh, yes, that makes sense. I was under-thinking it from the POV of it resolving timeout issues, but the functionality would do the same. I’m aware the response code and body are currently logged, so just being able to continue on would be the win!

Thanks!

---

<div class="post-metadata">

**Author:** ![Dianna\_Hutchcroft](https://avatars.discourse-cdn.com/v4/letter/d/91b2a8/32.png) [@Dianna\_Hutchcroft](https://developer.sailpoint.com/discuss/u/Dianna_Hutchcroft)\
**Post date:** [June 25, 2024, 10:04pm UTC](https://developer.sailpoint.com/discuss/t/reassign-object-owners-using-identitynow-workflows/22371/7 "2024-06-25T22:04:02Z")

</div>

Can this workflow or a similar one be utilized to reassign Tasks that remain assigned to an identity in a terminated state? Setting up a reassignment after the fact will only affect new work tasks. As an admin, it would be great to be able to oversee/override such things in the UI to be able to push tasks along as needed.

---

<div class="post-metadata">

**Author:** ![colin\_mckibben](https://sea1.discourse-cdn.com/sailpoint/discuss/user_avatar/developer.sailpoint.com/colin_mckibben/32/37182_2.png) [@colin\_mckibben](https://developer.sailpoint.com/discuss/u/colin_mckibben)\
**Post date:** [July 23, 2024, 4:51pm UTC](https://developer.sailpoint.com/discuss/t/reassign-object-owners-using-identitynow-workflows/22371/8 "2024-07-23T16:51:10Z")

</div>

Without digging deeper into the APIs required to do this, it sounds like a similar and plausible use case for workflows to handle.

---

<div class="post-metadata">

**Author:** ![adamian](https://avatars.discourse-cdn.com/v4/letter/a/a183cd/32.png) [@adamian](https://developer.sailpoint.com/discuss/u/adamian)\
**Post date:** [December 17, 2024, 11:54am UTC](https://developer.sailpoint.com/discuss/t/reassign-object-owners-using-identitynow-workflows/22371/9 "2024-12-17T11:54:40Z")

</div>

> [@colin\_mckibben](#):
>
> Exit the form settings menu and add a “Select Field” to the form with the following details. This will allow the form recipient to select a new identity to assign the objects to.
> 
> ![image](https://global.discourse-cdn.com/sailpoint/original/2X/c/c1ad33e0335a6cb4b8f8c4d22c07aace7986ad49.png)

Hi @colin_mckibben, it seems that inactive identities are included for selection. Am I missing some setting to exclude them? Is this a desired behavior?

---

<div class="post-metadata">

**Author:** ![colin\_mckibben](https://sea1.discourse-cdn.com/sailpoint/discuss/user_avatar/developer.sailpoint.com/colin_mckibben/32/37182_2.png) [@colin\_mckibben](https://developer.sailpoint.com/discuss/u/colin_mckibben)\
**Post date:** [December 17, 2024, 2:22pm UTC](https://developer.sailpoint.com/discuss/t/reassign-object-owners-using-identitynow-workflows/22371/10 "2024-12-17T14:22:19Z")

</div>

You can change the “Option Type” to be “Search” and then create a search query to only return the identities you want to be selectable.

 ![image](https://global.discourse-cdn.com/sailpoint/original/3X/e/c/ec5871d1c13f0937fc3153b329e3086c802bbe41.png)

---

<div class="post-metadata">

**Author:** ![adamian](https://avatars.discourse-cdn.com/v4/letter/a/a183cd/32.png) [@adamian](https://developer.sailpoint.com/discuss/u/adamian)\
**Post date:** [December 18, 2024, 8:37am UTC](https://developer.sailpoint.com/discuss/t/reassign-object-owners-using-identitynow-workflows/22371/11 "2024-12-18T08:37:03Z")

</div>

Thanks for your reply, @colin_mckibben .

> [@colin\_mckibben](#):
>
> You can change the “Option Type” to be “Search” and then create a search query to only return the identities you want to be selectable.

It would be nice to have a solution without limitations. If you want to select all active users, using the search query you are limiting the number of users you can have in the dropdown box, right?

> If the search query returns more than 10,000 items, only the first 10,000 items will be returned.

Fortunately we haven’t reached this limitation in the current project, but nonetheless, it’s a bummer to take into consideration all this limitations (loops, number of users, active/inactive users, …)

On the release notes from Nov 18, 2024 ( [https://community.sailpoint.com/t5/SaaS-Release-Notes/tkb-p/saas-release-notes](https://community.sailpoint.com/t5/SaaS-Release-Notes/tkb-p/saas-release-notes) ) it was mentioned that all dropdown lists would filter out inactive identities. Why is here not the case? Is this a known bug?

> When selecting an identity from a dropdown list, inactive identities are filtered out on all pages except for the Update Correlation overlay of the Account Management UI.

---

<div class="post-metadata">

**Author:** ![adamian](https://avatars.discourse-cdn.com/v4/letter/a/a183cd/32.png) [@adamian](https://developer.sailpoint.com/discuss/u/adamian)\
**Post date:** [January 2, 2025, 8:14am UTC](https://developer.sailpoint.com/discuss/t/reassign-object-owners-using-identitynow-workflows/22371/12 "2025-01-02T08:14:13Z")

</div>

As we invested some time to build on this workflow, and failed, maybe this information will help others:

- You can not use a dynamically calculated **form submission deadline**

> [@ISC: Workflows Form - can't use variable as deadline](https://developer.sailpoint.com/discuss/t/isc-workflows-form-cant-use-variable-as-deadline/94159/4):
>
> SailPoint Support: I checked with the engineering team and here is what they have to say: Inline variable is not supported in deadline for forms. The form submission deadline is looking for an absolute value from 1-30 days or maximum of 30 days 720 hours. The Variable getting a validation error seems accurate as we would not be able to set a deadline that exceeds those documented maximums. I ask myself how this UI change passed the QA test.

- You can not customize the e-mail subject for the form submission reminder and expiration.

> [@ISC: Workflows Form customization](https://developer.sailpoint.com/discuss/t/isc-workflows-form-customization/94149):
>
> What problem are you observing? Not all form ( [Actions - SailPoint Identity Services](https://documentation.sailpoint.com/saas/help/workflows/workflow-actions.html#form) ) emails can be customized / translated. Allowing customization: The reminder message can not be disabled. If the functionality is kept like this, and you select a dead line of one hour, you have to select a reminder deadline of exactly of one hour (it can not be 0 or bigger than the deadline). At the same time two messages will be sent after one hour: the reminder and the cancellation message, b…

- Information for FormData while testing is misleading

> [@ISC Workflows: formData is empty in the step output of Form](https://developer.sailpoint.com/discuss/t/isc-workflows-formdata-is-empty-in-the-step-output-of-form/94465):
>
> What problem are you observing? While trying to create a similar workflow to the one described on this page [Reassign Object Owners Using IdentityNow Workflows](https://developer.sailpoint.com/discuss/t/reassign-object-owners-using-identitynow-workflows/22371) I have noticed that the formData step output is an empty object, even if the user has submitted the form with data. This incorrect information is confusing and makes debugging a lot harder than it should be. formData is empty in the Workflow execution as well, so it may be impossible to debug what exactly the user selected on t…

- Form action doesn’t behave as documented on deadline

> [@ISC Workflows: Form action doesn't behave as documented on deadline](https://developer.sailpoint.com/discuss/t/isc-workflows-form-action-doesnt-behave-as-documented-on-deadline/94477):
>
> What problem are you observing? From [Actions - SailPoint Identity Services](https://documentation.sailpoint.com/saas/help/workflows/workflow-actions.html#form) If the form is not submitted before the configured deadline the workflow will encounter an error and stop. From what I can see the workflow will not error out and stop. What is the correct behavior? Documentation matches the actual behaviour, and vice-versa. What product feature is this related to? ISC Workflows What are the steps to reproduce the issue? Create workflow Add Form action Test workflow, wait until t…

---

<div class="post-metadata">

**Author:** ![ChristopherS](https://avatars.discourse-cdn.com/v4/letter/c/898d66/32.png) [@ChristopherS](https://developer.sailpoint.com/discuss/u/ChristopherS)\
**Post date:** [January 8, 2026, 5:38pm UTC](https://developer.sailpoint.com/discuss/t/reassign-object-owners-using-identitynow-workflows/22371/13 "2026-01-08T17:38:28Z")

</div>

Hi @colin_mckibben / [@community\_managers](https://developer.sailpoint.com/discuss/groups/community_managers) , the link to the Workflow files doesn’t work, and I don’t see this in the Colab Workflows section either. Can this be made available again so others don’t have to re-create it from scratch?

---

<div class="post-metadata">

**Author:** ![tyler\_mairose](https://sea1.discourse-cdn.com/sailpoint/discuss/user_avatar/developer.sailpoint.com/tyler_mairose/32/30112_2.png) [@tyler\_mairose](https://developer.sailpoint.com/discuss/u/tyler_mairose)\
**Post date:** [January 15, 2026, 8:56pm UTC](https://developer.sailpoint.com/discuss/t/reassign-object-owners-using-identitynow-workflows/22371/15 "2026-01-15T20:56:33Z")

</div>

Hey Christopher!

While it’s not the exact workflow, I added similar functionality to our SailPoint cli where you could automate this process as well!

> **[Reassign | SailPoint Developer Community](https://developer.sailpoint.com/docs/tools/cli/reassign/)**
>
> Learn how to use the CLI to reassign the owner on objects in Identity Security Cloud.

---

<div class="post-metadata">

**Author:** ![ChristopherS](https://avatars.discourse-cdn.com/v4/letter/c/898d66/32.png) [@ChristopherS](https://developer.sailpoint.com/discuss/u/ChristopherS)\
**Post date:** [January 15, 2026, 9:20pm UTC](https://developer.sailpoint.com/discuss/t/reassign-object-owners-using-identitynow-workflows/22371/16 "2026-01-15T21:20:03Z")

</div>

Thanks for the enhancement @tyler_mairose !

---

<div class="post-metadata">

**Author:** ![mario\_rod](https://avatars.discourse-cdn.com/v4/letter/m/50afbb/32.png) [@mario\_rod](https://developer.sailpoint.com/discuss/u/mario_rod)\
**Post date:** [March 16, 2026, 3:31pm UTC](https://developer.sailpoint.com/discuss/t/reassign-object-owners-using-identitynow-workflows/22371/17 "2026-03-16T15:31:52Z")

</div>

@tyler_mairose Is there any existing functionality to make this CLI object reassignment functionality available in a **form** so that a manager (or any other identity who’s taking ownership) can execute this?

I don’t want to do all this in a workflow, so just wondering if there’s a way to use what’s already been developed w/out reinventing the wheel

Thanks
