Identity Cloud

Object modeling

IDM provides a default schema for typical managed object types, such as users and roles. This section provides information on how to change and add to the managed object schema, establish relationships between objects, and use policies to validate objects. You will also learn how to access IDM objects using queries.

Managed objects

These topics describe how to work with managed object types:

The IDM object model includes other object types besides managed objects.

For more information, refer to Data models and objects reference.

Define managed object schema

Managed objects and their properties are defined in the default IDM managed object schema.

The default schema includes these types of managed objects:

Each managed object type contains properties for storing information about objects of that type. For example, the user object type has properties for storing usernames, passwords, email addresses, and so forth.

You can extend the default IDM managed object schema to meet your needs:

To store custom data for users, you can add custom attributes (non-searchable) or adapt one of the general purpose extension attributes (searchable). Refer to Customize user identities.

ForgeRock recommends that you do not delete the default managed objects in your tenant. In many cases it can break your tenant.

The IDM admin UI depends on the presence of the default managed object types and the default properties nested within them. If you remove any of these schema elements, and you use the IDM admin UI to configure IDM, you must modify the IDM admin UI code accordingly. For example, if you remove the assignment object type from the managed object configuration, the UI will throw exceptions wherever it queries this schema element.

To interact with a managed object schema via REST, refer to Schema.

Create and modify object types

If the managed object types provided in the default configuration are not sufficient for your deployment, you can create new ones. To do this through the Identity Cloud admin UI:

  1. From the Identity Cloud admin UI, select Native Consoles > Identity Management.

  2. Select Configure > Managed Objects > New Managed Object.

  3. On the New Managed Object page, enter a name and readable title for the object, make optional changes, as necessary, and click Save. The readable title specifies what the object will be called in the UI.

  4. On the Properties tab, specify the schema for the object type (the properties that make up the object).

  5. On the Scripts tab, specify any scripts that will be applied on events associated with that object type. For example, scripts that will be run when an object of that type is created, updated, or deleted.

You can also create a new managed object type by editing your managed object schema. For more information, refer to Schema.

Example: Phone object created using the IDM admin UI
{
    "name": "Phone",
    "schema": {
        "$schema": "http://forgerock.org/json-schema#",
        "type": "object",
        "properties": {
            "brand": {
                "description": "The supplier of the mobile phone",
                "title": "Brand",
                "viewable": true,
                "searchable": true,
                "userEditable": false,
                "policies": [],
                "returnByDefault": false,
                "pattern": "",
                "isVirtual": false,
                "type": [
                    "string",
                    "null"
                ]
            },
            "assetNumber": {
                "description": "The asset tag number of the mobile device",
                "title": "Asset Number",
                "viewable": true,
                "searchable": true,
                "userEditable": false,
                "policies": [],
                "returnByDefault": false,
                "pattern": "",
                "isVirtual": false,
                "type": "string"
            },
            "model": {
                "description": "The model number of the mobile device, such as 6 plus, Galaxy S4",
                "title": "Model",
                "viewable": true,
                "searchable": false,
                "userEditable": false,
                "policies": [],
                "returnByDefault": false,
                "pattern": "",
                "isVirtual": false,
                "type": "string"
            }
        },
        "required": [],
        "order": [
            "brand",
            "assetNumber",
            "model"
        ]
    }
}

Every managed object type has a name and a schema that describes the properties associated with that object. The name can only include the characters a-z, A-Z, 0-9, and _ (underscore). You can add any arbitrary properties to the schema.

Avoid using the dash character in property names (like last-name) because dashes in names make JavaScript syntax more complex. Rather use "camel case" (lastName). If you cannot avoid dash characters, write source['last-name'] instead of source.last-name in your JavaScript.

Also, managed object properties that contain an underscore (_) are reserved for internal use. Do not create new properties that contain underscores, and do not include these properties in update requests.

Typical property definition fields
title

The name of the property, in human-readable language, used to display the property in the UI.

description

A brief description of the property.

viewable

Specifies whether this property is viewable in the object’s profile in the UI. Boolean, true or false (true by default).

searchable

Specifies whether this property can be searched in the UI. A searchable property is visible within the Managed Object data grid in the End User UI.

Boolean, true or false (false by default).

Do not modify the searchable setting on properties in the default manged object schema in IDM, unless otherwise noted in documentation.
userEditable

Specifies whether users can edit the property value in the UI. This property applies in the context of the End User UI, where users are able to edit certain properties of their own accounts. Boolean, true or false (false by default).

pattern

Any specific pattern to which the value of the property must adhere. For example, a property whose value is a date might require a specific date format.

policies

Any policy validation that must be applied to the property.

required

Specifies whether the property must be supplied when an object of this type is created. Boolean, true or false.

To set an attribute as required:

  1. In the left menu, go to Native Consoles > Identity Management.

  2. Click Configure > Managed Objects and select the managed object, in this case, click Alpha_user. A list of the properties in the managed object displays. The Required column displays which properties Identity Cloud currently requires.

  3. Click on the desired property.

  4. In the Details tab, enable the Required field.

  5. Click Save.

    The required policy is assessed only during object creation, not when an object is updated. You can effectively bypass the policy by updating the object and supplying an empty value for that property. To prevent this inconsistency, set both required and notEmpty to true for required properties. This configuration indicates that the property must exist, and must have a value.
type

The data type for the property value; can be string, array, boolean, integer, number, object, Resource Collection, or null.

If any user might not have a value for a specific property (such as a telephoneNumber), you must include null as one of the property types. You can set a null property type in the IDM admin UI (Configure > Managed Objects > User, select the property, and under the Details tab, Advanced Options, set Nullable to true).

You can also set a null property type in your managed object configuration by setting "type" : '[ "string","null" ]' for that property (where string can be any other valid property type. This information is validated by the policy service.

If you’re configuring a data type of array through the IDM admin UI, you’re limited to two values.

isVirtual

Specifies whether the property takes a static value, or whether its value is calculated "on the fly" as the result of a script. Boolean, true or false.

returnByDefault

For non-core attributes (virtual attributes and relationship fields), specifies whether the property is returned in the results of a query on an object of this type if it is not explicitly requested. Virtual attributes and relationship fields are not returned by default. Boolean, true or false. When the property is in an array within a relationship, always set to false.

default

Specifies a default value if the object is created without passing a value. Default values are available for the following data types, and arrays of those types:

  • boolean

  • number

  • object

  • string

IDM assumes all default values are valid for the schema.

Default values

You can specify default values in the IDM managed object schema. If you omit a value when creating an object, the default value is automatically applied to the object. You can have default values for the following data types, and arrays of those types:

  • boolean

  • number

  • object

  • string

For example, the default IDM managed object schema includes a default value that makes accountStatus:active, which effectively replaces the onCreate script that was previously used to achieve the same result. The following excerpt from the IDM managed object schema displays the default value for accountStatus:

"accountStatus" : {
    "title" : "Status",
    "description" : "Status",
    "viewable" : true,
    "type" : "string",
    "searchable" : true,
    "userEditable" : false,
    "usageDescription" : "",
    "isPersonal" : false,
    "policies" : [
        {
            "policyId": "regexpMatches",
            "params": {
                "regexp": "^(active|inactive)$"
            }
        }
    ],
    "default" : "active"
}
IDM assumes all default values are valid for the schema.

Calculate properties based off other properties

Properties can be derived from other properties within an object. This lets computed and composite values be created in the object. These derived properties are called virtual properties, and their value can be calculated in two ways:

  • Using a script called by the onRetrieve script hook. This script calculates the current value of the virtual property based on the related properties.

    For example, you may want to dynamically update a property that you use for a country code (for phone number purposes). When a user’s record is retrieved, the country code is dynamically calculated based off of the country property of the user’s record.

  • Using a query to identify the relationship fields to traverse to reach the managed objects whose state is included in the virtual property, and the fields in these managed objects to include in the value of the virtual property.

    These properties are called relationship-derived virtual properties.

    You can not create new relationships in Identity Cloud. There are default relationships that exist (for example, between users and roles). For more information, refer to Relationships between objects.

For more information on extending attributes of the user object, refer to idcloud:identities:identity-cloud-identity-schema.adoc#extend_user_identities.

Derive virtual properties using`onRetrieve` scripts

The onRetrieve script hook lets you run a script when the object is retrieved. In the case of virtual properties, this script gets the data from related properties and uses it to calculate a value for the virtual property. For more information about running scripts on managed objects, refer to Extend functionality through scripts.

Relationship-derived virtual properties

Virtual properties can be calculated by IDM based on relationships and relationship notifications. This means that, rather than calculating the current state when retrieved, the managed object that contains the virtual property is notified of changes in a related object, and the virtual property is recalculated when this notification is received. To configure virtual properties to use relationship notifications, there are two areas that need to be configured:

  • The related managed objects must be configured to use relationship notifications. This lets IDM know where to send notifications of changes in related objects.

  • To calculate the value of a virtual property, you must configure which relationships to check, and in which order, a notification of a change in a related object is received. You configure this using the queryConfig property.

The queryConfig property tells IDM the sequence of relationship fields it should traverse in order to calculate (or recalculate) a virtual property, and which fields it should return from that related object. This is done using the following fields:

  • referencedRelationshipFields is an array listing a sequence of relationship fields connecting the current object with the related objects you want to calculate the value of the virtual property from. The first field in the array is a relationship field belonging to the same managed object as the virtual property. The second field is a relationship in the managed object referenced by the first field, and so on.

    Example

    For example, the referencedRelationshipFields for effectiveAssignments is ["roles","assignments"]. The first field refers to the roles relationship field in managed/realm-name_user, which references the managed/realm-name_role object. It then refers to the assignments relationship in managed/realm-name_role, which references the managed/realm-name_assignment object. Changes to either related object (managed/realm-name_role or managed/realm-name_assignment) will cause the virtual property value to be recalculated, due to the notify, notifySelf, and notifyRelationships configurations on managed user, role, and assignment. These configurations ensure that any changes in the relationships between a user and their roles, or their roles, and their assignments, as well as any relevant changes to the roles or assignments themselves, such as the modification of temporal constraints on roles, or attributes on assignments, will be propagated to connected users, so their effectiveRoles and effectiveAssignments can be recalculated and potentially synced.

    • referencedObjectFields is an array of object fields that should be returned as part of the virtual property. If this property is not included, the returned properties will be a reference for the related object. To return the entire related object, use *.

    • flattenProperties is a boolean that specifies whether relationship-derived virtual properties should be returned as plain fields rather than as JSON objects with an _id and a _rev. This property is false by default.

      With flattenProperties set to false, and referencedObjectFields set to name, the response to a query on a user’s effectiveAssignments might look something like this:

      "effectiveAssignments": [
          {
              "name": "MyFirstAssignment",
              "_id": "02b166cc-d7ed-46b7-813f-5ed103145e76",
              "_rev": "2"
          },
          {
              "name": "MySecondAssignment",
              "_id": "7162ddd4-591a-413e-a30b-3a5864bee5ec",
              "_rev": "0"
          }
      ]

      With flattenProperties set to true, and referencedObjectFields set to name, the response to the same query looks like this:

      "effectiveAssignments": [
          "MyFirstAssignment",
          "MySecondAssignment"
      ]

      Setting flattenProperties to true also lets singleton relationship-derived virtual properties be initialized to null.

Using queryConfig, the virtual property is recalculated when it receives a notice that changes occurred in the related objects. This can be significantly more efficient than recalculating whenever an object is retrieved, while still ensuring the state of the virtual property is correct.

When you change which fields to return using referencedObjectFields, changes are not reflected until there is a change in the related object that would trigger the virtual property to be recalculated (as specified by the notify, notifySelf, and notifyRelationships configurations). The calculated state of the virtual property is still correct, but since a change is necessary for the state to be updated, the returned fields will still be based on the previous configuration.

Extend functionality through scripts

Before implementing a script, it’s highly recommended that you validate the script over REST. Use scripts in a test environment before deploying them to a production environment.

A number of script hooks let you manipulate managed objects using scripts. Scripts can be triggered during various stages of the lifecycle of the managed object, and are defined in the managed object schema.

You can trigger scripts when a managed object is:

  • Created (onCreate)

  • Deleted (onDelete)

  • Read (onRead)

  • Retrieved (onRetrieve)

  • Stored in the repository (onStore)

  • Synchronized (onSync)

  • Updated (onUpdate)

  • Validated (onValidate)

Post-action scripts let you manipulate objects after they are:

  • Created (postCreate)

  • Updated (postUpdate)

  • Deleted (postDelete)

For in-depth explanations of the various scripts, refer to managed object configuration properties.

Enable self-service by tracking user metadata

Some self-service features, such as progressive profile completion, privacy and consent, and terms and conditions acceptance, rely on user metadata that tracks information related to a managed object state.

For example, this data might include when the object was created or the date of the most recent change. This metadata is not stored within the object itself but in a separate resource location.

In Identity Cloud, metadata is only tracked for managed/alpha_user and managed/bravo_user managed objects.

If you are not using the self-service features that require metadata, you can remove the meta stanza from the two managed objects in the schema. Preventing the creation and tracking of metadata where it is not required improves performance.

The metadata configuration includes the following properties:

property

The property dynamically added to the managed object schema for this object.

resourceCollection

The resource location where the metadata is stored.

Metadata is stored under ou=usermeta,ou=internal,dc=openidm,dc=forgerock,dc=com by default.

You must include the ou specified in the preceding dnTemplate attribute.

trackedProperties

The properties tracked as metadata for this object. In the following example, the createDate (when the object was created) and the lastChanged date (when the object was last modified) are tracked.

You cannot search on metadata, and it is not returned by the results of a query, unless it is specifically requested. To return all metadata for an object, include _fields=,_meta/* in your request. The following example returns a user entry without requesting the metadata:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/bjensen"
{
  "_id": "bjensen",
  "_rev": "000000000444dd1a",
  "mail": "bjensen@example.com",
  "givenName": "Barbara",
  "sn": "Jensen",
  "description": "Created By CSV",
  "userName": "bjensen",
  "telephoneNumber": "1234567",
  "accountStatus": "active",
  "effectiveRoles": [],
  "effectiveAssignments": []
}

The following example returns the same user entry, with metadata:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/bjensen?_fields=,_meta/*"
{
  "_id": "bjensen",
  "_rev": "000000000444dd1a",
  "mail": "bjensen@example.com",
  "givenName": "Barbara",
  "sn": "Jensen",
  "description": "Created By CSV",
  "userName": "bjensen",
  "telephoneNumber": "1234567",
  "accountStatus": "active",
  "effectiveRoles": [],
  "effectiveAssignments": []
  "_meta": {
    "_ref": "internal/usermeta/284273ff-5e50-4fa4-9d30-4a3cf4a5f642",
    "_refResourceCollection": "internal/usermeta",
    "_refResourceId": "284273ff-5e50-4fa4-9d30-4a3cf4a5f642",
    "_refProperties": {
      "_id": "30076e2e-8db5-4b4d-ab91-5351d2da4620",
      "_rev": "000000001ad09f00"
    },
    "createDate": "2018-04-12T19:53:19.004Z",
    "lastChanged": {
      "date": "2018-04-12T19:53:19.004Z"
    },
    "loginCount": 0,
    "_rev": "0000000094605ed9",
    "_id": "284273ff-5e50-4fa4-9d30-4a3cf4a5f642"
  }
}

Apart from the createDate and lastChanged shown previously, the request also returns the loginCount. This property is stored by default and increments with each login request based on password or social authentication.

The request also returns a _meta property that includes relationship information. IDM uses the relationship model to store the metadata. When the meta stanza is added to the user object definition, the attribute specified by the property ("property" : "_meta", in this case) is added to the schema as a uni-directional relationship to the resource collection specified by resourceCollection.

In this example, the user object’s _meta field is stored as an internal/usermeta object. The _meta/_ref property shows the full resource path to the internal object where the metadata for this user is stored.

Manage identities

In Identity Cloud user identities are sometimes referred to as managed users or user managed objects. There are alpha users and bravo users.

To retrieve, add, change, and delete managed users, use one of the following methods:

  • In the Identity Cloud admin UI, any of the options in Identities > Manage > realm-name_user.

  • The REST interface at the context path /openidm/managed/realm-name_user.

Managed users examples

The following examples show how to retrieve, add, change, and delete users over the REST interface. For more information on all the managed user endpoints and actions, refer to the Managed users endpoint.

Retrieve IDs of all managed users in a realm

The size of the returned set can be large when there are many users in your tenant.
curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=true&_fields=_id"
{
  "result": [
    {
      "_id": "1dff18dc-ac57-4388-8127-dff309f80002",
      "_rev": "ceea2483-7f92-411e-9194-dcca0d61198e-48377"
    },
    {
      "_id": "7750881d-1622-451e-9ee5-71f7aaafcadf",
      "_rev": "ecf2cd07-f187-482e-9fa0-1127c267bce2-65781"
    },
    ...
  ],
  ...
}

Query managed users for a specific user

You can return a subset of users based on a query. If the conditions are met, then the users are returned.

The _queryFilter requires double quotes, or the URL-encoded equivalent (%22), around the search term. This example uses the URL-encoded equivalent:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=userName+eq+%22scarter%22"
{
  "result": [
    {
      "_id": "7750881d-1622-451e-9ee5-71f7aaafcadf",
      "_rev": "ecf2cd07-f187-482e-9fa0-1127c267bce2-65781",
      "userName": "scarter",
      "givenName": "Sam",
      "sn": "Carter",
      "telephoneNumber": "12345678",
      "active": "true",
      "mail": "scarter@example.com",
      "accountStatus": "active",
      "effectiveAssignments": [],
      "effectiveRoles": []
    }
  ],
  ...
}

This example uses single quotes around the URL to avoid conflicts with the double quotes around the search term:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
'https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=userName+eq+"scarter"'
{
  "result": [
    {
      "_id": "7750881d-1622-451e-9ee5-71f7aaafcadf",
      "_rev": "ecf2cd07-f187-482e-9fa0-1127c267bce2-65781",
      "userName": "scarter",
      "givenName": "Sam",
      "sn": "Carter",
      "telephoneNumber": "12345678",
      "active": "true",
      "mail": "scarter@example.com",
      "accountStatus": "active",
      "effectiveAssignments": [],
      "effectiveRoles": []
    }
  ],
  ...
}

Retrieve a managed user by their ID

In the following example, 7750881d-1622-451e-9ee5-71f7aaafcadf is the UUID of the user.

If you do not know the UUID of the user, you can retrieve the user by performing a search query, as described in Query managed users for a specific user.

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/7750881d-1622-451e-9ee5-71f7aaafcadf"
{
  "_id": "7750881d-1622-451e-9ee5-71f7aaafcadf",
  "_rev": "ecf2cd07-f187-482e-9fa0-1127c267bce2-65781",
  "userName": "scarter",
  "givenName": "Sam",
  "sn": "Carter",
  "telephoneNumber": "12345678",
  "active": "true",
  "mail": "scarter@example.com",
  "accountStatus": "active",
  "effectiveAssignments": [],
  "effectiveRoles": []
}

Add a user with a specific user ID

To add a user, you must provide the minimum required attributes.

To locate the minimum required attributes:

  1. From the Identity Cloud admin UI, click Native Consoles > Identity Management.

  2. Click Configure > Managed Objects > managed/realm-name_user.

  3. In the Required column, note the properties that have required marked.

    1. To create a user, these are the minimum attributes you must present.

If you create an object using PUT, the ID you assign must be a UUID, for example, 4cf65bb9-baa4-4488-aa73-216adf0787a1.
curl \
--header "Content-Type: application/json" \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--header "If-None-Match: *" \
--request PUT \
--data '{
  "userName": "bjackson",
  "sn": "Jackson",
  "givenName": "Barbara",
  "mail": "bjackson@example.com",
  "telephoneNumber": "082082082",
  "password": "Passw0rd"
}' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/4cf65bb9-baa4-4488-aa73-216adf0787a1"
{
  "_id": "4cf65bb9-baa4-4488-aa73-216adf0787a1",
  "_rev": "ceea2483-7f92-411e-9194-dcca0d61198e-51099",
  "userName": "bjackson",
  "sn": "Jackson",
  "givenName": "Barbara",
  "mail": "bjackson@example.com",
  "telephoneNumber": "082082082",
  "accountStatus": "active",
  "effectiveAssignments": [],
  "effectiveRoles": []
}

Add a user with a system-generated ID

To add a user, you must provide the minimum required attributes.

To locate the minimum required attributes:

  1. From the Identity Cloud admin UI, click Native Consoles > Identity Management.

  2. Click Configure > Managed Objects > managed/realm-name_user.

  3. In the Required column, note the properties that have required marked.

    1. To create a user, these are the minimum attributes you must present.

In this instance, Identity Cloud will create a UUID for you.

curl \
--header "Content-Type: application/json" \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request POST \
--data '{
  "userName": "pjensen",
  "sn": "Jensen",
  "givenName": "Pam",
  "mail": "pjensen@example.com",
  "telephoneNumber": "082082082",
  "password": "Passw0rd"
}' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_action=create"
{
  "_id": "4121ae44-7bf4-4dcb-b853-cfc8b5b8582c",
  "_rev": "ceea2483-7f92-411e-9194-dcca0d61198e-51129",
  "userName": "pjensen",
  "sn": "Jensen",
  "givenName": "Pam",
  "mail": "pjensen@example.com",
  "telephoneNumber": "082082082",
  "accountStatus": "active",
  "effectiveAssignments": [],
  "effectiveRoles": []
}

Update a user

This example checks whether user bjackson exists, then replaces the telephone number attribute with the new data provided in the request body:

curl \
--header "Content-Type: application/json" \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request POST \
--data '[
  {
    "operation": "replace",
    "field": "/telephoneNumber",
    "value": "0763483726"
  }
]' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_action=patch&_queryFilter=userName+eq+'bjackson'"
{
  "userName": "bjackson",
  "sn": "Jackson",
  "givenName": "Barbara",
  "mail": "bjackson@example.com",
  "telephoneNumber": "0763483726",
  "accountStatus": "active",
  "effectiveAssignments": [],
  "effectiveRoles": [],
  "_rev": "ceea2483-7f92-411e-9194-dcca0d61198e-51153",
  "_id": "4cf65bb9-baa4-4488-aa73-216adf0787a1"
}

Delete a user

To delete a user, all you need is the UUID.

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request DELETE \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/4cf65bb9-baa4-4488-aa73-216adf0787a1"
{
  "_id": "4cf65bb9-baa4-4488-aa73-216adf0787a1",
  "_rev": "ceea2483-7f92-411e-9194-dcca0d61198e-51153",
  "userName": "bjackson",
  "sn": "Jackson",
  "givenName": "Barbara",
  "mail": "bjackson@example.com",
  "telephoneNumber": "0763483726",
  "accountStatus": "active",
  "effectiveAssignments": [],
  "effectiveRoles": []
}

Relationships between objects

Relationships are references between managed objects. Roles and Organizations are implemented using relationships.

The default IDM schema defines several user properties as relationships. For information on how to define custom relationships, refer to Create a custom relationship property.

Create a relationship between two objects

In the default IDM schema, several user properties are defined as relationships, for example, the manager relationship.

Relationships let you reference one managed object from another using the _ref* relationship properties. Three properties make up a relationship reference:

  • _refResourceCollection specifies the container of the referenced object, for example, managed/realm-name_user.

  • _refResourceId specifies the ID of the referenced object. This is generally a system-generated UUID, such as 9dce06d4-2fc1-4830-a92b-bd35c2f6bcbb.

  • _ref is a derived path that is a combination of _refResourceCollection and a URL-encoded _refResourceId.

For example, imagine that you are creating a new user, psmith, and that psmith's manager is bjensen. You would add psmith's user entry, and reference bjensen's entry with the _ref property.

First, retrieve bjensen's UUID, displayed in the _id property value.

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=userName+eq+%22bjensen%22"
{
  "result": [
    {
      "_id": "1dff18dc-ac57-4388-8127-dff309f80002",
      "_rev": "f4816053-aa01-4a7b-8380-8f3646787fd0-23348",
      "country": null,
      ...
    }
  ]
  ...
}

Next, add the new user psmith and specify bjensen as the manager using the _ref property. Make sure to use bjensen's UUID, for example, 1dff18dc-ac57-4388-8127-dff309f80002.

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--request POST \
--data '{
  "sn":"Smith",
  "userName":"psmith",
  "givenName":"Patricia",
  "displayName":"Patti Smith",
  "description" : "psmith - new user",
  "mail" : "psmith@example.com",
  "telephoneNumber" : "0831245986",
  "password" : "Passw0rd",
  "manager" : {"_ref" : "managed/realm-name_user/1dff18dc-ac57-4388-8127-dff309f80002"}
}' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_action=create"
{
  "_id": "51257f1e-6562-4b67-a80b-47b84f693f1b",
  "_rev": "6aad0f3b-eb20-4ae4-8c72-7e904b1062e5-34787",
  "country": null,
  "frUnindexedString1": null,
  "mail": "psmith@example.com",
  "memberOfOrgIDs": [],
  ...
}

Note that relationship information is not returned by default. To show the relationship in psmith's entry, you must explicitly request their manager entry, as follows:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=userName+eq+%22psmith%22&_fields=manager"
{
  "result": [
    {
      "_id": "51257f1e-6562-4b67-a80b-47b84f693f1b",
      "_rev": "6aad0f3b-eb20-4ae4-8c72-7e904b1062e5-34787",
      "manager": {
        "_ref": "managed/alpha_user/1dff18dc-ac57-4388-8127-dff309f80002",
        "_refResourceCollection": "managed/alpha_user",
        "_refResourceId": "1dff18dc-ac57-4388-8127-dff309f80002",
        "_refProperties": {
          "_id": "3dd2c42d-598e-4b78-bf59-0aab43113be7",
          "_rev": "6aad0f3b-eb20-4ae4-8c72-7e904b1062e5-34784"
        }
      }
    }
  ],
  ...
}

If a relationship changes, you can query the updated relationship state when any referenced managed objects are queried. So, after creating user psmith with manager bjensen, run a query on bjensen's user entry. The query shows a reference to psmith's entry in their reports property, which is configured as the reversePropertyName of the manager property.

The following query shows bjensen's direct reports including the new user entry, psmith:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=userName+eq+%22bjensen%22&_fields=reports"
{
  "result": [
    {
      "_id": "1dff18dc-ac57-4388-8127-dff309f80002",
      "_rev": "f4816053-aa01-4a7b-8380-8f3646787fd0-23348",
      "reports": [
        ...
        {
          "_ref": "managed/alpha_user/51257f1e-6562-4b67-a80b-47b84f693f1b",
          "_refResourceCollection": "managed/alpha_user",
          "_refResourceId": "51257f1e-6562-4b67-a80b-47b84f693f1b",
          "_refProperties": {
            "_id": "3dd2c42d-598e-4b78-bf59-0aab43113be7",
            "_rev": "6aad0f3b-eb20-4ae4-8c72-7e904b1062e5-34784"
          }
        }
      ]
    }
  ],
  ...
}
IDM maintains referential integrity by deleting the relationship reference if the object referred to by that relationship is deleted. In our example, if bjensen's user entry is deleted, the corresponding reference in psmith's manager property is removed.

Manage custom relationship properties

Custom relationship properties allow you to define custom relationships between managed objects. For example, you could model a parent-child relationship by creating the custom_Parents and custom_Children properties and configuring them as one-way one-to-many relationships.

Only use the Identity Cloud admin UI or the Schema API to manage relationships. Using other methods may cause your data to de-sync.

Create a custom relationship property

To create a custom relationship property using the Identity Cloud admin UI:

  1. In the Identity Cloud admin UI, click Native Consoles > Identity Management.

  2. From the top navigation menu, click Configure > Managed Objects.

  3. Select a managed object type.

  4. Click Add a Property. An entry field displays.

  5. In the Name field, enter a name for the custom relationship property. The name must begin with the string custom_, such as custom_Example.

  6. From the Type drop-down, select Relationship.

  7. Click Next. The Add Resources modal displays.

  8. From the Resource drop-down, select the resource to map the custom relationship property to.

  9. From the Display Properties drop-down, select the properties on the resource to map to the custom relationship property.

  10. Click Save. The Relationships Property screen for the new relationship property displays.

Objects are limited to 5 custom relationships. If you need an object to have more, create custom relationships from the related object and map them to the original object.

Update a custom relationship

You can adjust a custom relationship’s cardinality by configuring each side of the relationship to be have one, many, or none of the other side. For instance, custom_Managers may have many custom_Employees, while custom_Employees have only one custom_Managers.

To change the cardinality of a custom relationship using the Identity Cloud admin UI:

  1. In the Identity Cloud admin UI, click Native Consoles > Identity Management.

  2. From the top navigation menu, click Configure > Managed Objects.

  3. Click the managed object type which has the relationship property to modify.

  4. Click the relationship property to modify.

  5. In the Relationship Configuration section, click the cardinality relationship name associated with the arrow indicating the direction of the relationship. A popover displays.

  6. From the Relationship drop-down on the popover, select the cardinality of the relationship. The Changes Pending notification displays in the lower left of the UI.

  7. Click Save.

When you change the configuration of a custom relationship, existing objects which contain that custom relationship are not automatically updated to match the new configuration. Ensure your data is updated to reflect the new relationship configuration.

For example, suppose custom_Doctors have many custom_Patients and custom_Patients have many custom_Doctors. The rules change and now custom_Patients have one custom_Doctor. In addition to updating the custom relationship’s cardinality in the configuration, you must also update all existing custom_Patients with more than one custom_Doctor to have at most one.

Delete a custom relationship property

Existing objects are not automatically updated when you delete a custom relationship property. When you delete a custom relationship property, you must also update the existing objects to no longer reference them. Failing to do this may result in the "orphaned" data unpredictably reappearing if Identity Cloud reuses the deleted reference attribute for other data.

Before you delete a custom relationship property, find all of the managed objects which are in the custom relationship and either modify or delete the data. The following REST API query returns all managed users with the property custom_Example:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=2.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/user?_queryFilter=/custom_Example+pr&_pageSize=30"

For more information on using the REST API to manage custom relationship properties, refer to Schema.

Configure relationship change notification

A relationship exists between two managed objects. By default, when a relationship changes for any create, update, or delete operation, the managed objects on either side of the relationship are not notified of that change. This means that the state of each object with respect to that relationship field is not recalculated until the object is read. This default behavior improves performance, especially cases where many objects are affected by a single relationship change.

For roles, change notification is set to TRUE by default. This default configuration lets managed users receive notifications when any relationships that link users, roles, and assignments are manipulated. For more information about relationship change notification, refer to Roles and relationship change notification.

Origin and referenced objects

A relationship exists between an origin object and a referenced object. These terms reflect which managed object is specified in the URL (for example managed/realm-name_user/psmith), and which object is referenced by the relationship (_ref*) properties. For more information about the relationship properties, refer to Create a relationship between two objects.

In an example in the Create a relationship between two objects section, a POST on managed/realm-name_user/psmith (UUID is 51257f1e-6562-4b67-a80b-47b84f693f1b) with "manager":{_ref:"managed/realm-name_user/bjensen"} (UUID is 1dff18dc-ac57-4388-8127-dff309f80002) causes managed/realm-name_user/psmith to be the origin object, and managed/realm-name_user/bjensen to be the referenced object for that relationship.

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--request POST \
--data '{
  "sn":"Smith",
  "userName":"psmith",
  "givenName":"Patricia",
  "displayName":"Patti Smith",
  "description" : "psmith - new user",
  "mail" : "psmith@example.com",
  "telephoneNumber" : "0831245986",
  "password" : "Passw0rd",
  "manager" : {"_ref" : "managed/realm-name_user/1dff18dc-ac57-4388-8127-dff309f80002"}
}' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_action=create"
{
  "_id": "51257f1e-6562-4b67-a80b-47b84f693f1b",
  "_rev": "6aad0f3b-eb20-4ae4-8c72-7e904b1062e5-34787",
  "country": null,
  "frUnindexedString1": null,
  "mail": "psmith@example.com",
  "memberOfOrgIDs": [],
  ...
}

This relationship is illustrated as follows:

Illustration shows the origin and referenced objects in a relationship
Figure 1. Relationship Objects

Note that for the reverse relationship (a POST on managed/realm-name_user/bjensen with "reports":[{_ref = "managed/realm-name_user/psmith"}]) managed/realm-name_user/bjensen would be the origin object, and managed/realm-name_user/psmith would be the referenced object.

By default, when a relationship changes, neither the origin object nor the referenced object is notified of the change. So, with the POST on managed/realm-name_user/psmith with "manager":{_ref:"managed/realm-name_user/bjensen"}, neither psmith's object nor bjensen's object is notified. This means that the objects are not updated to reflect the latest change.

Notification properties

To configure relationship change notifications, set the notify and notifySelf properties in your managed object schema.

Auditing is not tied to relationship change notification and is always triggered when a relationship changes; therefore, relationship changes are audited, regardless of the notifySelf, notify, and notifyRelationships properties.

The following properties specify whether objects that reference relationships are notified of a relationship change:

notifySelf

Notifies the origin object of the relationship change.

In our example, if the manager definition includes "notifySelf":true and if the relationship is changed through a URL that references psmith, then psmith's object would be notified of the change. Thus, for any CREATE, UPDATE or DELETE request on the psmith/manager, psmith would be notified, but the managed object referenced by this relationship (bjensen) would not be notified.

If the relationship were manipulated through a request to bjensen/reports, then bjensen would only be notified if the reports relationship specified "notifySelf":true.

notify

Notifies the referenced object of the relationship change. Set this property on the resourceCollection of the relationship property.

In our example, assume that the manager definition has a resourceCollection with a path of managed/realm-name_user and that this object specifies "notify":true. If the relationship changes through any CREATE, UPDATE, or DELETE operation on the URL psmith/manager, then the reference object (managed/realm-name_user/bjensen) would be notified of the change to the relationship.

notifyRelationships

This property controls the propagation of notifications out of a managed object when one of its properties changes through an update or patch or when that object receives a notification through one of these fields.

The notifyRelationships property takes an array of relationships as a value; for example, "notifyRelationships":["relationship1", "relationship2"]. The relationships specified here are fields defined on the managed object type, which might itself be a relationship.

Notifications are propagated according to the recipient’snotifyRelationships configuration. If a managed object type is notified of a change through one if its relationship fields, the notification is done according to the configuration of the recipient object.

To illustrate, review the attributes property in the default managed/realm-name_assignment object:

{
  "name" : "assignment",
    "schema" : {
      ...
      "properties" : {
        ...
        "attributes" : {
          "description" : "The attributes operated on by this assignment.",
          "title" : "Assignment Attributes",
          ...
          "notifyRelationships" : ["roles"]
        },
        ...

This configuration means that if an assignment is updated or patched and the assignment’s attributes change in some way, all the roles connected to that assignment are notified.

Note that the role managed object has "notifyRelationships":["members"] defined on its assignments field as follows:

{
  "name" : "role",
    "schema" : {
      ...
      "properties" : {
        ...
        "assignments" : {
          ...
          "notifyRelationships" : ["members"]
        }
    ...
}

When a role is notified of the creation of a new relationship to an assignment, the notification is propagated through the assignments property. Because "notifyRelationships":["members"] is set on the assignments property, the notification is propagated across the role to all of its members.

Relationship change notifications

By default, roles, assignments, and members use relationship change notification to ensure that relationship changes are accurately provisioned.

For example, the default user object includes a roles property with notifySelf set to true:

{
  "name" : "user",
  ...
  "schema" : {
    ...
    "properties" : {
      ...
      "roles" : {
        "description" : "Provisioning Roles",
        ...
        "items" : {
          "type" : "relationship",
          ...
          "reverseRelationship" : true,
          "reversePropertyName" : "members",
          "notifySelf" : true,
          ...
        }
        ...

In this case, notifySelf indicates the origin or user object. If any changes are made to a relationship referencing a role through a URL that includes a user, the user is notified of the change. For example, if there is a CREATE on managed/realm-name_user/psmith/roles specifying a set of references to existing roles, user psmith is notified of the change.

Similarly, the role object also includes a members property. That property includes the following schema definition:

{
  "name" : "role",
  ...
  "schema" : {
    ...
    "properties" : {
      ...
      "members" : {
        ...
        "items" : {
          "type" : "relationship",
          ...
          "properties" : {
            ...
            "resourceCollection" : [
              {
                "notify" : true,
                "path" : "managed/realm-name_user",
                "label" : "User",
                ...
              }
           ]
          }
          ...

Notice the "notify":true setting on the resourceCollection. This setting indicates that if the relationship is created, updated, or deleted through a URL that references that role, all objects in that resource collection (in this case, managed/realm-name_user objects), which are identified as members of that role, are notified of the change.

  • To notify an object that the relationship has changed (using the notify property), the relationship must be bidirectional ("reverseRelationship":true).

    When an object is notified of a relationship state change (create, delete, or update), part of that notification process involves calculating the changed object state with respect to the changed relationship field. For example, if a managed user is notified that a role was created, the user object calculates its base state and the state of its roles field, before and after the new role is created. This before and after state is then reconciled.

    An object referenced by a forward (unidirectional) relationship does not have a field referencing that relationship; the object is "pointed-to" but does not "point-back". Because this object cannot calculate its before and after state with respect to the relationship field, it cannot be notified.

    Similarly, relationships that are notified of changes to the objects that reference them must be bidirectional relationships.

    If you configure relationship change notification on a unidirectional relationship, IDM throws an exception.

  • You cannot configure relationship change notification in the IDM admin UI; you must update the managed object schema directly.

Validate relationships between objects

Optionally, you can specify that a relationship between two objects must be validated when the relationship is created. For example, you can indicate that a user cannot reference a role if that role does not exist.

When you create a new relationship type, validation is disabled by default because it involves an expensive query to the relationship that is not always required.

To configure validation of a referenced relationship, set "validate":true in the managed object schema. The default schema enables validation for the following relationships:

  • For user objects—roles, managers, and reports

  • For role objects—members and assignments

  • For assignment objects—roles

Query relationships bidirectionally

Relationships between two managed objects come in two forms: forward and reverse. Forward relationships mean one side points to the other in a uni-directional flow. Reverse relationships means both sides point to the other in a bidirectional flow.

Most cases use reverse or bidirectional relationships for efficient querying of objects. For example, a relationship between a user and his manager might indicate a reverse relationship between the manager and her direct report. You may want to query jdoe's user entry to discover who his manager is, or query bjensen's user entry to discover all the users who report to bjensen.

You define a reverse relationship within a relationship definition. Consider the following sample excerpt of the default managed object configuration:

"reports" : {
  "description" : "Direct Reports",
  "title" : "Direct Reports",
  ...
  "type" : "array",
  "returnByDefault" : false,
  "items" : {
    "type" : "relationship",
    "reverseRelationship" : true,
    "reversePropertyName" : "manager",
    "validate" : true,
    ...
  }
  ...

The reports property is a relationship type between users and managers, so you can refer to a managed user’s reports by referencing the reports object. However, the reports property is also a reverse relationship ("reverseRelationship":true), which means you can list all users that reference that report.

You can list all users whose manager property is set to the currently queried user.

The reverse relationship includes an optional resourceCollection that lets you query a set of objects, based on specific fields:

"resourceCollection" : [
  {
    "path" : "managed/realm-name_user",
    "label" : "User",
    "query" : {
      "queryFilter" : "true",
      "fields" : [
        "userName",
        "givenName",
        "sn"
      ]
    }
  }
]

The path property of the resourceCollection points to the set of objects to be queried. If this path is not in the local repository, the link expansion can incur a significant performance cost. Although the resourceCollection is optional, the same performance cost is incurred if the property is absent.

The query property indicates how you will query this resource collection to configure the relationship. In this case, "queryFilter":true indicates that you can search on any of the properties listed in the fields array when you are assigning a manager to a user or a new report to a manager.

Grant relationships conditionally

Relationships can be granted dynamically, based on a specified condition. In order to conditionally grant a relationship, the schemas for the resources you are creating a relationship between need to be configured to support conditional association. To do this, three fields in the schema are used:

conditionalAssociation

Boolean. This property is applied to the resourceCollection for the grantor of the relationship. For example, the members relationship on managed/realm-name_role specifies that there is a conditional association with the managed/realm-name_user resource:

"resourceCollection" : [
  {
    "notify" : true,
    "conditionalAssociation" : true,
    "path" : "managed/realm-name_user",
    "label" : "User",
    "query" : {
      "queryFilter" : "true",
      "fields" : [
        "userName",
        "givenName",
        "sn"
      ]
    }
  }
]
conditionalAssociationField

String. This property specifies the field used to determine whether a conditional relationship is granted. The field is applied to the resourceCollection of the grantee of the relationship. For example, the roles relationship on managed/realm-name_user specifies that the conditional association with managed/realm-name_role is defined by the condition field in managed/realm-name_role.

"resourceCollection" : [
  {
    "path" : "{managed_role}",
    "label" : "Role",
    "conditionalAssociationField" : "condition",
    "query" : {
      "queryFilter" : "true",
      "fields" : [
        "name"
      ]
    }
  }
]
If you are using the default schema, the field name is usually the condition but can be any field that evaluates a condition and is flagged as isConditional.
isConditional

Boolean. This property is applied to the field to check whether membership in a relationship is granted. You can only mark one field on a resource as isConditional. For example, in the relationship between managed/realm-name_user and managed/realm-name_role, conditional membership in the relationship is determined by the query filter specified in the managed/realm-name_role condition field:

"condition" : {
  "description" : "A conditional filter for this role",
  "title" : "Condition",
  "viewable" : false,
  "searchable" : false,
  "isConditional" : true,
  "type" : "string"
}

Conditions support both properties and virtual properties derived from other relationships, if the query property has been configured. Conditions are a powerful tool for dynamically creating relationships between two objects. An example of conditional relationships in use is covered in Grant a Role Based on a Condition.

View relationships over REST

By default, information about relationships is not returned as the result of a GET request on a managed object. You must explicitly include the relationship property in the request. For example, if you request a user’s manager entry, the manager's _ref property returns the UUID (managed/alpha_user/1dff18dc-ac57-4388-8127-dff309f80002) of the manager, bjensen.

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=userName+eq+%22psmith%22&_fields=manager"
{
  "result": [
    {
      "_id": "4121ae44-7bf4-4dcb-b853-cfc8b5b8581c",
      "_rev": "e7b5a983-c0dc-405d-9d6a-cf0e186e5abf-66315",
      "manager": {
        "_ref": "managed/alpha_user/1dff18dc-ac57-4388-8127-dff309f80002",
        "_refResourceCollection": "managed/alpha_user",
        "_refResourceId": "1dff18dc-ac57-4388-8127-dff309f80002",
        "_refProperties": {
          "_id": "152ae6f2-d862-46df-8569-9cc2b2e6533a",
          "_rev": "a41bb123-7755-4ceb-9e49-e0f26b5912a8-15964"
        }
      }
    }
  ],
  ...
}

To obtain more information about the referenced object (psmith's manager, in this case), you can include additional fields from the referenced object in the query, using the syntax object/property (for a simple string value) or object/*/property (for an array of values).

The following example returns the email address and contact number for psmith's manager:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=userName+eq+%22psmith%22&_fields=manager/mail,manager/telephoneNumber"
{
  "result": [
    {
      "_id": "4121ae44-7bf4-4dcb-b853-cfc8b5b8581c",
      "_rev": "e7b5a983-c0dc-405d-9d6a-cf0e186e5abf-66315",
      "manager": {
        "_rev": "b5ae9a0e-cc07-45ba-8a9e-d8c43aa3ff13-4157",
        "_id": "1dff18dc-ac57-4388-8127-dff309f80002",
        "mail": "bjensen@example.com",
        "telephoneNumber": null,
        "_ref": "managed/alpha_user/1dff18dc-ac57-4388-8127-dff309f80002",
        "_refResourceCollection": "managed/alpha_user",
        "_refResourceId": "1dff18dc-ac57-4388-8127-dff309f80002",
        "_refProperties": {
          "_id": "152ae6f2-d862-46df-8569-9cc2b2e6533a",
          "_rev": "a41bb123-7755-4ceb-9e49-e0f26b5912a8-15964"
        }
      }
    }
  ],
  ...
}

To query all the relationships associated with a managed object, query the reference (*_ref) property of that object. The following example shows all the objects referenced by psmith's entry:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=userName+eq+%22psmith%22&_fields=*_ref"
{
  "result": [
  {
    "_id": "4121ae44-7bf4-4dcb-b853-cfc8b5b8581c",
    "_rev": "e7b5a983-c0dc-405d-9d6a-cf0e186e5abf-66315",
    "reports": [],
    "manager": {
      "_ref": "managed/alpha_user/1dff18dc-ac57-4388-8127-dff309f80002",
      "_refResourceCollection": "managed/alpha_user",
      "_refResourceId": "1dff18dc-ac57-4388-8127-dff309f80002",
      "_refProperties": {
        "_id": "152ae6f2-d862-46df-8569-9cc2b2e6533a",
        "_rev": "a41bb123-7755-4ceb-9e49-e0f26b5912a8-15964"
      }
    },
    "adminOfOrg": [],
    "memberOfOrg": [],
    "ownerOfOrg": [],
    "roles": [],
    "_meta": {
      "_ref": "managed/alpha_usermeta/95718189-7138-4e18-97c4-5fe42e4cabb5",
      "_refResourceCollection": "managed/alpha_usermeta",
      "_refResourceId": "95718189-7138-4e18-97c4-5fe42e4cabb5",
      "_refProperties": {
        "_id": "57306c2d-8a49-49cc-9088-ef269a16d067",
        "_rev": "a41bb123-7755-4ceb-9e49-e0f26b5912a8-15967"
      }
    },
    "authzRoles": [],
    "_notifications": []
  }
  ],
  ...
}

To expand that query to show all fields within each relationship, add a wildcard (*) as follows:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=userName+eq+%22psmith%22&_fields=*_ref/*"
{
  "result": [
    {
      "_id": "4121ae44-7bf4-4dcb-b853-cfc8b5b8581c",
      "_rev": "e7b5a983-c0dc-405d-9d6a-cf0e186e5abf-66315",
      "reports": [],
      "manager": {
        "_rev": "b5ae9a0e-cc07-45ba-8a9e-d8c43aa3ff13-4157",
        "_id": "1dff18dc-ac57-4388-8127-dff309f80002",
        "accountStatus": "active",
        "aliasList": null,
        "assignedDashboard": null,
        "city": null,
        "consentedMappings": null,
        "country": null,
        "description": "Password = Password1!",
        "displayName": null,
        "effectiveAssignments": null,
        "effectiveRoles": null,
        "frIndexedDate1": null,
        ...
        "frIndexedInteger1": null,
        ...
        "frIndexedMultivalued1": null,
        ...
        "frIndexedString2": null,
        ...
        "frUnindexedDate1": null,
        ...
        "frUnindexedInteger1": null,
        ...
        "frUnindexedMultivalued1": null,
        ...
        "frUnindexedString1": null,
        ...
        "givenName": "Babs",
        "isMemberOf": [
          "cn=am-policy-evaluation,ou=groups,o=alpha,o=root,ou=identities"
        ],
        "kbaInfo": null,
        "mail": "bjensen@example.com",
        "memberOfOrgIDs": null,
        "postalAddress": null,
        "postalCode": null,
        "preferences": null,
        "profileImage": null,
        "sn": "Jensen",
        "stateProvince": null,
        "telephoneNumber": null,
        "userName": "bjensen",
        "_ref": "managed/alpha_user/1dff18dc-ac57-4388-8127-dff309f80002",
        "_refResourceCollection": "managed/alpha_user",
        "_refResourceId": "1dff18dc-ac57-4388-8127-dff309f80002",
        "_refProperties": {
          "_id": "152ae6f2-d862-46df-8569-9cc2b2e6533a",
          "_rev": "a41bb123-7755-4ceb-9e49-e0f26b5912a8-15964"
        }
      },
      "adminOfOrg": [],
      "memberOfOrg": [],
      "ownerOfOrg": [],
      "roles": [],
      "_meta": {
        "_rev": "e7b5a983-c0dc-405d-9d6a-cf0e186e5abf-66336",
        "_id": "95718189-7138-4e18-97c4-5fe42e4cabb5",
        "createDate": "2022-11-02T16:35:20.112988Z",
        "lastChanged": {
          "date": "2022-11-02T16:35:20.113032Z"
        },
        "loginCount": 1,
        "_ref": "managed/alpha_usermeta/95718189-7138-4e18-97c4-5fe42e4cabb5",
        "_refResourceCollection": "managed/alpha_usermeta",
        "_refResourceId": "95718189-7138-4e18-97c4-5fe42e4cabb5",
        "_refProperties": {
          "_id": "57306c2d-8a49-49cc-9088-ef269a16d067",
          "_rev": "a41bb123-7755-4ceb-9e49-e0f26b5912a8-15967"
        }
      },
      "authzRoles": [],
      "_notifications": []
    }
  ],
  ...
}

Metadata is implemented using the relationships mechanism. When you request all relationships for a user with _ref/, you also get all the metadata for that user if metadata is being tracked. For more information, refer to Enable self-service by tracking user metadata.

Roles

Roles define privileges for user and device identities. Roles let you automatically assign and update privileges in numerous identity profiles. For further information about roles and assignments, refer to Roles and assignments.

The role object is a managed object type that uses the relationships mechanism to link the role to the managed object to which it applies.

IDM role types

IDM supports two types of roles:

  • Provisioning roles : used to specify how objects are provisioned to an external system.

    Provisioning roles are created as managed roles, at the context path openidm/managed/realm-name_role/role-name, and are granted to managed users as values of the user’s roles property.

  • Authorization roles : used to specify the authorization rights of a managed object internally, within IDM.

    Authorization roles are created as internal roles, at the context path openidm/internal/role/role-name, and are granted to managed users as values of the user’s authzRoles property.

Authorization roles can also be granted statically during authentication with the defaultUserRoles property.

Managed roles

Managed roles are intended to be collections of assignments for easier provisioning.

For information about roles, and how IDM controls authorization to its own endpoints, refer to Authorization and roles.

Managed roles are defined like any other managed object, and are granted to users through the relationships mechanism. A managed role can be granted manually, as a static value of the user’s roles attribute, or dynamically, as a result of a condition or script. For example, a user might be granted a role such as asia-sales-role dynamically, if a user in the sales organization is located in Asia region.

A user’s roles attribute takes an array of references as a value, where the references point to the managed roles. For example, if user bjensen has been granted two roles (employee and supervisor), the value of bjensen’s roles attribute would look something like the following:

"roles": [
  {
    "_ref": "managed/realm-name_role/employee",
    "_refResourceCollection": "managed/realm-name_role",
    "_refResourceId": "employee",
    "_refProperties": {
      "_grantType": "",
      "_id": "bb399428-21a9-4b01-8b74-46a7ac43e0be",
      "_rev": "00000000e43e9ba7"
    }
  },
  {
    "_ref": "managed/realm-name_role/supervisor",
    "_refResourceCollection": "managed/realm-name_role",
    "_refResourceId": "supervisor",
    "_refProperties": {
      "_grantType": "",
      "_id": "9f7d124b-c7b1-4bcf-9ece-db4900e37c31",
      "_rev": "00000000e9c19d26"
    }
  }
]

The _refResourceCollection container holds each role. The _refResourceId is the ID of the role. The _ref property is a resource path that is derived from the _refResourceCollection and the URL-encoded _refResourceId. _refProperties provides more information about the relationship.

Manipulate roles

These sections show how to create, read, update, and delete managed roles, and to grant roles to users. For information about using roles to provision users to external systems, refer to Use assignments to provision users.

Create a role

By default, the role name must be unique. To change this behavior, adjust the policy validation on the role property in your managed object schema.

Using the Identity Cloud admin UI

  1. From the navigation bar, click Identities > Manage.

  2. On the Manage Identities page, click Realm-name - Roles > New Realm-name - Role .

  3. On the New Role page, enter a name and description for the new role, and click Next.

  4. Optionally, to assign users to the role based on the presence of specific attributes, enable Condition, and define the query. Then click Next.

  5. Optionally, to allow the role to be assigned only on a temporary basis, enable An array of temporal constraints for this role, and set the Start time, End time, and Time Zone Offset. Then click Save.

Using the IDM admin UI

  1. On the Quick Start page, click the Manage Roles tile.

  2. On the Realm-name - Role List page, click New Realm-name - Role.

  3. On the New Realm-name - Role page, enter a name and description, and click Save.

  4. Optionally, do any of the following, and click Save:

    • To restrict the role grant to a set time period, enable Temporal Constraint, and set the Timezone Offset, Start Date, and End Date.

    • To define a query filter that dynamically grants the role to members, enable Condition, and define the query.

Using REST

To create a role, send a PUT or POST request to the /openidm/managed/realm-name_role context path. The following example creates a managed role named employee:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--request POST \
--data '{
  "name": "employee",
  "description": "Role granted to workers on the company payroll"
}' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_role?_action=create"
{
  "_id": "5790220a-719b-49ad-96a6-6571e63cbaf1",
  "_rev": "0000000079c6644f",
  "name": "employee",
  "description": "Role granted to workers on the company payroll"
}

This employee role has no corresponding assignments. Assignments are what enables the provisioning logic to the external system. Assignments are created and maintained as separate managed objects, and are referred to within role definitions. For more information about assignments, refer to Use assignments to provision users.

Use script hooks to configure role behavior. For more information, refer to event hooks.

List roles

Using the Identity Cloud admin UI

  1. From the navigation bar, click Identities > Manage.

  2. On the Manage Identities page, click Realm-name - Roles > New Realm-name - Role.

Using REST

To list all the managed roles over REST, query the openidm/managed/realm-name_role endpoint. The following example shows the employee role that you created in the previous example:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_role?_queryFilter=true"
{
  "result": [
    {
      "_id": "5790220a-719b-49ad-96a6-6571e63cbaf1",
      "_rev": "0000000079c6644f",
      "name": "employee",
      "description": "Role granted to workers on the company payroll"
    }
  ],
  ...
}

Grant roles to a user

You grant roles to users through the relationship mechanism. Relationships are essentially references from one managed object to another; in this case, from a user object to a role object. For more information about relationships, refer to Relationships between objects.

You can grant roles statically or dynamically.

To grant a role statically, you must do one of the following:

  • Update the value of the user’s roles property to reference the role.

  • Update the value of the role’s members property to reference the user.

Dynamic role grants use the result of a condition or script to update a user’s list of roles.

Using the Identity Cloud admin UI

  1. From the navigation bar, click Identities > Manage.

  2. On the Manage Identities page, click Realm-name - Roles > New Realm-name - Role.

  3. Click the role-name you want to assign to users.

  4. On the role-name page, click Role Members > + Add Role Members

  5. Enter the name of the user.

  6. Optionally enable Assign role only during a selected time period, and specify the time interval.

  7. Click Save.

Using the IDM admin UI

  1. On the Quick Start page, click the Manage Roles tile.

  2. On the Realm-name - Role List page, click Realm-name.

  3. On the Realm-name page, click Role Members > Add Role Members.

  4. Enter Realm-name in the Role Members field.

  5. Optionally, to restrict the role grant to a set time period, enable Temporal Constraint, and set the Timezone Offset, Start Date, and End Date.

  6. Click Add.

Using REST

Grant roles statically

Use one of the following methods to grant a role statically to a user over REST:

  • Add the user as a role member.

    This preferred method does not incur an unnecessary performance cost when working with a role that contains many members.

    The following example adds user scarter with UUID 1002e929-5605-4a31-865d-ee0a16df6e3a as a member of the role (5790220a-719b-49ad-96a6-6571e63cbaf1):

    curl \
    --header "Authorization: Bearer <token>" \
    --header "Accept-API-Version: resource=1.0" \
    --header "Content-Type: application/json" \
    --request POST \
    --data '{
      "_ref":"managed/realm-name_user/<scarterUUID>",
      "_refProperties":{}
    }' \
    "https://<tenant-env-fqdn>/openidm/managed/realm-name_role/5790220a-719b-49ad-96a6-6571e63cbaf1/members?_action=create"
    {
      "_id": "4c32ae53-abed-45f8-bc84-c367e2b0e194",
      "_rev": "5b65b2b8-4955-461b-8532-d763426fc058-5396",
      "_ref": "managed/realm-name_user/1002e929-5605-4a31-865d-ee0a16df6e3a",
      "_refResourceCollection": "managed/realm-name_user",
      "_refResourceId": "<scarterUUID>",
      "_refProperties": {
        "_id": "4c32ae53-abed-45f8-bc84-c367e2b0e194",
        "_rev": "5b65b2b8-4955-461b-8532-d763426fc058-5396"
      }
    }
  • Update the user’s roles property to refer to the role.

    The following example grants the employee role (5790220a-719b-49ad-96a6-6571e63cbaf1) to user scarter:

    curl \
    --header "Authorization: Bearer <token>" \
    --header "Accept-API-Version: resource=1.0" \
    --header "Content-Type: application/json" \
    --request PATCH \
    --data '[
      {
        "operation": "add",
        "field": "/roles/-",
        "value": {"_ref" : "managed/realm-name_role/5790220a-719b-49ad-96a6-6571e63cbaf1"}
      }
    ]' \
    "https://<tenant-env-fqdn>/openidm/managed/realm-name_user/<scarterUUID>"
    {
      "_id": "<scarterUUID>",
      "_rev": "000000003be825ce",
      "mail": "scarter@example.com",
      "givenName": "Steven",
      "sn": "Carter",
      "description": "Created By CSV",
      "userName": "scarter",
      "telephoneNumber": "1234567",
      "accountStatus": "active",
      "effectiveRoles": [
          {
            "_ref": "managed/realm-name_role/5790220a-719b-49ad-96a6-6571e63cbaf1"
          }
        ],
      "effectiveAssignments": []
    }

    Note that scarter’s effectiveRoles attribute has been updated with a reference to the new role. For more information about effective roles and effective assignments, refer to Effective roles and effective assignments.

    When you update a user’s existing roles array, use the - special index to add the new value to the set. For more information, refer to Set semantic arrays in Patch.

  • Update the role’s members property to refer to the user.

    The following sample command makes scarter a member of the employee role:

    curl \
    --header "Authorization: Bearer <token>" \
    --header "Accept-API-Version: resource=1.0" \
    --header "Content-Type: application/json" \
    --request PATCH \
    --data '{
        "operation": "add",
        "field": "/members/-",
        "value": {"_ref" : "managed/realm-name_user/<scarterUUID>"}
      }' \
    "https://<tenant-env-fqdn>/openidm/managed/realm-name_role/5790220a-719b-49ad-96a6-6571e63cbaf1"
    {
      "_id": "5790220a-719b-49ad-96a6-6571e63cbaf1",
      "_rev": "0000000079c6644f",
      "name": "employee",
      "description": "Role granted to workers on the company payroll"
    }

    The members property of a role is not returned by default in the output. To show all members of a role, you must specifically request the relationship properties (*_ref) in your query. The following example lists the members of the employee role (currently only scarter):

    curl \
    --header "Authorization: Bearer <token>" \
    --header "Accept-API-Version: resource=1.0" \
    --request GET \
    "https://<tenant-env-fqdn>/openidm/managed/realm-name_role/5790220a-719b-49ad-96a6-6571e63cbaf1?_fields=*_ref,name"
    {
      "_id": "5790220a-719b-49ad-96a6-6571e63cbaf1",
      "_rev": "0000000079c6644f",
      "name": "employee",
      "assignments": [],
      "members": [
        {
          "_ref": "managed/realm-name_user/<scarterUUID>",
          "_refResourceCollection": "managed/realm-name_user",
          "_refResourceId": "<scarterUUID>",
          "_refProperties": {
            "_id": "7ad15a7b-6806-487b-900d-db569927f56d",
            "_rev": "0000000075e09cbf"
          }
        }
      ]
    }
  • You can replace an existing role grant with a new one by using the replace operation in your patch request.

    The following command replaces scarter’s entire roles entry (that is, overwrites any existing roles) with a single entry, the reference to the employee role (ID 5790220a-719b-49ad-96a6-6571e63cbaf1):

    curl \
    --header "Authorization: Bearer <token>" \
    --header "Accept-API-Version: resource=1.0" \
    --header "Content-Type: application/json" \
    --request PATCH \
    --data '[
      {
        "operation": "replace",
        "field": "/roles",
        "value": [
          {"_ref":"managed/realm-name_role/5790220a-719b-49ad-96a6-6571e63cbaf1"}
        ]
      }
    ]' \
    "https://<tenant-env-fqdn>/openidm/managed/realm-name_user/<scarterUUID>"
    {
      "_id": "<scarterUUID>",
      "_rev": "00000000da112702",
      "mail": "scarter@example.com",
      "givenName": "Steven",
      "sn": "Carter",
      "description": "Created By CSV",
      "userName": "scarter",
      "telephoneNumber": "1234567",
      "accountStatus": "active",
      "effectiveRoles": [
        {
          "_ref": "managed/realm-name_role/5790220a-719b-49ad-96a6-6571e63cbaf1"
        }
      ],
      "effectiveAssignments": []
    }
Grant roles dynamically

Grant a role dynamically by using one of the following methods:

  • Use a condition, expressed as a query filter, in the role definition. If the condition is true for a particular member, that member is granted the role. Conditions can be used in both managed and internal roles.

  • Use a custom script to define a more complex role-granting strategy.

Grant a conditional role

A role that is granted based on a defined condition is called a conditional role. To create a conditional role, include a query filter in the role definition.

To set up a condition for a role by using the Identity Cloud admin UI, select Settings node on the role [.var]#Role-nmae page, then define the query filter that will be used to assess the condition.

To set up a condition for a role by using the IDM admin UI, select Condition on the role Details page, then define the query filter that will be used to assess the condition.

To set up a condition for a role over REST, include the query filter as a value of the condition property in the role definition. The following example creates a role, fr-employee, that will be granted to users whose country property is set to FR:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--request POST \
--data '{
  "name": "fr-employee",
  "description": "Role granted to employees resident in France",
  "condition": "/country eq \"FR\""
}' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_role?_action=create"
{
  "_id": "eb18a2e2-ee1e-4cca-83fb-5708a41db94f",
  "_rev": "000000004085704c",
  "name": "fr-employee",
  "description": "Role granted to employees resident in France",
  "condition": "/country eq \"FR\""
}

When a condition is enabled for a role, IDM automatically assesses all managed users. It recalculates the value of the roles property for users who qualify for that role. When a condition is removed from a role, that is, when the role becomes an unconditional role, all conditional grants are removed. So, users who were granted the role based on the condition, have that role removed from their roles property.

When a condition is defined in an existing data set, every user entry (including the mapped entries on remote systems) must be updated with the assignments implied by that conditional role. The time that it takes to create a new conditional role is impacted by the following items:

  • The number of managed users affected by the condition.

  • The number of assignments related to the conditional role.

  • The average time required to provision updates to all remote systems affected by those assignments.

In a data set with a very large number of users, creating a new conditional role can therefore incur a significant performance cost when you create it. Ideally, you should set up your conditional roles at the beginning of your deployment to avoid performance issues later.

Query a user’s roles

Using the Identity Cloud admin UI

  1. From the navigation bar, click Identities > Manage.

  2. On the Manage Identities page, click Realm name - Users.

  3. Click the User name you want to check the roles.

  4. On the User name page, click Provisioning Roles.

Using the IDM admin UI

You can verify the dynamic and static roles granted to a user from the user’s entry in the IDM admin UI:

  1. On the Quick Start page, select Manage Users, then select User name.

  2. Select the Provisioning Roles tab.

  3. If you have a large number of managed roles, use the Advanced Filter option on the Role List page to build a custom query.

Using REST

Query user’s roles property to get the roles granted to the user. The following example shows that scarter has been granted two roles—an employee role, and an fr-employee role:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/<scarterUUID>/roles?_queryFilter=true&_fields=_ref/*,name"
{
  "result": [
    {
      "_id": "5a023862-654d-4d7f-b9d0-7c151b8dede5",
      "_rev": "00000000baa999c1",
      "_refResourceCollection": "managed/realm-name_role",
      "_refResourceId": "b8783543-869a-4bd4-907e-9c1d89f826ae",
      "_refResourceRev": "0000000027a959cf",
      "name": "employee",
      "_ref": "managed/realm-name_role/b8783543-869a-4bd4-907e-9c1d89f826ae",
      "_refProperties": {
        "_id": "5a023862-654d-4d7f-b9d0-7c151b8dede5",
        "_rev": "00000000baa999c1"
      }
    },
    {
      "_id": "b281ffdf-477e-4211-a112-84476435bab2",
      "_rev": "00000000d612a248",
      "_refResourceCollection": "managed/realm-name_role",
      "_refResourceId": "01ee6191-75d8-4d4b-9291-13a46592c57a",
      "_refResourceRev": "000000000cb0794d",
      "name": "fr-employee",
      "_ref": "managed/realm-name_role/01ee6191-75d8-4d4b-9291-13a46592c57a",
      "_refProperties": {
        "_grantType": "conditional",
        "_id": "b281ffdf-477e-4211-a112-84476435bab2",
        "_rev": "00000000d612a248"
      }
    }
  ],
  ...
}

Note that the fr-employee role indicates a _grantType of conditional. This property indicates how the role was granted to the user. If no _grantType is listed, the role was granted statically.

Querying a user’s roles in this way does not return any roles that would be in effect as a result of a custom script, or of any temporal constraint applied to the role. To return a complete list of all the roles in effect at a specific time, query the user’s effectiveRoles property, as follows:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/<scarterUUID>?_fields=effectiveRoles"

Remove a user’s roles

To remove a statically granted role from a user entry, do one of the following:

  • Update the value of the user’s roles property to remove the reference to the role.

  • Update the value of the role’s members property to remove the reference to that user.

A delegated administrator must use PATCH to add or remove relationships.

Roles that have been granted as the result of a condition can only be removed when the condition is changed or removed, or when the role itself is deleted.

Using the Identity Cloud admin UI

  1. From the navigation bar, click Identities > Manage.

  2. On the Manage Identities page, click Realm name - Roles.

  3. Click the Role name that you want to delete membership.

  4. Select the users you want to remove from this role and click Remove.

  5. On the Confirm Removal page, click Remove.

Using the IDM admin UI

Method 1 (If you want to remove multiple roles from a user):

  1. On the Quick Start page, select Manage Users, and select the user whose roles you want to remove.

  2. Select the Provisioning Roles tab, select the roles that you want to remove, then select Remove Selected Provisioning Roles.

Method 2 (If you want to remove a role from multiple users):

  1. On the Quick Start page, select Manage Roles, and select the role whose members you want to remove.

  2. Select the Role Members tab, select the members that you want to remove, then select Remove Selected Role Members.

Using REST

Use one of the following methods to remove a role grant from a user:

  • DELETE the role from the user’s roles property, including the reference ID (the ID of the relationship between the user and the role) in the delete request.

    The following example removes the employee role from user scarter. The role ID is b8783543-869a-4bd4-907e-9c1d89f826ae, but the ID required in the DELETE request is the reference ID (5a023862-654d-4d7f-b9d0-7c151b8dede5):

    curl \
    --header "Authorization: Bearer <token>" \
    --header "Accept-API-Version: resource=1.0" \
    --request DELETE \
    "https://<tenant-env-fqdn>/openidm/managed/realm-name_user/<scarterUUID>/roles/5a023862-654d-4d7f-b9d0-7c151b8dede5"
    {
      "_id": "5a023862-654d-4d7f-b9d0-7c151b8dede5",
      "_rev": "00000000baa999c1",
      "_ref": "managed/realm-name_role/b8783543-869a-4bd4-907e-9c1d89f826ae",
      "_refResourceCollection": "managed/realm-name_role",
      "_refResourceId": "b8783543-869a-4bd4-907e-9c1d89f826ae",
      "_refProperties": {
        "_id": "5a023862-654d-4d7f-b9d0-7c151b8dede5",
        "_rev": "00000000baa999c1"
      }
    }
  • PATCH the user entry to remove the role from the array of roles, specifying the value of the role object in the JSON payload.

    When you remove a role in this way, you must include the entire object in the value, as shown in the following example:
    curl \
    --header "Content-type: application/json" \
    --header "Authorization: Bearer <token>" \
    --header "Accept-API-Version: resource=1.0" \
    --request PATCH \
    --data '[
      {
        "operation" : "remove",
        "field" : "/roles",
        "value" : {
          "_ref": "managed/realm-name_role/b8783543-869a-4bd4-907e-9c1d89f826ae",
          "_refResourceCollection": "managed/realm-name_role",
          "_refResourceId": "b8783543-869a-4bd4-907e-9c1d89f826ae",
          "_refProperties": {
            "_id": "5a023862-654d-4d7f-b9d0-7c151b8dede5",
            "_rev": "00000000baa999c1"
          }
        }
      }
    ]' \
    "https://<tenant-env-fqdn>/openidm/managed/realm-name_user/<scarterUUID>"
    {
      "_id": "<scarterUUID>",
      "_rev": "000000007b78257d",
      "mail": "scarter@example.com",
      "givenName": "Steven",
      "sn": "Carter",
      "description": "Created By CSV",
      "userName": "scarter",
      "telephoneNumber": "1234567",
      "accountStatus": "active",
      "effectiveRoles": [
        {
          "_ref": "managed/realm-name_role/01ee6191-75d8-4d4b-9291-13a46592c57a"
        }
      ],
      "effectiveAssignments": [],
      "preferences": {
        "updates": false,
        "marketing": false
      },
      "country": "France"
    }
  • DELETE the user from the role’s members property, including the reference ID (the ID of the relationship between the user and the role) in the delete request.

    The following example first queries the members of the employee role, to obtain the ID of the relationship, then removes bjensen’s membership from that role:

    curl \
    --header "Authorization: Bearer <token>" \
    --header "Accept-API-Version: resource=1.0" \
    --request GET \
    "https://<tenant-env-fqdn>/openidm/managed/realm-name_role/b8783543-869a-4bd4-907e-9c1d89f826ae/members?_queryFilter=true"
    {
      "result": [
        {
          "_id": "a5a4bf94-6425-4458-aae4-bbd6ad094f72",
          "_rev": "00000000c25d994a",
          "_ref": "managed/realm-name_user/bjensen",
          "_refResourceCollection": "managed/realm-name_user",
          "_refResourceId": "bjensen",
          "_refProperties": {
            "_id": "a5a4bf94-6425-4458-aae4-bbd6ad094f72",
            "_rev": "00000000c25d994a"
          }
        }
      ],
      ...
    }
    curl \
    --header "Authorization: Bearer <token>" \
    --header "Accept-API-Version: resource=1.0" \
    --request DELETE \
    "https://<tenant-env-fqdn>/openidm/managed/realm-name_role/b8783543-869a-4bd4-907e-9c1d89f826ae/members/a5a4bf94-6425-4458-aae4-bbd6ad094f72"
    {
      "_id": "a5a4bf94-6425-4458-aae4-bbd6ad094f72",
      "_rev": "00000000c25d994a",
      "_ref": "managed/realm-name_user/bjensen",
      "_refResourceCollection": "managed/realm-name_user",
      "_refResourceId": "bjensen",
      "_refProperties": {
        "_id": "a5a4bf94-6425-4458-aae4-bbd6ad094f72",
        "_rev": "00000000c25d994a"
      }
    }

Delete a role definition

To delete a role over the REST interface, delete that managed object.

You cannot delete a role that is currently granted to users. If you attempt to delete a role that is granted to a user (either over the REST interface, or by using the IDM admin UI), IDM returns an error.

Using the Identity Cloud admin UI

  1. From the navigation bar, click Identities > Manage.

  2. On the Manage Identities page, click Realm name - Roles.

  3. Click the Role name you want to delete.

  4. Click Delete Realm name - Role.

  5. On the Delete Realm name - Role page, click Delete.

Using the IDM admin UI

  1. On the Quick Start page, select Manage Roles.

  2. Select the roles you want to remove and click Delete Selected.

Using REST

The following example deletes the employee role created in the previous section:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request DELETE \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_role/b8783543-869a-4bd4-907e-9c1d89f826ae"
{
  "_id": "b8783543-869a-4bd4-907e-9c1d89f826ae",
  "_rev": "0000000027a959cf",
  "privileges": [],
  "name": "employee",
  "description": "All employees"
}

The following example attempts to remove a role that is still granted to a user, and receives an error message:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request DELETE \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_role/01ee6191-75d8-4d4b-9291-13a46592c57a"
{
  "code": 409,
  "reason": "Conflict",
  "message": "Cannot delete a role that is currently granted"
}

Use temporal constraints to restrict effective roles

Temporal constraints restrict the period that a role is effective. You can apply temporal constraints to managed and internal roles, and to role grants (for individual users).

For example, you may want a role, contractors-2020, to apply to all contract employees for the year 2020. In this case, you would set the temporal constraint on the role. Alternatively, you may want to assign a contractors role that applies to an individual user only for the period of their contract of employment.

The following examples show how to set temporal constraints on role definitions, and on individual role grants.

Add a temporal constraint to a role

When you create a role, you can include a temporal constraint in the role definition that restricts the validity of the role, regardless of how that role is granted. Temporal constraints are expressed as a time interval in ISO 8601 date and time format. For more information on this format, refer to the ISO 8601 standard.

The following example adds a contractor role over the REST interface. The role is effective from March 1, 2020 to August 31, 2020:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--request POST \
--data '{
  "name": "contractor",
  "description": "Role granted to contract workers for 2020",
  "temporalConstraints": [
    {
      "duration": "2020-03-01T00:00:00.000Z/2020-08-31T00:00:00.000Z"
    }
  ]
}' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_role?_action=create"
{
  "_id": "ed761370-b24f-4e21-8e58-a3230942da67",
  "_rev": "000000007429750e",
  "name": "contractor",
  "description": "Role granted to contract workers for 2020",
  "temporalConstraints": [
    {
      "duration": "2020-03-01T00:00:00.000Z/2020-08-31T00:00:00.000Z"
    }
  ]
}

This example specifies the time zone as Coordinated Universal Time (UTC) by appending Z to the time. If no time zone information is provided, the time zone is assumed to be local time. To specify a different time zone, include an offset (from UTC) in the format ±hh:mm. For example, an interval of 2020-03-01T00:00:00.000-07:00/2020-08-31T00:00:00.000-07:00 specifies a time zone seven hours behind UTC.

When the period defined by the constraint ends, the role object remains in the repository, but the effective roles script will not include the role in the list of effective roles for any user.

The following example assumes the user scarter was granted a role contractor-march. A temporal constraint was included in the contractor-march role definition, specifying that the role should be applicable only during the month of March 2020. At the end of this period, a query on scarter’s entry shows that his roles property still includes the contractor-march role (with ID 0face495-772d-4d36-a30d-8594618aba0d), but his effectiveRoles property does not:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/<scarterUUID>?_fields=_id,userName,roles,effectiveRoles"
{
  "_id": "scarter",
  "_rev": "00000000e5fdeb51",
  "userName": "scarter",
  "effectiveRoles": [],
  "roles": [
    {
      "_ref": "managed/realm-name_role/0face495-772d-4d36-a30d-8594618aba0d",
      "_refResourceCollection": "managed/realm-name_role",
      "_refResourceId": "0face495-772d-4d36-a30d-8594618aba0d",
      "_refProperties": {
        "_id": "5f41d5a5-19b4-4524-a4b1-445790ff14da",
        "_rev": "00000000cb339810"
      }
    }
  ]
}

The role is still in place but is no longer effective.

To restrict the period a role is valid by using the IDM admin UI, select Temporal Constraint on the role Details tab, then select a time zone offset relative to GMT and the start and end dates for the required period.

Add a temporal constraint to a role grant

To restrict the validity of a role for individual users, apply a temporal constraint at the grant level, rather than as part of the role definition. In this case, the temporal constraint is taken into account per user, when the user’s effective roles are calculated. Temporal constraints defined at the grant level can differ for each user who is a member of that role.

To apply a temporal constraint to a grant over the REST interface, include the constraint as one of the _refProperties of the relationship between the user and the role. The following example assumes a contractor role, with ID ed761370-b24f-4e21-8e58-a3230942da67. The command adds user bjensen as a member of that role, with a temporal constraint that specifies she be a member of the role for one year only, from January 1, 2020 to January 1, 2021:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--request PATCH \
--data '[
  {
    "operation": "add",
    "field": "/members/-",
    "value": {
      "_ref": "managed/realm-name_user/bjensen",
      "_refProperties": {
        "temporalConstraints": [{"duration": "2020-01-01T00:00:00.000Z/2021-01-01T00:00:00.000Z"}]
      }
    }
  }
]' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_role/<contractorUUID>"
{
  "_id": "ed761370-b24f-4e21-8e58-a3230942da67",
  "_rev": "000000007429750e",
  "name": "contractor",
  "description": "Role granted to contract workers for 2020",
  "temporalConstraints": [
    {
      "duration": "2020-03-01T00:00:00.000Z/2020-08-31T00:00:00.000Z"
    }
  ]
}

A query on bjensen’s roles property shows the temporal constraint was applied to this grant:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/<bjensenUUID>/roles?_queryFilter=true"
{
  "result": [
    {
      "_id": "40600260-111d-4695-81f1-450365025784",
      "_rev": "00000000173daedb",
      "_ref": "managed/realm-name_role/ed761370-b24f-4e21-8e58-a3230942da67",
      "_refResourceCollection": "managed/realm-name_role",
      "_refResourceId": "ed761370-b24f-4e21-8e58-a3230942da67",
      "_refProperties": {
        "temporalConstraints": [
          {
            "duration": "2020-01-01T00:00:00.000Z/2021-01-01T00:00:00.000Z"
          }
        ],
        "_id": "40600260-111d-4695-81f1-450365025784",
        "_rev": "00000000173daedb"
      }
    }
  ],
  ...
}

To restrict the period that a role grant is valid using the IDM admin UI, set a temporal constraint when you add the member to the role.

For example, to specify that bjensen is added to a Contractor role only for the period of her employment contract, select Manage > Role, select the Contractor role, then select Add Role Members. On the Add Role Members screen, select bjensen from the list, then enable the Temporal Constraint, and specify the start and end date of her contract.

Use assignments to provision users

Authorization roles control access to IDM itself. Provisioning roles define the rules for how attribute values update on external systems.

You configure these rules using assignments that are attached to a provisioning role definition or directly assigned to a user. Assignments provision an attribute or set of attributes based on an object’s role membership or through a direct assignment. After you configure a synchronization mapping configuration between two resources to provide the basic account provisioning logic (how an account is mapped from a source to a target system), then you can use role assignments to add more logic. The attributes and values that are updated by using assignments might include membership in external groups, access to specific external resources, and so on. A set of assignments can collectively represent a role.

Assignment objects are created, updated, and deleted like any other managed object, and are attached to a role by using the relationships mechanism, in much the same way as a role is granted to a user. Assignments are stored in the repository and are accessible at the context path /openidm/managed/realm-name_assignment.

This section describes how to manage assignments over the REST interface, and by using the Identity Cloud admin UI.

When you create an assignment, and if desired, attach it to a role definition, all user objects that reference that role definition will, as a result, reference the corresponding assignment in their effectiveAssignments attribute.

If you have mapped roles and assignments to properties on a target system, and you are preloading the result set into memory, make sure that your targetQuery returns the mapped property. For example, if you have mapped a specific role to the ldapGroups property on the target system, the target query must include the ldapGroups property when it returns the object.

The following mapping excerpt indicates that the target query must return the _id of the object as well as its ldapGroups property:

"targetQuery": {
    "_queryFilter": true,
    "_fields": "_id,ldapGroups"
}

For more information about preloading the result set for reconciliation operations, refer to Improve Reconciliation Query Performance.

Create an assignment

You can create assignments over the REST interface or using the Identity Cloud admin UI.

Over REST

To create a new assignment over REST, send a PUT or POST request to the /openidm/managed/realm-name_assignment context path.

The following example creates a new managed assignment named employee. The JSON payload in this example shows the following:

  • The assignment is applied for the mapping managedAlpha_user_systemLdapAccounts, so attributes will be updated on the external LDAP system specified in this mapping.

    The external system must be configured through a connector and a mapping defined before you can attach an assignment to the mapping.
  • The name of the attribute on the external system whose value will be set is employeeType, and its value will be set to Employee.

  • When the assignment is applied during a sync operation, the attribute value Employee is added to any existing values for that attribute. When the assignment is removed (if the role is deleted, or if the user is no longer a member of that role), the attribute value Employee is removed from the values of that attribute.

    curl \
    --header "Authorization: Bearer <token>" \
    --header "Accept-API-Version: resource=1.0" \
    --header "Content-Type: application/json" \
    --request POST \
    --data '{
      "name": "employee",
      "description": "Assignment for employees",
      "mapping": "managedAlpha_user_systemLdapAccounts",
      "attributes": [
        {
          "name": "employeeType",
          "value": [
            "Employee"
          ],
          "assignmentOperation": "mergeWithTarget",
          "unassignmentOperation": "removeFromTarget"
        }
      ]
    }' \
    "https://<tenant-env-fqdn>/openidm/managed/realm-name_assignment?_action=create"
    {
      "_id": "1a6a3af3-024f-4cf1-b4f6-116b98053816",
      "_rev": "132bbd98-b3d6-4d70-9274-7bcd4e765d3a-6329",
      "name": "employee",
      "description": "Assignment for employees",
      "mapping": "managedAlpha_user_systemLdapAccounts",
      "attributes": [
        {
          "name": "employeeType",
          "value": [
            "Employee"
          ],
          "assignmentOperation": "mergeWithTarget",
          "unassignmentOperation": "removeFromTarget"
        }
      ]
    }

    At this stage the assignment is not linked to any role, so no user can make use of the assignment. To make use of the assignment, either Add a user directly to an assignment or Add an assignment to a role.

Using the Identity Cloud admin UI
  1. Select Identities > Manage > Alpha realm - Assignments > + New Alpha realm - assignment.

  2. Enter a name, description, and select the mapping to which the assignment should apply.

    The mapping indicates the target resource, that is, the resource on which the attributes specified in the assignment will be adjusted.

  3. Click Next.

  4. Click + Add an attribute to attach an attribute to your assignment.

  5. Select the Target system attribute, enter the Value of the attribute.

  6. Click the gear icon and determine the action to take when assigning and unassigning the attribute to a user:

    1. On Assignment select one of the following:

      • Merge with target: The attribute value is added to any existing values for that attribute. This operation merges the existing value of the target object attribute with the value(s) from the assignment. If duplicate values are found (for attributes that take a list as a value), each value is included only once in the resulting target. This assignment operation is used only with complex attribute values like arrays and objects, and does not work with strings or numbers.

      • Replace target: The attribute value overwrites any existing values for that attribute. The value from the assignment becomes the authoritative source for the attribute.

    2. On Unassignment select one of the following:

      • Remove from target: The attribute value is removed from the system object when the user is no longer a member of the role, or when the assignment itself is removed from the role definition.

      • No Operation: When you remove the assignment from the user’s effectiveAssignments, it has no effect on the current state of the attribute in the system object.

  7. Repeat steps 4-6 until you have added all the attributes required for the assignment.

  8. Click Save.

Modify an assignment

After you create an assignment, you can modify it by doing one or more of the following:

Add script logic when assignment is granted or revoked

After you create an assignment, you can specify custom logic to take place during assignment or unassignment of an assignment.

These scripts apply additional logic or operations that should be performed when a user (or other object) receives or loses an entire assignment. This logic must not be restricted to an operation on a single attribute.

For example, if an assignment is removed from a user, in the onUnassignment event, the system can automatically perform additional actions such as revoking access to any external systems, sending notifications to managers or IT staff, and archiving or deleting the users’s data.

To create a script to associate with an assignment event:

  1. On the Details tab of the assignment in the Event Scripts section, click Add an event script.

  2. In the Event box, select the script to apply to onAssignment or onUnassignment of the assignment to the user.

  3. Define the script by specifying what should happen to each attribute in the script.

    The scriptable onAssignment and onUnassignment events operate at the assignment level, rather than the attribute level.

    The onAssignment and onUnassignment events occur before the onCreate or onUpdate scripts.
    Table 1. Variables available in assignment script
    Variable Description

    sourceObject

    The full, original object from the source system (in this case, Identity Cloud).

    targetObject

    The current, computed value, from the mapping logic. This results from the property mapping logic or prior assignment computation.

    existingTargetObject

    The object that exists (if any) in the current target system, before the update is made.

    linkQualifier

    A string value that represents a version of the source object as it is mapped to a record in the target system. There can be multiple linkQualifiers for a given mapping, but in this context, it is the one being processed.

    attributeName

    The name of the attribute in the assignment to reference.

    attributeValue

    The value of an attribute in the assignment to reference.

    attributesInfo

    A mechanism that allows one invocation of an onAssignment or onUnassignment events to communicate helpful information to other invocations, as needed.

    Role assignment scripts must always return targetObject, otherwise other scripts and code that occur downstream of your script will not work as expected. For example, specify:

    return targetObject;

Add a user directly to an assignment

You can add an assignment directly to users in Identity Cloud instead of through a role.

Add users to an assignment directly over REST or using the Identity Cloud admin UI.

Over REST

Update the assignment definition to include a reference to the ID of the user in the members property of the assignment.

The following example adds the user (ID 1a6a3af3-024f-4cf1-b4f6-116b98053816) to an existing assignment (ID assignmentTest):

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--request PATCH \
--data '[
{
  "operation": "add",
  "field": "/members/-",
  "value": { "_ref": "managed/realm-name_user/1a6a3af3-024f-4cf1-b4f6-116b98053816" }
}
]' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_assignment/assignmentTest"
{
  "_id": "assignmentTest",
  "_rev": "4f50bccb-dbad-46dd-b703-962ae61c77c9-1683",
  "name": "assignmentTest",
  "description": "This is an assignment",
  "mapping": "managedAlpha_user_systemLdapAccounts",
  "attributes": []
}
Using the Identity Cloud admin UI
  1. Select Identities > Manage > Alpha realm - Assignments > assignment.

  2. Select the Assignment Members tab.

  3. Click +Add Assignment Members.

  4. Select the user(s) to directly add to the assignment.

  5. Click Save.

Add an assignment to a role

After you create a role and an assignment, create a relationship between the assignment and the role, in much the same way as a user references a role.

Update a role definition to include one or more assignments over the REST interface or using the Identity Cloud admin UI:

Over REST

Update the role definition to include a reference to the ID of the assignment in the assignments property of the role. The following example adds the employee assignment (ID 1a6a3af3-024f-4cf1-b4f6-116b98053816) to an existing employee role (ID 2243f5f8-ed75-4c3b-b4b3-058d5c58fbb4):

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--request PATCH \
--data '[
{
    "operation": "add",
    "field": "/assignments/-",
    "value": { "_ref": "managed/realm-name_assignment/1a6a3af3-024f-4cf1-b4f6-116b98053816" }
  }
]' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_role/2243f5f8-ed75-4c3b-b4b3-058d5c58fbb4"
{
  "_id": "2243f5f8-ed75-4c3b-b4b3-058d5c58fbb4",
  "_rev": "132bbd98-b3d6-4d70-9274-7bcd4e765d3a-4145",
  "privileges": [],
  "name": "employee",
  "description": "Roll granted to all permanent employees"
}

To check that the assignment was added successfully, query the role’s assignments property:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_role/2243f5f8-ed75-4c3b-b4b3-058d5c58fbb4/assignments?_queryFilter=true&_fields=_ref/*,name,assignments"
{
  "result": [
    {
        "_id": "8189bbb9-a7fb-45cb-b4c0-49a6ddd47b64",
        "_rev": "132bbd98-b3d6-4d70-9274-7bcd4e765d3a-4144",
        "_refResourceCollection": "managed/realm-name_assignment",
        "_refResourceId": "1a6a3af3-024f-4cf1-b4f6-116b98053816",
        "_refResourceRev": "132bbd98-b3d6-4d70-9274-7bcd4e765d3a-6329",
        "name": "Employee",
        "_ref": "managed/realm-name_assignment/alpha_assignment/1a6a3af3-024f-4cf1-b4f6-116b98053816",
        "_refProperties": {
            "_id": "8189bbb9-a7fb-45cb-b4c0-49a6ddd47b64",
            "_rev": "132bbd98-b3d6-4d70-9274-7bcd4e765d3a-4144"
        }
    }
  ],
  ...
}

The assignments property references the assignment shown in the previous step.

To remove an assignment from a role definition, remove the reference to the assignment from the role’s assignments property.

Using the Identity Cloud admin UI

You can assign an assignment to a role in the following ways:

  • From an assignment to a role

  • From a role to an assignment

    From assignment to role
    1. Select Identities > Manage > Alpha realm - Assignments > assignment.

    2. Click the Managed Roles tab.

    3. Click + Add Managed Roles.

    4. Select the role(s) to associate to the assignment.

    5. Click Save.

    From role to assignment
    1. Select Identities > Manage > Alpha realm - Roles > role.

    2. Select the Managed Assignments tab and click + Add Managed Assignments.

    3. Select the assignment(s) to associate to the role.

    4. Click Save.

Delete an assignment

You can delete assignments over REST or using the Identity Cloud admin UI.

Deleting an assignment may result in large downstream impacts, such as removing attributes or access to many users in an external system.
You can delete an assignment, even if it is referenced by a managed role. When the assignment is removed, any users to whom the corresponding roles were granted will no longer have that assignment in their list of effectiveAssignments. For more information about effective roles and effective assignments, refer to Effective roles and effective assignments.
Over REST

To delete an assignment over the REST interface, simply delete that object. The following example deletes the employee assignment created in the previous example:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request DELETE \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_assignment/1a6a3af3-024f-4cf1-b4f6-116b98053816"
{
  "_id": "1a6a3af3-024f-4cf1-b4f6-116b98053816",
  "_rev": "132bbd98-b3d6-4d70-9274-7bcd4e765d3a-6329",
  "name": "employee",
  "description": "Assignment for employees",
  "mapping": "managedAlpha_user_systemLdapAccounts",
  "attributes": [
    {
      "name": "employeeType",
      "value": [
        "Employee"
      ],
      "assignmentOperation": "mergeWithTarget",
      "unassignmentOperation": "removeFromTarget"
    }
  ]
}
Using the Identity Cloud admin UI
  1. In the Identity Cloud admin UI, select Identities > Manage > Alpha realm - Assignments > assignment.

  2. In the Details tab > Delete Alpha realm - Assignment section, click Delete Alpha realm - Assignment.

  3. A confirmation dialog displays. Click Delete.

Effective roles and effective assignments

Effective roles and effective assignments are virtual properties of a user object. IDM uses the relationships between objects to know when to recalculate the values of these properties.

The relationships between objects are configured using the notify, notifySelf, and notifyRelationships settings for managed/realm-name_user, managed/realm-name_role, and managed/realm-name_assignment. The queryConfig property is used to configure which related objects to traverse for this calculation.

Calculation or recalculation is performed when IDM notifies the related objects that the roles or assignments for a managed user have been added, removed, or changed.

The following excerpt of the IDM managed object schema shows how these two virtual properties are constructed for each managed user object:

"effectiveRoles" : {
    "type" : "array",
    "title" : "Effective Roles",
    "description" : "Effective Roles",
    "viewable" : false,
    "returnByDefault" : true,
    "isVirtual" : true,
    "queryConfig" : {
        "referencedRelationshipFields" : ["roles"]
    },
    "usageDescription" : "",
    "isPersonal" : false,
    "items" : {
        "type" : "object",
        "title" : "Effective Roles Items"
    }
},
"effectiveAssignments" : {
    "type" : "array",
    "title" : "Effective Assignments",
    "description" : "Effective Assignments",
    "viewable" : false,
    "returnByDefault" : true,
    "isVirtual" : true,
    "queryConfig" : {
        "referencedRelationshipFields" : ["roles", "assignments"],
        "referencedObjectFields" : ["*"]
    },
    "usageDescription" : "",
    "isPersonal" : false,
    "items" : {
        "type" : "object",
        "title" : "Effective Assignments Items"
    }
}

When a user references a role which references an assignment, that user automatically references the assignment in its list of effective assignments.

effectiveRoles uses the roles relationship to calculate the grants currently in effect, including any qualified by temporal constraints.

effectiveAssignments uses the roles relationship and the assignments relationship for each role to calculate the current assignments in effect for that user. The synchronization engine reads the calculated value of the effectiveAssignments attribute when it processes the user. The target system is updated according to the configured assignmentOperation for each assignment.

When a user’s roles or assignments are updated, IDM calculates their effectiveRoles and effectiveAssignments based on the current value of their roles property and the assignments property of any roles referenced by that property. The previous set of examples showed the creation of a role employee that referenced an assignment employee and was granted to user bjensen. Querying that user entry would show the following effective roles and effective assignments:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/<bjensenUUID>?_fields=userName,roles,effectiveRoles,effectiveAssignments"
{
  "_id": "ca8855fd-a404-42c7-88b7-02f8a8a825b2",
  "_rev": "0000000081eebe1a",
  "userName": "bjensen",
  "effectiveRoles": [
    {
      "_refResourceCollection": "managed/realm-name_role",
      "_refResourceId": "2243f5f8-ed75-4c3b-b4b3-058d5c58fbb4"
      "_ref": "managed/realm-name_role/2243f5f8-ed75-4c3b-b4b3-058d5c58fbb4"
    }
  ],
  "effectiveAssignments": [
    {
      "name": "employee",
      "description": "Assignment for employees.",
      "mapping": "managedUser_systemLdapAccounts",
      "attributes": [
        {
          "assignmentOperation": "mergeWithTarget",
          "name": "employeeType",
          "unassignmentOperation": "removeFromTarget",
          "value": [
            "employee"
          ]
        }
      ],
      "_rev": "0000000087d5a9a5",
      "_id": "46befacf-a7ad-4633-864d-d93abfa561e9"
      "_refResourceCollection": "managed/realm-name_assignment",
      "_refResourceId": "46befacf-a7ad-4633-864d-d93abfa561e9",
      "_ref": "managed/realm-name_assignment/46befacf-a7ad-4633-864d-d93abfa561e9"
    }
  ],
  "roles": [
    {
      "_ref": "managed/realm-name_role/2243f5f8-ed75-4c3b-b4b3-058d5c58fbb4",
      "_refResourceCollection": "managed/realm-name_role",
      "_refResourceId": "2243f5f8-ed75-4c3b-b4b3-058d5c58fbb4",
      "_refProperties": {
        "_id": "93552530-10fa-49a4-865f-c942dffd2801",
        "_rev": "0000000081ed9f2b"
      }
    }
  ]
}

In this example, synchronizing the managed/realm-name_user repository with the external LDAP system defined in the mapping populates user bjensen’s employeeType attribute in LDAP with the value employee.

Roles and relationship change notification

Before you read this section, see Configure relationship change notification to understand the notify and notifyRelationships properties, and how change notification works for relationships in general. In the case of roles, the change notification configuration exists to ensure that managed users are notified when any of the relationships that link users, roles, and assignments are manipulated (that is, created, updated, or deleted).

Consider the situation where a user has role R. A new assignment A is created that references role R. Ultimately, we want to notify all users that have role R so that their reconciliation state will reflect any attributes in the new assignment A. We achieve this notification with the following configuration:

In the managed object schema, the assignment object definition has a roles property that includes a resourceCollection. The path of this resource collection is managed/realm-name_role and "notify" : true for the resource collection:

{
    "name" : "assignment",
    "schema" : {
        ...
        "properties" : {
            ...
            "roles" : {
                ...
                "items" : {
                    ...
                    "resourceCollection" : [
                        {
                            "notify" : true,
                            "path" : "managed/realm-name_role",
                            "label" : "Role",
                            "query" : {
                                "queryFilter" : "true",
                                "fields" : [
                                    "name"
                                ]
                            }
                        }
                    ...
}

With this configuration, when assignment A is created, with a reference to role R, role R is notified of the change. However, we still need to propagate that notification to any users who are members of role R. To do this, we configure the role object as follows:

{
    "name" : "role",
    "schema" : {
        ...
        "properties" : {
            ...
            "assignments" : {
                ...
                "notifyRelationships" : ["members"]
            }
    ...
}

When role R is notified of the creation of a new relationship to assignment A, the notification is propagated through the assignments property. Because "notifyRelationships" : ["members"] is set on the assignments property, the notification is propagated across role R to all members of role R.

Map external groups to internal authz roles

A user’s access to Identity Cloud is based on one or more authorization roles. Authorization roles are cumulative, and are calculated for a user in the following order:

  1. Roles set specifically in the user’s userRoles property

  2. Group roles — based on group membership in an external system

    Group roles are controlled with the following properties in the authentication configuration:

    • groupMembership: the property on the external system that represents group membership. In a DS directory server, that property is ldapGroups by default. In an Active Directory server, the property is memberOf by default. For example:

      "groupMembership" : "ldapGroups"
      The value of the groupMembership property must be the ICF property name defined in the provisioner file, rather than the property name on the external system. For more information on the attributes in connectors, refer to Connector objects and properties.
    • groupRoleMapping: a mapping between an IDM role and a group on the external system. Setting this property ensures that if a user authenticates through pass-through authentication, they are given specific IDM roles depending on their membership in groups on the external system. In the following example, users who are members of the group cn=admins,ou=Groups,dc=example,dc=com are given the internal openidm-admin role when they authenticate:

      "groupRoleMapping" : {
          "internal/role/openidm-admin" : ["cn=admins,ou=Groups,dc=example,dc=com"]
      }
    • groupComparisonMethod: the method used to check whether the authenticated user’s group membership matches one of the groups mapped to an IDM role (in the groupRoleMapping property).

      The groupComparisonMethod can be one of the following:

      • equals: a case-sensitive equality check

      • caseInsensitive: a case-insensitive equality check

      • ldap: a case-insensitive and whitespace-insensitive equality check. Because LDAP directories do not take case or whitespace into account in group DNs, you must set the groupComparisonMethod if you are using pass-through authentication with an LDAP directory.

To control access to external systems, use provisioning roles and assignments, as described in Use assignments to provision users.

Groups

Groups may not be enabled in your tenant. To check if groups are enabled, from the Identity Cloud admin UI, go to Identities > Manage. If Alpha realm - Groups is present, then groups are enabled.

If this is not present, enable groups using the Feature enablement endpoint.

If you previously used AM static groups, submit a ForgeRock Support ticket for guidance on how to migrate group membership to managed groups.

Groups are an important tool for identity management because they simplify managing collections of users by applying permissions and authorizations to all members of a group rather than to individual users. Groups may follow an organization structure or be based on the needs and privileges of an arbitrary set of users.

The managed group object is a default managed object type and is defined like any other managed object type. Managed groups simplify management by using common groups across the entire platform.

Users are made members of groups through the relationships mechanism. You should understand how relationships work before you read about IDM groups.

A group can be assigned to a user manually, as a static value of the user’s groups attribute, or dynamically, as a result of a condition or script. For example, a user might be assigned to a group such as sales dynamically, if that user is in the sales organization.

A user’s groups attribute takes an array of references as a value, where the references point to the managed groups. For example, if user bjensen has been assigned to two groups (employees and supervisors), the value of bjensen’s groups attribute would look something like the following:

"groups": [
  {
    "_ref": "managed/realm-name_group/employees",
    "_refResourceCollection": "managed/realm-name_group",
    "_refResourceId": "employees",
    "_refProperties": {
      "_id": "38a23ddc-1345-48d6-b753-ad97f472a90e",
      "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-1692"
    }
  },
  {
    "_ref": "managed/realm-name_group/supervisors",
    "_refResourceCollection": "managed/realm-name_group",
    "_refResourceId": "supervisors",
    "_refProperties": {
      "_id": "0fabd212-f0c2-4d91-91f2-2b211bb58e89",
      "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-1974"
    }
  }
]
We recommend you use managed objects for all data management in Identity Cloud. While managed groups display in the AM admin UI and can serve the same function as a static group created in AM, they are not the same. A managed group supports dynamic, conditional membership you can leverage in other parts of Identity Cloud.

The _refResourceCollection is the container that holds the group. The _refResourceId is the ID of the group. The _ref property is a resource path derived from the _refResourceCollection and the URL-encoded _refResourceId. _refProperties provides more information about the relationship.

In most cases, Identity Cloud uses UUIDs as the _id for managed objects. Managed groups are an exception: the _id and name properties should match.

Manage groups

You can manage groups over REST or by using the Identity Cloud admin UI.

You can perform the following actions with groups:

Create a group

You can create groups using REST or by using the Identity Cloud admin UI.

Using REST

To create a group, send a PUT or POST request to the /openidm/managed/realm-name_group context path. The following example creates a group named employees, with ID employees:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--request POST \
--data '{
  "name": "employees",
  "description": "Group that includes temporary and permanent employees"
}' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_group?_action=create"
{
  "_id": "employees",
  "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-1028",
  "name": "employees",
  "condition": null,
  "description": "Group that includes temporary and permanent employees"
}

You can also omit ?_action=create and achieve the same result:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--request POST \
--data '{
  "name": "employees2",
  "description": "Second group that includes temporary and permanent employees"
}' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_group"
{
  "_id": "employees2",
  "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-1053",
  "name": "employees2",
  "condition": null,
  "description": "Second group that includes temporary and permanent employees"
}

Using the Identity Cloud admin UI

  1. From the navigation bar, click Identities > Manage > Alpha realm - Groups.

  2. On the Groups page, click New Alpha realm - Group.

  3. On the New Alpha realm - Group page, enter a name and description, and click Next.

  4. Optionally, create a conditional filter to assign the group dynamically. Conditional filters are custom rules you create that, when met, assign the user to your group automatically.

  5. Click Save.

List groups

Using REST

To list groups over REST, query the openidm/managed/realm-name_group endpoint. The following example shows the employees group that you created in the previous example:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_group?_queryFilter=true"
{
  "result": [
    {
      "_id": "employees",
      "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-1028",
      "name": "employees",
      "condition": null,
      "description": "Group that includes temporary and permanent employees"
    },
    {
      "_id": "employees2",
      "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-1053",
      "name": "employees2",
      "condition": null,
      "description": "Second group that includes temporary and permanent employees"
    }
  ],
  "resultCount": 2,
  "pagedResultsCookie": null,
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": -1
}

Using the Identity Cloud admin UI

To list the managed groups in the Identity Cloud admin UI, select Identities > Manage > Alpha realm - Groups.

Add users to a group

You add users to a group through the relationship mechanism. Relationships are references from one managed object to another; in this case, from a user object to a group object. For more information, refer to Relationships between objects.

You can add group members statically (manually) or dynamically (automated assigning through rules).

To add members statically, do one of the following:

  • Update the value of the user’s groups property to reference the group.

  • Update the value of the group’s members property to reference the user.

Dynamic groups use the result of a condition or script to update a user’s list of groups.

Add group members statically

Add a user to a group statically using the REST interface or the Identity Cloud admin UI.

Using REST

Use one of the following methods to add group members over REST:

  • Add the user as a group member. The following example adds user scarter as a member of the employees group:

    curl \
    --header "Authorization: Bearer <token>" \
    --header "Accept-API-Version: resource=1.0" \
    --header "Content-Type: application/json" \
    --request POST \
    --data '{
      "_ref":"managed/realm-name_user/d5b52064-6571-488a-8d85-440a99ed00d4"
    }' \
    "https://<tenant-env-fqdn>/openidm/managed/realm-name_group/employees/members?_action=create"
    {
      "_id": "7ab79f9b-70cc-4205-acec-e675a55c9bcf",
      "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-1479",
      "_ref": "managed/realm-name_user/d5b52064-6571-488a-8d85-440a99ed00d4",
      "_refResourceCollection": "managed/realm-name_user",
      "_refResourceId": "d5b52064-6571-488a-8d85-440a99ed00d4",
      "_refProperties": {
        "_id": "7ab79f9b-70cc-4205-acec-e675a55c9bcf",
        "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-1479"
      }
    }
    This is the preferred method as it does not incur an unnecessary performance cost for groups with many members.
  • Update the user’s groups property.

    The following example adds the employees group to user scarter:

    curl \
    --header "Authorization: Bearer <token>" \
    --header "Accept-API-Version: resource=1.0" \
    --header "Content-Type: application/json" \
    --request PATCH \
    --data '[
      {
        "operation": "add",
        "field": "/groups/-",
        "value": {"_ref" : "managed/realm-name_group/employees2"}
      }
    ]' \
    "https://<tenant-env-fqdn>/openidm/managed/realm-name_user/d5b52064-6571-488a-8d85-440a99ed00d4"
    {
      "_id": "d5b52064-6571-488a-8d85-440a99ed00d4",
      "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-1569",
      "country": null,
      "telephoneNumber": null,
      "mail": "scarter@example.com",
      "memberOfOrgIDs": [],
      "city": null,
      "displayName": null,
      "assignedDashboard": [],
      "effectiveAssignments": [],
      "postalCode": null,
      "description": null,
      "profileImage": null,
      "expireAccount": null,
      "accountStatus": "active",
      "aliasList": [],
      "kbaInfo": [],
      "inactiveDate": null,
      "activeDate": null,
      "consentedMappings": [],
      "sn": "Carter",
      "effectiveGroups": [
        {
          "_refResourceCollection": "managed/realm-name_group",
          "_refResourceId": "employees",
          "_ref": "managed/realm-name_group/employees"
        },
        {
          "_refResourceCollection": "managed/realm-name_group",
          "_refResourceId": "employees2",
          "_ref": "managed/realm-name_group/employees2"
        }
      ],
      "preferences": null,
      "organizationName": null,
      "givenName": "Sam",
      "stateProvince": null,
      "userName": "scarter",
      "postalAddress": null,
      "effectiveRoles": [],
      "activateAccount": null
    }

    When you update a user’s existing groups array, use the - special index to add the new value to the set. For more information, refer to Set semantic arrays in Patch.

  • Update the group’s members property to refer to the user.

    The following sample command makes scarter a member of the employees group:

    curl \
    --header "Authorization: Bearer <token>" \
    --header "Accept-API-Version: resource=1.0" \
    --header "Content-Type: application/json" \
    --request PATCH \
    --data '[
      {
        "operation": "add",
        "field": "/members/-",
        "value": {"_ref" : "managed/realm-name_user/d5b52064-6571-488a-8d85-440a99ed00d4"}
      }
    ]' \
    "https://<tenant-env-fqdn>/openidm/managed/realm-name_group/employees"
    {
      "_id": "employees",
      "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-1028",
      "name": "employees",
      "condition": null,
      "description": "Group that includes temporary and permanent employees"
    }

    The members property of a group is not returned by default in the output. To show all members of a group, you must specifically request the members property. The following example lists the members of the employees group:

    curl \
    --header "Authorization: Bearer <token>" \
    --header "Accept-API-Version: resource=1.0" \
    --request GET \
    "https://<tenant-env-fqdn>/openidm/managed/realm-name_group/employees?_fields=name,members"
    {
      "_id": "employees",
      "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-1028",
      "name": "employees",
      "members": [
        {
          "_ref": "managed/realm-name_user/d5b52064-6571-488a-8d85-440a99ed00d4",
          "_refResourceCollection": "managed/realm-name_user",
          "_refResourceId": "d5b52064-6571-488a-8d85-440a99ed00d4",
          "_refProperties": {
            "_id": "38a23ddc-1345-48d6-b753-ad97f472a90e",
            "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-1692"
          }
        }
      ]
    }
Using the Identity Cloud admin UI

Use one of the following UI methods to add members to a group:

  • Update the user entry:

    1. Select Identities > Manage > Alpha realm - Users and select the user to add.

    2. Select the Group tab and click Add Groups.

      1. Select the group from the dropdown list and click Add.

  • Update the group entry:

    1. Select Identities > Manage > Alpha realm - Groups and select the group to which you want to add members.

    2. Select the Members tab and click Add Members.

    3. Select the user from the dropdown list and click Add.

Add group members dynamically

To add a member to a group dynamically, use a condition, expressed as a query filter, in the group definition. If the condition is true for a member, they are added to the group. A conditional group is a group whose members are based on a defined condition, which you can specify when you create or modify a group. You can create a condition after you create the group as well.

You must configure the properties you use to create a conditional filter for a group as searchable. To configure a property as searchable, update its definition in your managed object configuration. For more information, refer to General purpose extension attributes.

When you create or update a conditional group, Identity Cloud performs the following actions:

  • Assesses all managed users

  • Recalculates the value of the user’s group property. This only takes place if the user is a member of the group.

  • If you remove a condition from a group and members in the group are now not a part of the condition, all members are removed from the group and their group property is updated.

When you define a conditional group in a data set, every user entry (including the mapped entries on remote systems) updates with the relationships implied by that conditional group. The time that it takes to create a new conditional group is impacted by the number of managed users affected by the condition.

In a data set with a large number of users, creating a new conditional group can incur a significant performance cost when you create it. If possible, set up your conditional groups at the beginning of your deployment to avoid performance issues later.

Using REST

To create a conditional group over REST, include the query filter as a value of the condition property in the group definition. The following example creates a group, fr-employees, whose members will be only users who live in France (whose country property is set to FR):

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--request POST \
--data '{
  "name": "fr-employees",
  "description": "Group for employees resident in France",
  "condition": "/country eq \"FR\""
}' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_group?_action=create"
{
  "_id": "fr-employees",
  "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-1898",
  "name": "fr-employees",
  "condition": "/country eq \"FR\"",
  "description": "Group for employees resident in France"
}
Using the Identity Cloud admin UI
  1. Select Identities > Manage > Alpha realm - Groups and select the group to add a condition to.

  2. Select the Settings tab and click Set up.

  3. Toggle the box and define the query filter to assess the condition.

  4. Click Save.

Query a user’s group memberships

To list a user’s groups, query their groups property.

Using REST

The following example shows that scarter is a member of two groups — the employees group and the supervisors group:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/d5b52064-6571-488a-8d85-440a99ed00d4/groups?_queryFilter=true&_fields=_ref/*,name"
{
  "result": [
    {
      "_id": "38a23ddc-1345-48d6-b753-ad97f472a90e",
      "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-1692",
      "_refResourceCollection": "managed/realm-name_group",
      "_refResourceId": "employees",
      "_refResourceRev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-1028",
      "name": "employees",
      "_ref": "managed/realm-name_group/employees",
      "_refProperties": {
        "_id": "38a23ddc-1345-48d6-b753-ad97f472a90e",
        "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-1692"
      }
    },
    {
      "_id": "0fabd212-f0c2-4d91-91f2-2b211bb58e89",
      "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-1974",
      "_refResourceCollection": "managed/realm-name_group",
      "_refResourceId": "supervisors",
      "_refResourceRev": "ae6e63c4-94f5-463b-8fbef-7a359b8e3004-1965",
      "name": "supervisors",
      "_ref": "managed/realm-name_group/supervisors",
      "_refProperties": {
        "_id": "0fabd212-f0c2-4d91-91f2-2b211bb58e89",
        "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-1974"
      }
    }
  ],
  "resultCount": 2,
  "pagedResultsCookie": null,
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": -1
}

Using the Identity Cloud admin UI

  1. Select Identities > Manage > Alpha realm - Users, then select the user whose groups you want to check.

  2. Select the Group tab.

Remove a member from a group

To remove a static group membership from a user entry, do one of the following:

  • Update the value of the user’s groups property to remove the reference to the role.

  • Update the value of the group’s members property to remove the reference to that user.

You can use both of these methods over REST or by using the Identity Cloud admin UI.

A delegated administrator must use PATCH to add or remove relationships.

Conditional group membership can only be removed when the condition is changed or removed, or when the group itself is deleted.

Using REST

Use one of the following methods to remove a member from a group:

  • DELETE the group from the user’s groups property, including the reference ID (the ID of the relationship between the user and the group) in the delete request.

    The following example removes the employees group from user scarter. The ID required in the DELETE request is not the ID of the group but the reference _id of the relationship:

    curl \
    --header "Authorization: Bearer <token>" \
    --header "Accept-API-Version: resource=1.0" \
    --request DELETE \
    "https://<tenant-env-fqdn>/openidm/managed/realm-name_user/d5b52064-6571-488a-8d85-440a99ed00d4/groups/e450a32c-e289-49e3-8de5-b0f84e07c740"
    {
      "_id": "e450a32c-e289-49e3-8de5-b0f84e07c740",
      "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-2122",
      "_ref": "managed/realm-name_group/employees",
      "_refResourceCollection": "managed/realm-name_group",
      "_refResourceId": "employees",
      "_refProperties": {
        "_id": "e450a32c-e289-49e3-8de5-b0f84e07c740",
        "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-2122"
      }
    }
  • PATCH the user entry to remove the group from the array of groups, specifying the value of the group object in the JSON payload.

    When you remove a group in this way, you must include the entire object in the value, as shown in the following example:

    curl \
    --header "Content-type: application/json" \
    --header "Authorization: Bearer <token>" \
    --header "Accept-API-Version: resource=1.0" \
    --request PATCH \
    --data '[
      {
        "operation" : "remove",
        "field" : "/groups",
        "value" : {
          "_ref": "managed/realm-name_group/employees",
          "_refResourceCollection": "managed/realm-name_group",
          "_refResourceId": "employees",
          "_refProperties": {
            "_id": "731120c0-a4e9-4e27-b201-7442169e8b7c",
            "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-2218"
          }
        }
      }
    ]' \
    "https://<tenant-env-fqdn>/openidm/managed/realm-name_user/d5b52064-6571-488a-8d85-440a99ed00d4"
    {
      "_id": "d5b52064-6571-488a-8d85-440a99ed00d4",
      "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-2387",
      "country": null,
      "telephoneNumber": null,
      "mail": "scarter@example.com",
      "memberOfOrgIDs": [],
      "city": null,
      "displayName": null,
      "assignedDashboard": [],
      "effectiveAssignments": [],
      "postalCode": null,
      "description": null,
      "profileImage": null,
      "expireAccount": null,
      "accountStatus": "active",
      "aliasList": [],
      "kbaInfo": [],
      "inactiveDate": null,
      "activeDate": null,
      "consentedMappings": [],
      "sn": "Carter",
      "effectiveGroups": [
        {
          "_refResourceCollection": "managed/realm-name_group",
          "_refResourceId": "supervisors",
          "_ref": "managed/realm-name_group/supervisors"
        }
      ],
      "preferences": null,
      "organizationName": null,
      "givenName": "Sam",
      "stateProvince": null,
      "userName": "scarter",
      "postalAddress": null,
      "effectiveRoles": [],
      "activateAccount": null
    }
  • DELETE the user from the group’s members property, including the reference ID (the ID of the relationship between the user and the role) in the delete request.

    The following example first queries the members of the employees group, to obtain the ID of the relationship, then removes scarter’s membership from that group:

    curl \
    --header "Authorization: Bearer <token>" \
    --header "Accept-API-Version: resource=1.0" \
    --request GET \
    "https://<tenant-env-fqdn>/openidm/managed/realm-name_group/employees/members?_queryFilter=true&_fields=_ref/*,name"
    {
      "result": [
        {
          "_id": "ef3261cd-a66f-4d3e-aad8-c0850e0b4a0e",
          "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-2430",
          "_refResourceCollection": "managed/realm-name_user",
          "_refResourceId": "d5b52064-6571-488a-8d85-440a99ed00d4",
          "_refResourceRev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-2432",
          "_ref": "managed/realm-name_user/d5b52064-6571-488a-8d85-440a99ed00d4",
          "_refProperties": {
            "_id": "ef3261cd-a66f-4d3e-aad8-c0850e0b4a0e",
            "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-2430"
          }
        }
      ],
      "resultCount": 1,
      "pagedResultsCookie": null,
      "totalPagedResultsPolicy": "NONE",
      "totalPagedResults": -1,
      "remainingPagedResults": -1
    }
    
    curl \
    --header "Authorization: Bearer <token>" \
    --header "Accept-API-Version: resource=1.0" \
    --request DELETE \
    "https://<tenant-env-fqdn>/openidm/managed/realm-name_group/employees/members/ef3261cd-a66f-4d3e-aad8-c0850e0b4a0e"
    {
      "_id": "ef3261cd-a66f-4d3e-aad8-c0850e0b4a0e",
      "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-2430",
      "_ref": "managed/realm-name_user/d5b52064-6571-488a-8d85-440a99ed00d4",
      "_refResourceCollection": "managed/realm-name_user",
      "_refResourceId": "d5b52064-6571-488a-8d85-440a99ed00d4",
      "_refProperties": {
        "_id": "ef3261cd-a66f-4d3e-aad8-c0850e0b4a0e",
        "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-2430"
      }
    }

Using the Identity Cloud admin UI

Use one of the following methods to remove a group member:

  • Select Identities > Manage > Users and select the user whose group or groups you want to remove.

    Select the Group tab, select the group you want to remove, then select Remove.

  • Select Identities > Manage > Groups, and select the group whose members you want to remove.

    Select the Members tab, select the member or members you want to remove, then select Remove.

Delete a group

Deleting a group removes all users in the group. This action cannot be undone.

Using REST

To delete a group over the REST interface, simply delete that managed object. The following command deletes the employees group created in the previous section:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request DELETE \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_group/employees"
{
  "_id": "employees",
  "_rev": "ae6e63c4-94f5-463b-8bef-7a359b8e3004-1028",
  "name": "employees",
  "condition": null,
  "description": "Group that includes temporary and permanent employees"
}

Using the Identity Cloud admin UI

  1. Select Identities > Manage > Alpha realm - Groups.

  2. Select the group to delete.

  3. Click then Delete Alpha realm - Group.

  4. A confirmation dialog displays. Click Delete.

Organizations

Organization objects let you arrange and manage users in hierarchical trees. Organizations also allow you to give users fine-grained administrative privileges to various parts of the tree based on their location in that tree. For example, an administrator of one organization might have full access to the users within that organization but no access to the users in an adjacent organization.

IDM comes with two types of managed objects for organizations: Alpha realm organizations and Bravo realm organizations. The default schemas for these two organization types are similar, except that Alpha realm organizations have relationships with Alpha realm users, while Bravo realm organizations have relationships with Bravo realm users. You can modify the default schemas of either of these managed object types; refer to Define managed object schema for more information.

The Alpha and Bravo organization object types have array attributes called admins, owners, and members. These attribute enable the hierarchical organization model.

Users and organizations have a set of relationship-derived virtual properties used by the delegated administration filters to provide the visibility and access constraints that underpin the organization model. Users have the ids of all the organizations of which they are members, and organizations have the ids of all their admin and owner users.

Only IDM administrative users can create top-level organizations. Within organizations, there are various levels of privileges, depending on how a user is related to the organization.

Refer to the organization use case for an example that illustrates organization concepts, including:

  • Organizations in the Alpha and Bravo realms

  • Hierarchies of organizations

  • Organization owners

  • Organization administrators

Manage organizations over REST

IDM provides RESTful access to managed organizations, at the context path /openidm/managed/realm-name_organization. You can add, change, and delete organizations by using the IDM admin UI or over the REST interface. To use the IDM admin UI, select Manage > Organization.

The examples on this page show how to add, query, modify, and delete organizations over the REST interface. For a reference of all managed organization endpoints and actions, refer to Managed organizations.

Add and modify organizations

The examples in this section create the example-org organization and add admins and members to the organization. In this organization, users bjensen and scarter can create and delete child organizations, also known as suborganizations, of example-org, and can create and delete members within the child organizations:

example-org
Add a top level organization to IDM.

Only IDM tenant administrators can create top level organizations.

curl \
--header "Authorization: Bearer <token>" \
--header "Content-Type: application/json" \
--header "Accept-API-Version: resource=1.0" \
--header "If-None-Match: *" \
--request PUT \
--data '{
  "name": "example-org"
}' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_organization/example-org"
{
  "_id": "example-org",
  "name": "example-org"
  ...
}
Make a user the organization’s owner.

IDM tenant administrators can designate organizations' owners. In this example, the Identity Management tenant administrator makes bjensen the owner of the example-org organization created previously. The example assumes the user bjensen already exists:

curl \
--header "Authorization: Bearer <token>" \
--header "Content-Type: application/json" \
--header "Accept-API-Version: resource=1.0" \
--request POST \
--data '{
  "_ref":"managed/realm-name_user/<bjensenUUID>"
}' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_organization/example-org/owners?_action=create"
Add a member to the organization.

Organization owners can create members in the organizations that they own. In this example, bjensen creates user scarter. bjensen also makes scarter a member of the example-org organization:

curl \
--header "Authorization: Bearer <token>" \
--header "Content-Type: application/json" \
--header "Accept-API-Version: resource=1.0" \
--request POST \
--data '{
  "userName": "scarter",
  "sn": "Carter",
  "givenName": "Steven",
  "mail": "scarter@example.com",
  "password": "Th3Password!",
  "memberOfOrg": [{"_ref": "managed/realm-name_organization/example-org"}]
}' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_action=create"
{
 ...
 "mail":"scarter@example.com",
 "memberOfOrgIDs":["example-org"],
 ...
}
Make one of the organization’s members an admin.

Organization owners can designate admins for the organizations they own. An organization admin must be a member of the organization. In this example, bjensen makes scarter an admin of the example-org organization:

curl \
--header "Authorization: Bearer <token>" \
--header 'Content-Type: application/json' \
--header "Accept-API-Version: resource=1.0" \
--request PATCH \
--data '[
    {
        "operation": "add",
        "field": "/admins/-",
        "value": {
          "_ref": "managed/realm-name_user/<scarterUUID>"
        }
    }
]' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_organization/example-org"
{
  "_id": "example-org",
  ...
  "name": "example-org"
}
Add a member to the organization.

Organization admins can add members to the organizations they administer. In this example, the organization admin, scarter, creates a new member, jsanchez. scarter also makes jsanchez a member of the example-org organization:

curl \
--header "Authorization: Bearer <token>" \
--header "Content-Type: application/json" \
--header "Accept-API-Version: resource=1.0" \
--request POST \
--data '{
  "userName": "jsanchez",
  "sn": "Sanchez",
  "givenName": "Juanita",
  "mail": "jsanchez@example.com",
  "password": "Th3Password!",
  "memberOfOrg": [{"_ref": "managed/realm-name_organization/example-org"}]
}' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_action=create"
{
 ...
 "mail":"jsanchez@example.com",
 "memberOfOrgIDs":["example-org"],
 ...
}
Create a child organization.

Organization owners and admins can create and manage child organizations of the organizations they own or administer. In this example, the organization owner, bjensen, creates a new organization named example-child-org, and makes it a child organization of the example-org organization:

curl \
--header "Authorization: Bearer <token>" \
--header "Content-Type: application/json" \
--header "Accept-API-Version: resource=1.0" \
--header "If-None-Match: *" \
--request POST \
--data '{
  "name": "example-child-org",
  "parent": {"_ref": "managed/realm-name_organization/example-org"}
}' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_organization?_action=create"
{
  ...
  "parentIDs":["example-org"],
  ...
  "name":"example-child-org"
}

When creating a child organization, you need to add custom attributes to the access flags for the owner-view-update-delete-orgs and owner-create-orgs privileges. After you add these attributes, you can create a child organization and the custom attributes are visible.

For more information on adding and updating privileges that apply to managed organizations, refer to Server configuration.

Query organizations

The examples in this section demonstrate several ways you can query organizations and organization membership:

List all the organizations a user owns.

This example lists the organizations bjensen owns:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/<bjensenUUID>/ownerOfOrg?_queryFilter=true"
{
  "result": [
    {
      ...
      "_ref": "managed/realm-name_organization/example-org",
      "_refResourceCollection": "managed/realm-name_organization",
      "_refResourceId": "example-org",
      ...
    }
  ],
  ...
}
List an organization’s members.

Organization owners can list the members of the organizations they own. In this example, bjensen lists the members of the example-org organization:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_organization/example-org/members?_queryFilter=true"
{
  "result": [
    ...
  ],
  "resultCount":1,
  ...
}
List organizations that you own or administer, and list their child organizations.

An organization owner or admin can list the organizations that they own or administer. When a user runs the curl command in this example, it lists:

  • The organizations that the user owns or administers

  • Those organizations' child organizations

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_organization?_queryFilter=true"
{
  "result": [
    {
      "_id":"example-org",
      "parentIDs":[],
      "name":"example-org"
    },
    {
      "_id":"<example-child-orgUUID>",
      "parentIDs":["example-org"],
      "name":"example-child-org"
    }
    "resultCount":2,
  ...
}
List organizations of which another user is a member.

Organization owners and admins can list all the organizations they own or administer that contain a given user. In this example, scarter lists the organizations of which jsanchez is a member:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/<jsanchezUUID>?_fields=memberOfOrg"
{
  "_id": ...
  "memberOfOrg":[
    {
      "_ref":"managed/realm-name_organization/example-org",
      "_refResourceCollection":"managed/realm-name_organization",
      "_refResourceId":"example-org",
      ...
}

Grow organizations downward if possible

The relationship-derived virtual properties that support the organization model are calculated in response to relationship signals that travel down the organization tree hierarchy. For example, suppose you:

  • Add a new root organization to an existing organization hierarchy

  • Add a new admin or owner to the root organization in an existing organization hierarchy

The relationship signals that trigger relationship-derived virtual property calculation are propagated down to all organizations in the organization hierarchy, and to all the members of the organizations in the hierarchy. This updates their relationship-derived virtual property state.

If there are many thousands of members of the organizations in the hierarchy, such an operation can take a long time to complete. Because of this, it is a best practice to grow organization hierarchies downward, adding new organizations as leaves of an existing hierarchy, and adding new admins and members to the leaves in the hierarchy tree. This is preferable to growing the hierarchy upwards, starting with the leaves, and then growing the hierarchy up towards the root organization.

If you must add a new root to an existing organization hierarchy with many organizations and many members, or add a new admin or owner to an organization near the top of the hierarchy, perform the operations over the command line, using the examples in Manage organizations over REST.

Use policies to validate data

Identity Cloud provides a policy service that lets you apply specific validation requirements to various components and properties.

The policy service provides a REST interface for reading policy requirements and validating the properties of components against configured policies. Objects and properties are validated automatically when they are created, updated, or patched. Policies are generally applied to user passwords, but can also be applied to any managed or system object, and to internal user objects.

The policy service lets you accomplish the following tasks:

  • Read the configured policy requirements of a specific component.

  • Read the configured policy requirements of all components.

  • Validate a component object against the configured policies.

  • Validate the properties of a component against the configured policies.

The router service limits policy validation to managed and internal user objects. To apply policies to additional objects, such as the audit service, modify your project’s router configuration. For more information about the router service, refer to Script triggers defined in the router configuration.

A configurable default policy applies to all managed objects.

Apply policies to managed objects

In Identity Cloud, policies can be applied to managed objects using default policies.

You can add a policy using:

Be cautious when using validation policies. If a policy relates to an array of relationships Return by Default should always be set to false. You can verify this in your managed object configuration. Any managed object that has items of "type" : "relationship", must also have "returnByDefault" : false.

The policy configuration determines which policies apply to resources other than managed objects. The default policy configuration includes policies that are applied to internal user objects, but you can extend the configuration to apply policies to system objects.

Policy configuration objects

Each element of the policy is defined in a policy configuration object. The structure of a policy configuration object is as follows:

{
    "policyId": "minimum-length",
    "policyExec": "minLength",
    "clientValidation": true,
    "validateOnlyIfPresent": true,
    "policyRequirements": ["MIN_LENGTH"]
}

policyId

A unique ID that enables the policy to be referenced by component objects.

policyExec

The name of the function that contains the policy implementation. For more information, refer to Policy Implementation Functions.

clientValidation

Indicates whether the policy decision can be made on the client. When "clientValidation": true, the source code for the policy decision function is returned when the client requests the requirements for a property.

validateOnlyIfPresent

Notes that the policy is to be validated only if the field within the object being validated exists.

policyRequirements

An array containing the policy requirement ID of each requirement that is associated with the policy. Typically, a policy will validate only one requirement, but it can validate more than one.

Policy reference

You can apply policies defined by Identity Cloud to any managed or internal object.

Identity Cloud includes the following default policies and parameters:

Policy Id Parameters

required

The property is required; not optional.

not-empty

The property can’t be empty.

not-null

The property can’t be null.

unique

The property must be unique.

valid-username

Tests for uniqueness and internal user conflicts.

no-internal-user-conflict

Tests for internal user conflicts.

regexpMatches

Matches a regular expression.

regexp

flags

The regular expression pattern.

valid-query-filter

Tests for a valid query filter.

valid-array-items

Tests for valid array items.

valid-date

Tests for a valid date.

valid-formatted-date

Tests for a valid date format.

valid-time

Tests for a valid time.

valid-datetime

Tests for a valid date and time.

valid-duration

Tests for a valid duration format.

valid-email-address-format

Tests for a valid email address.

valid-name-format

Tests for a valid name format.

valid-phone-format

Tests for a valid phone number format.

at-least-X-capitals

The property must contain the minimum specified number of capital letters.

numCaps

Minimum number of capital letters.

at-least-X-numbers

The property must contain the minimum specified number of numbers.

numNums

Minimum number of numbers.

validNumber

Tests for a valid number.

minimumNumber

The property value must be greater than the minimum.

minimum

The minimum value.

maximumNumber

The property value must be less than the maximum.

maximum

The maximum value.

minimum-length

The property’s minimum string length.

minLength

The minimum string length.

maximum-length

The property’s maximum string length.

maxLength

The maximum string length.

cannot-contain-others

The property cannot contain values of the specified fields.

disallowedFields

A comma-separated list of the fields to check against. For example, the default managed user password policy specifies userName,givenName,sn as disallowed fields.

cannot-contain-characters

The property cannot contain the specified characters.

forbiddenChars

A comma-separated list of disallowed characters. For example, the default managed user userName policy specifies / as a disallowed character.

cannot-contain-duplicates

The property cannot contain duplicate characters.

mapping-exists

A sync mapping must exist for the property.

valid-permissions

Tests for valid permissions.

valid-accessFlags-object

Tests for valid access flags.

valid-privilege-path

Tests for a valid privilege path.

valid-temporal-constraints

Tests for valid temporal constraints.

Policy configuration element

Properties defined in the managed object configuration can include a policies element that specifies how policy validation should be applied to that property. The following excerpt of the default managed object configuration shows how policy validation is applied to the id property of a managed/realm-name_user object.

You can only declare policies on top-level managed object attributes. Nested attributes (those within an array or object) cannot have policies declared on them.
{
    "name" : "user",
    "schema" : {
        "id" : "http://jsonschema.net",
        "properties" : {
            "_id" : {
                "description" : "User ID",
                "type" : "string",
                "viewable" : false,
                "searchable" : false,
                "userEditable" : false,
                "usageDescription" : "",
                "isPersonal" : false,
                "policies" : [
                    {
                        "policyId" : "cannot-contain-characters",
                        "params" : {
                            "forbiddenChars" : [
                                "/"
                            ]
                        }
                    }
                ]
            },
            "password" : {
                "title" : "Password",
                "description" : "Password",
                "type" : "string",
                "viewable" : false,
                "searchable" : false,
                "userEditable" : true,
                "encryption" : {
                    "purpose" : "idm.password.encryption"
                },
                "scope" : "private",
                "isProtected": true,
                "usageDescription" : "",
                "isPersonal" : false
            }
        }
    }
}

The policy for the _id property references the function cannot-contain-characters. This is a default policy that you can apply.

Validate managed object data types

The type property of a managed object specifies the data type of that property; for example, array, boolean, number, null, object, or string. For more information about data types, refer to the JSON Schema Primitive Types section of the JSON Schema standard.

The type property is subject to policy validation when a managed object is created or updated. Validation fails if data does not match the specified type, such as when the data is an array instead of a string. The default valid-type policy enforces the match between property values and the type defined in the managed object configuration.

Identity Cloud supports multiple valid property types. For example, you might have a scenario where a managed user can have more than one telephone number, or a null telephone number (when the user entry is first created and the telephone number is not yet known). In such a case, you could specify the accepted property type as follows in your managed object configuration:

"telephoneNumber" : {
    "type" : "string",
    "title" : "Telephone Number",
    "description" : "Telephone Number",
    "viewable" : true,
    "userEditable" : true,
    "pattern" : "^\\+?([0-9\\- \\(\\)])*$",
    "usageDescription" : "",
    "isPersonal" : true,
    "policies" : [
        {
            "policyId" : "minimum-length",
            "params" : {
                "minLength" : 1
            }
        },
        {
            "policyId": "maximum-length",
            "params": {
                "maxLength": 255
            }
        }
    ]
}

In this case, the type is defined in the policy configuration. The policy checks the telephone number for an accepted type and pattern, either for a real telephone number or a null entry.

Configure policy validation using the admin UI

To configure policy validation for a managed object type using the UI, update the configuration of the object type:

  1. From the Identity Cloud admin UI, click Native Consoles > Identity Management.

  2. From the navigation bar, click Configure > Managed Objects.

  3. On the Managed Objects page, edit or create a managed object.

  4. On the Managed Object NAME page, do one of the following:

    • To edit an existing property, click the property.

    • To create a property, click Add a Property, enter the required information, and click Save.

      • Click the property.

  5. From the Validation tab, click Add Policy.

  6. In the Add/Edit Policy window, enter information in the following fields, and click Add or Save:

    Policy Id

    Refers to the unique PolicyId.

    For a list of the default policies, refer to the Policy Reference.

    Parameter Name

    Refers to the parameters for the PolicyId. For a list of the default policy parameters, refer to the Policy Reference.

    Value

    The parameter’s value to validate.

Show Me
createPolicyUI

Add conditional policy definitions

You can extend the policy service to support policies that are applied only under specific conditions. To apply a conditional policy to managed objects, add the policy to your project’s managed object configuration. To apply a conditional policy to other objects, add it to your project’s policy configuration.

The following managed object configuration shows a sample conditional policy for the password property of managed user objects. The policy indicates that sys-admin users have a more lenient password policy than regular employees:

{
    "objects" : [
        {
            "name" : "user",
            ...
                "properties" : {
                ...
                    "password" : {
                        "title" : "Password",
                        "type" : "string",
                        ...
                        "conditionalPolicies" : [
                            {
                                "condition" : {
                                    "type" : "text/javascript",
                                    "source" : "(fullObject.org === 'sys-admin')"
                                },
                                "dependencies" : [ "org" ],
                                "policies" : [
                                    {
                                        "policyId" : "at-least-X-numbers",
                                        "params" : {
                                            "numNums" : ["1"]
                                        }
                                    }
                                ]
                            },
                            {
                                "condition" : {
                                    "type" : "text/javascript",
                                    "source" : "(fullObject.org === 'employees')"
                                },
                                "dependencies" : [ "org" ],
                                "policies" : [
                                    {
                                        "policyId" : "at-least-X-numbers",
                                        "params" : {
                                            "numNums" : ["2"]
                                        }
                                    }
                                ]
                            }
                        ],
                        "fallbackPolicies" : [
                            {
                                "policyId" : "at-least-X-numbers",
                                "params" : {
                                    "numNums" : ["1"]
                                }
                            }
                        ]
                    }
                    ...
}

There are two distinct scripted conditions (defined in the condition elements). The first condition asserts that the user object, contained in the fullObject argument, is a member of the sys-admin org. If that assertion is true, the at-least-X-numbers policy is applied to the password attribute of the user object, and minimum numbers is set to 1.

The second condition asserts that the user object is a member of the employees org. If that assertion is true, the at-least-X-numbers policy is applied to the password attribute of the user object, and the minimum numbers is 2.

In the event that neither condition is met (the user object is not a member of the sys-admin org or the employees org), an optional fallback policy can be applied. In this example, the fallback policy also references the at-least-X-numbers policy and specifies that for such users, the minimum numbers is 1.

The dependencies field prevents the condition scripts from being run at all, if the user object does not include an org attribute.

Scripted conditions do not apply to progressive profiling.

Manage policies over REST

Manage policies over REST through the policy configuration.

List the defined policies

The following REST call displays a list of all the policies defined (policies for objects other than managed objects). The policy objects are returned in JSON format, with one object for each defined policy ID:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/policy"
{
  "_id": "",
  "resources": [
    ...
    {
      "resource": "internal/user/*",
      "properties": [
        {
          "name": "_id",
          "policies": [
            {
              "policyId": "cannot-contain-characters",
              "params": {
                "forbiddenChars": [ "/" ]
              },
              "policyFunction": "\nfunction (fullObject, value, params, property) {\n    ...",
              "policyRequirements": [
                "CANNOT_CONTAIN_CHARACTERS"
              ]
            }
          ],
          "policyRequirements": [
            "CANNOT_CONTAIN_CHARACTERS"
          ]
        }
        ...
      ]
      ...
    }
  ]
}

To display the policies that apply to a specific resource, include the resource name in the URL. For example, the following REST call displays the policies that apply to managed users:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/policy/managed/realm-name_user/*"
{
  "_id": "*",
  "resource": "managed/realm-name_user/*",
  "properties": [
    {
      "policyRequirements": [
        "VALID_TYPE",
        "CANNOT_CONTAIN_CHARACTERS"
      ],
      "fallbackPolicies": null,
      "name": "_id",
      "policies": [
        {
          "policyRequirements": [
            "VALID_TYPE"
          ],
          "policyId": "valid-type",
          "params": {
            "types": [
              "string"
            ]
          }
        },
        {
          "policyId": "cannot-contain-characters",
          "params": {
            "forbiddenChars": [ "/" ]
          },
          "policyFunction": "...",
          "policyRequirements": [
            "CANNOT_CONTAIN_CHARACTERS"
          ]
        }
      ],
      "conditionalPolicies": null
    }
    ...
  ]
}

Validate objects and properties over REST

To verify that an object adheres to the requirements of all applied policies, include the validateObject action in the request.

The following example verifies that a new managed user object is acceptable, in terms of the policy requirements. Note that the ID in the URL (test in this example) is ignored—the action simply validates the object in the JSON payload:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--request POST \
--data '{
  "sn": "Jones",
  "givenName": "Bob",
  "telephoneNumber": "0827878921",
  "passPhrase": null,
  "mail": "bjones@example.com",
  "accountStatus": "active",
  "userName": "bjones@example.com",
  "password": "123"
}' \
"https://<tenant-env-fqdn>/openidm/policy/managed/realm-name_user/test?_action=validateObject"
{
  "result": false,
  "failedPolicyRequirements": [
    {
      "policyRequirements": [
        {
          "policyRequirement": "MIN_LENGTH",
          "params": {
            "minLength": 8
          }
        }
      ],
      "property": "password"
    },
    {
      "policyRequirements": [
        {
          "policyRequirement": "AT_LEAST_X_CAPITAL_LETTERS",
          "params": {
            "numCaps": 1
          }
        }
      ],
      "property": "password"
    }
  ]
}

The result (false) indicates that the object is not valid. The unfulfilled policy requirements are provided as part of the response - in this case, the user password does not meet the validation requirements.

Use the validateProperty action to verify that a specific property adheres to the requirements of a policy.

The following example checks whether a user’s new password (12345) is acceptable:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--request POST \
--data '{
  "password": "12345"
}' \
"https://<tenant-env-fqdn>/openidm/policy/managed/realm-name_user/9dce06d4-2fc1-4830-a92b-bd35c2f6bcbb?_action=validateProperty"
{
  "result": false,
  "failedPolicyRequirements": [
    {
      "policyRequirements": [
        {
          "policyRequirement": "MIN_LENGTH",
          "params": {
            "minLength": 8
          }
        }
      ],
      "property": "password"
    },
    {
      "policyRequirements": [
        {
          "policyRequirement": "AT_LEAST_X_CAPITAL_LETTERS",
          "params": {
            "numCaps": 1
          }
        }
      ],
      "property": "password"
    }
  ]
}

The result (false) indicates that the password is not valid. The unfulfilled policy requirements are provided as part of the response - in this case, the minimum length and the minimum number of capital letters.

Validating a property that fulfills the policy requirements returns a true result, for example:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--request POST \
--data '{
  "password": "1NewPassword"
}' \
"https://<tenant-env-fqdn>/openidm/policy/managed/realm-name_user/9dce06d4-2fc1-4830-a92b-bd35c2f6bcbb?_action=validateProperty"
{
  "result": true,
  "failedPolicyRequirements": []
}

Validate field removal

To validate field removal, specify the fields to remove when calling the policy validateProperty action. You cannot remove fields that:

  • Are required in the required schema array.

  • Have a required policy.

  • Have a default value.

The following example validates the removal of the fields description and givenName:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--request POST \
--data '{
  "_remove": [ "description", "givenName" ]
}' \
"https://<tenant-env-fqdn>/openidm/policy/managed/realm-name_user/ca5a3196-2ed3-4a76-8881-30403dee70e9?_action=validateProperty"

Because givenName is a required field, IDM returns a failed policy validation:

{
  "result": false,
  "failedPolicyRequirements": [
    {
      "policyRequirements": [
        {
          "policyRequirement": "REQUIRED"
        }
      ],
      "property": "givenName"
    }
  ]
}

Force validation of default values

IDM does not perform policy validation for default values specified in the managed objects schema. It may be necessary to force validation when validating properties for an object that does not yet exist. To force validation, include forceValidate=true in the request URL.

Validate properties to unknown resource paths

To perform a validateProperty action to a path that is unknown (*), such as managed/realm-name_user/* or managed/realm-name_user/userDoesntExistYet, the payload must include:

  • An object field that contains the object details.

  • A properties field that contains the properties to be evaluated.

Pre-registration validation example

A common use case for validating properties for unknown resources is prior to object creation, such as during pre-registration.

  1. Always pass the object and properties content in the POST body because Identity Cloud has no object to look up.

  2. Use any placeholder id in the request URL, as * has no special meaning in the API.

    This example uses a conditional policy for any object with the description test1:

    "givenName" : {
        ...
        "conditionalPolicies" : [
            {
                "condition" : {
                    "type" : "text/javascript",
                    "source" : "(fullObject.description === 'test1')"
                },
                "dependencies" : [ "description" ],
                "policies" : [
                    {
                        "policyId" : "at-least-X-capitals",
                        "params" : {
                            "numCaps" : 1
                        }
                    }
                ]
            }
        ],
  3. Using the above conditional policy, you could perform a validateProperty action to managed/realm-name_user/* with the request:

    curl \
    --header "Authorization: Bearer <token>" \
    --header "Accept-API-Version: resource=1.0" \
    --header "Content-Type: application/json" \
    --request POST \
    --data '{
      "object": {
        "description": "test1"
      },
      "properties": {
        "givenName": "passw0rd"
      }
    }' \
    "https://<tenant-env-fqdn>/openidm/policy/managed/realm-name_user/*?_action=validateProperty"
    {
      "result": false,
      "failedPolicyRequirements": [
        {
          "policyRequirements": [
            {
              "params": {
                "numCaps": 1
              },
              "policyRequirement": "AT_LEAST_X_CAPITAL_LETTERS"
            }
          ],
          "property": "givenName"
        }
      ]
    }

Access data objects

Identity Cloud gives you the ability to access various data objects such as:

  • Managed objects

  • Configuration objects

  • Repository objects

You can perform various actions on these objects. Identity Cloud standardizes the objects through a uniform programming model. A uniform programming model means that all objects are queried and manipulated using the Resource API. The URL or URI that is used to identify the target object for an operation depends on the object type.

The various subsections explore the following:

  • Access data objects using scripts

  • Access data objects using REST

  • Access data objects (from one Identity Cloud tenant/IDM instance to another) via a remote proxy

  • Query data objects

Access data objects using scripts

IDM gives you the ability to access various data objects (such as managed objects, configuration objects, repository objects and so on) and perform actions (functions) through inline scripts. Identity Cloud standardizes the objects through a uniform programming model.

For more information about scripts and the objects available to scripts, refer to Scripting.

You can use the Resource API to obtain managed, system, configuration, and repository objects, as follows:

val = openidm.read("managed/realm-name_organization/mysampleorg")
val = openidm.read("system/mysystem/account")
val = openidm.read("config/custom/mylookuptable")
val = openidm.read("repo/custom/mylookuptable")

For information about constructing an object ID, refer to URI Scheme.

For information on all the actions you can take on a resource, refer to scripting functions.

Access data objects using the REST API

IDM provides access to data objects through the ForgeRock REST API. To access objects over REST, you can use a browser-based REST client, such as the Simple REST Client for Chrome or RESTClient for Firefox. Alternatively, you can use the curl command-line utility.

Refer to the REST API for a comprehensive overview.

To obtain a managed object through the REST API, perform an HTTP GET on the corresponding URL; for example:

https://<tenant-env-fqdn>/openidm/managed/realm-name_organization/mysampleorg
Performing an HTTP GET on the corresponding URL is dependent on your security settings and authentication configuration.

By default, the HTTP GET returns a JSON representation of the object.

In general, you can map any HTTP request to the corresponding openidm.method call. For more information, refer to script functions.

The following example shows how the parameters provided in an openidm.query request correspond with the key-value pairs you would include in a similar HTTP GET request. It shows the same call using the Resource API and the REST API:

  • Resource API

  • REST API

Reading an object using the Resource API:

openidm.query("managed/realm-name_user", { "_queryFilter": "true" }, ["userName","sn"])

Reading an object using the REST API:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=true&_fields=userName,sn"

Use a remote proxy to access data objects

You can proxy REST requests to another Identity Cloud tenant or IDM instance using the /external/idm/instanceName endpoint via the IDM remote proxy. This lets you treat any other tenant/IDM instance as a resource within the one you are managing.

For more information on determining the exact value for instanceName, refer to How to determine the value for instanceName.

The remote proxy acts as a REST client to the tenant/IDM instance; therefore, typical configurations for a remote proxy to operate (DNS resolution, network connectivity, SSL, and so on) are required.

Once you set up and configure the remote proxy, you can then:

  • Use it in a sync mapping

  • Call actions on it

  • Use it within scripts

  • Use it in any other way that you might use a resource

You can call any endpoint in the remote tenant/IDM instance using this proxy.

A few situations where this feature may be useful include:

  • Syncing data in a sandbox or development tenant into the staging environment (or from staging to production).

  • Syncing changes where there are geographically diverse data centers and they need to be kept in sync with one another.

  • Syncing data between existing self-managed IDM and a tenant/IDM instance.

The proxy does not support liveSync/implicit sync from the remote Identity Cloud resources. This means you are limited to using reconciliation when it comes to pulling data from a remote system.

How to determine the value for instanceName

The instanceName is a fragment of the external configuration’s name. You can determine the value for instanceName using REST:

  1. Get the configurations:

    Request
    curl \
    --header "Authorization: Bearer <token>" \
    --header "Accept-API-Version: resource=1.0" \
    --request GET \
    "https://<tenant-env-fqdn>/openidm/config/"
  2. Locate the external configuration:

    Return
    {
      "_id": "",
      "configurations": [
        ...
        {
          "_id": "emailTemplate/welcome",
          "pid": "emailTemplate.212e...f7a",
          "factoryPid": "emailTemplate"
        },
        ...
        {
          "_id": "external.idm/name1", (1)
          "pid": "external.idm.29cd...f4a",
          "factoryPid": "external.idm"
        },
        ...
      ]
    }
    1 In this example, the external configuration "_id": "external.idm/name1" would be available as a remote system at the openidm/external/idm/name1 endpoint.

Prerequisites

To connect to a remote instance over SSL, you must import the remote instance’s server certificate into your local instance’s truststore (if the cert is signed by a CA that is not already in the truststore). For further information, refer to Configure a self-managed SSL certificate.

Authenticate to another tenant or IDM instance

The manner in which you authenticate is based on how the remote tenant/IDM instance is configured to authenticate requests:

  • Remote proxy from one tenant to another.

    • Authentication is completed via bearer authentication. Ensure you properly configure a client with the client credentials grant flow in the remote tenant before obtaining an access token.

      For the proxy to work, you must set client_secret_post as the Token Endpoint Authentication Method (tokenEndpointAuthMethod).
  • Remote proxy from a tenant to a self-managed IDM instance.

    • If you need to remote proxy from a tenant to a self-managed IDM instance (or vice versa), you authenticate by the way in which the self-managed IDM is configured.

      If you connect to a self-managed IDM instance, basic authentication or bearer token authentication when IDM is configured to use rsFilter are supported.

      • basic authentication: Use a simple username/password binding to make the request.

      • bearer authentication: Ensure you properly configure a client with the client credentials grant flow in the remote instance before obtaining an access token.

        For the proxy to work, you must set client_secret_post as the Token Endpoint Authentication Method (tokenEndpointAuthMethod).

For either method, you must ensure the user authenticating has the required authorization role(s) to perform the necessary operations. Operations depend on the actions you intend to take on the remote tenant/IDM instance.

The authentication method you use determines the available properties:

Table 2. Properties available for authentication
Property Required? Definition

enabled

No

The enable state of the service. The default is true.

scope

No

The requested OAuth2 scope(s).

scopeDelimiter

No

The scope delimiter to use. Defaults to space.

authtype

Yes

The authentication strategy to use. Either basic or bearer.

instanceUrl

Yes

The URL of the remote instance to relay the request to.

userName

With basic auth

The basic authentication user name.

password

With basic auth

The basic authentication password.

clientId

With bearer auth

The clientId used to request an access token from the token endpoint.

clientSecret

With bearer auth

The client secret used to request an access token from the token endpoint.

tokenEndpoint

With bearer auth

The OAuth2 token endpoint.

For any request sent to the source server that includes an X-Requested-With header, the value of the header is set to RemoteIDMProxy.

Examples

The following subsections show examples of how to authenticate via basic and with bearer authentication.

Basic authentication

{
  "enabled" : true,
  "authType" : "basic",
  "instanceUrl" : "https://localhost:8443/openidm/",
  "userName" : "openidm-admin",
  "password" : "openidm-admin"
}

Bearer/Oauth2 authentication

{
  "enabled" : true,
  "authType" : "bearer",
  "instanceUrl" : "https://fr-platform.iam.example.com/openidm/",
  "clientId" : "idm-provisioning",
  "clientSecret" : "password",
  "scope" : [ ],
  "tokenEndpoint" : "https://fr-platform.iam.example.com/am/oauth2/realms/root/access_token",
  "scopeDelimiter" : " "
}

REST request

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
'https://<tenant-env-fqdn>/openidm/external/idm/platform/managed/user?_queryFilter=true'
{
  "result": [
    {
      "_id": "95b2b43c-621e-4bca-8a97-efc768f17751",
      "_rev": "00000000f20217df",
      "userName": "testUser",
      "accountStatus": "active",
      "givenName": "Test",
      "sn": "User",
      "mail": "testUser@test.com"
    }
  ],
  "resultCount": 1,
  "pagedResultsCookie": null,
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": -1
}

Use the remote proxy in a sync mapping

To use the remote proxy in a synchronization mapping, add the mapping to your mapping configuration.

For example:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--data '{
  "mappings": [
    {
      "name": "onprem_user_to_fidc_alpha_user",
      "source": "external/idm/65/managed/user",
      "target": "external/idm/fidc/managed/alpha_user"
    }
  ]
}' \
--request PUT \
"https://<tenant-env-fqdn>/openidm/config/sync"

To verify the changes, get the mapping configuration.

For example:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/config/sync"

Use the remote proxy in a script

Once you have created a mapping, you can manipulate the remote Identity Cloud tenant or IDM instance via scripts.

For more information, refer to script functions.

openidm.query("external/idm/fidc/managed/alpha_user", {"_queryFilter": "userName eq 'bjensen'"});

Define and call data queries

You can define and call queries using the REST or Resource API. Queries are supported on both managed and system objects, and you can define them through:

  • Common filter expressions using the _queryFilter keyword.

  • Parameterized, or predefined queries, such as the keyword _pageSize.

Common filter expressions (_queryFilter)

The ForgeRock REST API defines common filter expressions that enable you to form arbitrary queries using a number of supported filter operations. This query capability is the standard way to query data if no predefined query exists and is supported for all managed and system objects.

Common filter expressions are useful because they do not require knowledge of how the object is stored, and they do not require additions to the repository configuration.

Common filter expressions are called with the _queryFilter keyword. The following example uses a common filter expression to retrieve managed user objects whose user name is Smith:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
'https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=userName+eq+"smith"'

The filter is URL encoded in this example. The corresponding filter using the resource API would be:

openidm.query("managed/realm-name_user", { "_queryFilter" : '/userName eq "smith"' });

Special characters in queries

JavaScript query invocations are not subject to the same URL-encoding requirements as GET requests. Since JavaScript supports the use of single quotes, it is not necessary to escape the double quotes from most examples in this guide. Make sure to protect against pulling in data that could contain special characters, such as double-quotes ("). The following example shows one method of handling special characters:

"correlationQuery" : {
  "type" : "text/javascript",
  "source" : "var qry = {'_queryFilter': org.forgerock.util.query.QueryFilter.equalTo('uid', source.userName).toString()}; qry"
}

Construct queries

The openidm.query function lets you query managed and system objects. The query syntax is openidm.query(id, params), where id specifies the object upon the query should be performed, and params provides the parameters passed to the query (the _queryFilter). For example:

var equalTo = org.forgerock.util.query.QueryFilter.equalTo;
queryParams = {
    "_queryFilter": equalTo("uid", value).toString()
};
openidm.query("managed/realm-name_user", queryParams)

Over the REST interface, the query filter is specified as _queryFilter=filter, for example:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
'https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=userName+eq+"Smith"'

In _queryFilter expressions, string values must use double-quotes. Numeric and boolean expressions should not use quotes.

When called over REST, you must URL encode the filter expression. The following examples show the filter expressions using the Resource API and the REST API but do not show the URL encoding to make them easier to read.

The filter expression is constructed from the building blocks shown in this section. In these expressions, the simplest json-pointer is a field of the JSON resource, such as userName or id. A JSON pointer can, however, point to nested elements.

You can also use the negation operator (!) in query construction. For example, a _queryFilter=!(userName+eq+"jdoe") query would return every userName except for jdoe.

Comparison expressions

You can use comparison query filters for objects and object array properties that:

Equal a specified value

This is the associated JSON comparison expression: json-pointer eq json-value.

Example 1. Example 1
"_queryFilter" : '/givenName eq "Dan"'

The following REST call returns the user name and given name of all managed users whose first name (givenName) is "Dan":

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
'https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=givenName+eq+"Dan"&_fields=userName,givenName'
{
  "result": [
    {
      "givenName": "Dan",
      "userName": "dlangdon"
    },
    {
      "givenName": "Dan",
      "userName": "dcope"
    },
    {
      "givenName": "Dan",
      "userName": "dlanoway"
    }
  ],
  ...
}
Example 2. Example 2
"_queryFilter" : "/stringArrayField eq 'foo'"

The following REST call returns role entries where a value within the stringArrayField array equals "foo":

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
'https://<tenant-env-fqdn>/openidm/managed/realm-name_role?_queryFilter=stringArrayField+eq+"foo"'
{
  "result": [
    {
      "_id": "admin2",
      "_rev": "0",
      "name": "admin2",
      "stringArrayField": [
        "foo",
        "bar"
      ]
    }
  ],
  ...
}
Contain a specified value

This is the associated JSON comparison expression: json-pointer co json-value.

Example 3. Example
"_queryFilter" : '/givenName co "Da"'

The following REST call returns the username and given name of all managed users whose first name (givenName) contains "Da":

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
'https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=givenName+co+"Da"&_fields=userName,givenName'
{
  "result": [
    {
      "givenName": "Dave",
      "userName": "djensen"
    },
    {
      "givenName": "David",
      "userName": "dakers"
    },
    {
      "givenName": "Dan",
      "userName": "dlangdon"
    },
    {
      "givenName": "Dan",
      "userName": "dcope"
    },
    {
      "givenName": "Dan",
      "userName": "dlanoway"
    },
    {
      "givenName": "Daniel",
      "userName": "dsmith"
    },
    ...
  ],
  "resultCount": 10,
  "pagedResultsCookie": null,
  "remainingPagedResults": -1
}
Start with a specified value

This is the associated JSON comparison expression: json-pointer sw json-value.

Example 4. Example
"_queryFilter" : '/sn sw "Jen"'

The following REST call returns the user names of all managed users whose last name (sn) starts with "Jen":

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
'https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=sn+sw+"Jen"&_fields=userName'
{
  "result": [
    {
      "userName": "bjensen"
    },
    {
      "userName": "djensen"
    },
    {
      "userName": "cjenkins"
    },
    {
      "userName": "mjennings"
    }
  ],
  "resultCount": 4,
  "pagedResultsCookie": null,
  "remainingPagedResults": -1
}
Are less than a specified value

This is the associated JSON comparison expression: json-pointer lt json-value.

Example 5. Example
"_queryFilter" : '/employeeNumber lt 5000'

The following REST call returns the user names of all managed users whose employeeNumber is lower than 5000:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
'https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=employeeNumber+lt+5000&_fields=userName,employeeNumber'
{
  "result": [
    {
      "employeeNumber": 4907,
      "userName": "jnorris"
    },
    {
      "employeeNumber": 4905,
      "userName": "afrancis"
    },
    {
      "employeeNumber": 3095,
      "userName": "twhite"
    },
    {
      "employeeNumber": 3921,
      "userName": "abasson"
    },
    {
      "employeeNumber": 2892,
      "userName": "dcarter"
    },
    ...
  ],
  "resultCount": 4999,
  "pagedResultsCookie": null,
  "remainingPagedResults": -1
}
Are less than or equal to a specified value

This is the associated JSON comparison expression: json-pointer le json-value.

Example 6. Example
"_queryFilter" : '/employeeNumber le 5000'

The following REST call returns the user names of all managed users whose employeeNumber is 5000 or less:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
'https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=employeeNumber+le+5000&_fields=userName,employeeNumber'
{
  "result": [
    {
      "employeeNumber": 4907,
      "userName": "jnorris"
    },
    {
      "employeeNumber": 4905,
      "userName": "afrancis"
    },
    {
      "employeeNumber": 3095,
      "userName": "twhite"
    },
    {
      "employeeNumber": 3921,
      "userName": "abasson"
    },
    {
      "employeeNumber": 2892,
      "userName": "dcarter"
    },
    ...
  ],
  "resultCount": 5000,
  "pagedResultsCookie": null,
  "remainingPagedResults": -1
}
Are greater than a specified value

This is the associated JSON comparison expression: json-pointer gt json-value

Example 7. Example
"_queryFilter" : '/employeeNumber gt 5000'

The following REST call returns the user names of all managed users whose employeeNumber is higher than 5000:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
'https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=employeeNumber+gt+5000&_fields=userName,employeeNumber'
{
  "result": [
    {
      "employeeNumber": 5003,
      "userName": "agilder"
    },
    {
      "employeeNumber": 5011,
      "userName": "bsmith"
    },
    {
      "employeeNumber": 5034,
      "userName": "bjensen"
    },
    {
      "employeeNumber": 5027,
      "userName": "cclarke"
    },
    {
      "employeeNumber": 5033,
      "userName": "scarter"
    },
    ...
  ],
  "resultCount": 1458,
  "pagedResultsCookie": null,
  "remainingPagedResults": -1
}
Are greater than or equal to a specified value

This is the associated JSON comparison expression: json-pointer ge json-value.

Example 8. Example
"_queryFilter" : '/employeeNumber ge 5000'

The following REST call returns the user names of all managed users whose employeeNumber is 5000 or greater:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
'https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=employeeNumber+ge+5000&_fields=userName,employeeNumber'
{
  "result": [
    {
      "employeeNumber": 5000,
      "userName": "agilder"
    },
    {
      "employeeNumber": 5011,
      "userName": "bsmith"
    },
    {
      "employeeNumber": 5034,
      "userName": "bjensen"
    },
    {
      "employeeNumber": 5027,
      "userName": "cclarke"
    },
    {
      "employeeNumber": 5033,
      "userName": "scarter"
    },
    ...
  ],
  "resultCount": 1457,
  "pagedResultsCookie": null,
  "remainingPagedResults": -1
}

Although specific system endpoints also support EndsWith and ContainsAllValues queries, such queries are not supported for managed objects and have not been tested with all supported ICF connectors.

Presence expressions

The following examples show how you can build filters using a presence expression, shown as pr. The presence expression is a filter that returns all records with a given attribute.

A presence expression filter evaluates to true when a json-pointer pr matches any object in which the json-pointer is present and contains a non-null value. Consider the following expression:

"_queryFilter" : '/mail pr'

The following REST call uses that expression to return the mail addresses for all managed users with a mail property:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
'https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=mail+pr&_fields=mail'
{
  "result": [
    {
      "mail": "jdoe@exampleAD.com"
    },
    {
      "mail": "bjensen@example.com"
    }
  ],
  "resultCount": 2,
  "pagedResultsCookie": null,
  "remainingPagedResults": -1
}

Depending on the connector, you can apply the presence filter on system objects. The following query returns the email address of all users in a CSV file who have the email attribute in their entries:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
'https://<tenant-env-fqdn>/openidm/system/csvfile/account?_queryFilter=email+pr&_fields=email'
{
  "result": [
    {
      "_id": "bjensen",
      "email": "bjensen@example.com"
    },
    {
      "_id": "scarter",
      "email": "scarter@example.com"
    }
  ],
  "resultCount": 2,
  "pagedResultsCookie": "MA%3D%3D",
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": -1
}

Not all connectors support the presence filter. In most cases, you can replicate the behavior of the presence filter with an "equals" (eq) query, such as _queryFilter=email+eq+"*"

Literal expressions

A literal expression is a boolean:

  • true matches any object in the resource.

  • false matches no object in the resource.

For example, you can list the _id of all managed objects as follows:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
'https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=true&_fields=_id'
{
  "result": [
    {
      "_id": "d2e29d5f-0d74-4d04-bcfe-b1daf508ad7c"
    },
    {
      "_id": "709fed03-897b-4ff0-8a59-6faaa34e3af6"
    }
  ],
  "resultCount": 2,
  "pagedResultsCookie": null,
  "remainingPagedResults": -1
}
In expression clause

IDM provides limited support for the in expression clause. You can use this clause for queries on singleton string properties or arrays. in query expressions are not supported through the IDM admin UI or for use by delegated administrators.

The in operator is shorthand for multiple OR conditions.

The following example command includes escaped characters. For readability, the non-escaped URL syntax is:

https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_pageSize=1000&_fields=userName&_queryFilter=/userName+in+'["user4a","user3a"]'
curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_pageSize=1000&_fields=userName&_queryFilter=userName%20in%20'%5B%22user4a%22%2C%22user3a%22%5D'"
{
  "result": [
    {
      "_id": "e32f9a3d-0039-4cb0-82d7-347cb808672e",
      "_rev": "000000000ae18357",
      "userName": "user3a"
    },
    {
      "_id": "120625c5-cfe7-48e7-b66a-6a0a0f9d2901",
      "_rev": "000000005ad98467",
      "userName": "user4a"
    }
  ],
  "resultCount": 2,
  "pagedResultsCookie": null,
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": -1
}
Filter expanded relationships

You can use _queryFilter to filter expanded relationships from a collection, such as authzRoles. The following example queries the manager-int authorization role of a user:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/b70293db-8743-45a7-9215-1ca8fd8a0073/authzRoles?_queryFilter=name+eq+'manager-int'&_fields=*"
{
  "result": [
    {
      "_id": "b1d78144-7029-4135-8e73-85efe0a40b6b",
      "_rev": "00000000d4b8ab97",
      "_ref": "internal/role/c0a38233-c0f2-477d-8f18-f5485b7d002f",
      "_refResourceCollection": "internal/role",
      "_refResourceId": "c0a38233-c0f2-477d-8f18-f5485b7d002f",
      "_refProperties": {
        "_grantType": "",
        "_id": "b1d78144-7029-4135-8e73-85efe0a40b6b",
        "_rev": "00000000d4b8ab97"
      },
      "name": "manager-int",
      "description": "manager-int-desc",
      "temporalConstraints": null,
      "condition": null,
      "privileges": null
    }
  ],
  "resultCount": 1,
  "pagedResultsCookie": null,
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": -1
}
Complex expressions

You can combine expressions using the boolean operators and, or, and ! (not). The following example queries managed user objects located in London with the last name Jensen:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
'https://<tenant-env-fqdn>/openidm/managed/realm-name_user/?_queryFilter=city+eq+"London"and+sn+eq"Jensen"&_fields=userName,givenName,sn'
{
  "result": [
    {
      "sn": "Jensen",
      "givenName": "Clive",
      "userName": "cjensen"
    },
    {
      "sn": "Jensen",
      "givenName": "Dave",
      "userName": "djensen"
    },
    {
      "sn": "Jensen",
      "givenName": "Margaret",
      "userName": "mjensen"
    }
  ],
  "resultCount": 3,
  "pagedResultsCookie": null,
  "remainingPagedResults": -1
}
Filter objects in arrays

Use query grouping to perform your query on properties within an array. For example, to query effectiveRoles for users who have the testManagedRole, check the _refResourceId inside the effectiveRoles array:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
'https://<tenant-env-fqdn>/openidm/managed/realm-name_user/?_queryFilter=/effectiveRoles\[/_refResourceId+eq+"testManagedRole"]&_fields=userName,givenName,sn,effectiveRoles'
{
  "result": [
    {
      "_id": "917bc052-ef39-4add-ae05-0a278e2de9c0",
      "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1565",
      "userName": "scarter",
      "sn": "Carter",
      "givenName": "Steven",
      "effectiveRoles": [
        {
          "_refResourceCollection": "managed/realm-name_role",
          "_refResourceId": "testManagedRole",
          "_ref": "managed/realm-name_role/testManagedRole"
        }
      ]
    },
    {
      "_id": "aca0042c-9f4c-4ad5-8cf7-aca0adeb3470",
      "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1545",
      "userName": "jdoe",
      "sn": "Doe",
      "givenName": "John",
      "effectiveRoles": [
        {
          "_refResourceCollection": "managed/realm-name_role",
          "_refResourceId": "testManagedRole",
          "_ref": "managed/realm-name_role/testManagedRole"
        }
      ]
    }
  ],
  "resultCount": 2,
  "pagedResultsCookie": null,
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": -1
}

Since curl uses brackets ([], {}) for processing, you need to escape your brackets with a \. This may be unnecessary when you use a different method to call IDM.

Page query results

The common filter query mechanism supports paged query results for managed objects, and for some system objects, depending on the system resource. There are two ways to page objects in a query:

  • Using a cookie based on the value of a specified sort key.

  • Using an offset that specifies how many records should be skipped before the first result is returned.

These methods are implemented with the following query parameters:

_pagedResultsCookie

Opaque cookie used by the server to keep track of the position in the search results. The format of the cookie is a base-64 encoded version of the value of the unique sort key property. The value of the returned cookie is URL-encoded to prevent values such as + from being incorrectly translated.

You cannot page results without sorting them (using the _sortKeys parameter). If you do not specify a sort key, the _id of the record is used as the default sort key. At least one of the specified sort key properties must be a unique value property, such as _id.

For paged searches on generic mappings, you should sort on the _id property, because this is the only property that is stored outside of the JSON blob. If you sort on something other than _id, the search will incur a performance hit because IDM has to pull the entire result set and then sort it.

The server provides the cookie value on the first request. You should then supply the cookie value in subsequent requests until the server returns a null cookie, meaning that the final page of results has been returned.

The _pagedResultsCookie parameter is supported only for filtered queries, that is, when used with the _queryFilter parameter. You cannot use the _pagedResultsCookie with a _queryId.

The _pagedResultsCookie and _pagedResultsOffset parameters are mutually exclusive and cannot be used together.

Paged results are enabled only if the _pageSize is a non-zero integer.

_pagedResultsOffset

Specifies the index within the result set of the number of records to be skipped before the first result is returned. The format of the _pagedResultsOffset is an integer value. When the value of _pagedResultsOffset is greater than or equal to 1, the server returns pages, starting after the specified index.

This request assumes that the _pageSize is set, and not equal to zero.

For example, if the result set includes 10 records, the _pageSize is 2, and the _pagedResultsOffset is 6, the server skips the first 6 records, then returns 2 records, 7 and 8. The _remainingPagedResults value would be 2, the last two records (9 and 10) that have not yet been returned.

If the offset points to a page beyond the last of the search results, the result set returned is empty.

_pageSize

An optional parameter indicating that query results should be returned in pages of the specified size. For all paged result requests other than the initial request, a cookie should be provided with the query request.

The default behavior is not to return paged query results. If set, this parameter should be an integer value, greater than zero.

When a _pageSize is specified, and non-zero, the server calculates the totalPagedResults in accordance with the totalPagedResultsPolicy and provides the value as part of the response. If a count policy is specified (_totalPagedResultsPolicy=EXACT), the totalPagedResults returns the total result count. If no count policy is specified in the query, or if _totalPagedResultsPolicy=NONE, result counting is disabled, and the server returns a value of -1 for totalPagedResults. The following example shows a query that requests two results with a totalPagedResultsPolicy of EXACT:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=true&_pageSize=2&_totalPagedResultsPolicy=EXACT"
{
  "result": [
    {
      "_id": "adonnelly",
      "_rev": "0",
      "userName": "adonnelly",
      "givenName": "Abigail",
      "sn": "Donnelly",
      "telephoneNumber": "12345678",
      "active": "true",
      "mail": "adonnelly@example.com",
      "accountStatus": "active",
      "effectiveRoles": [],
      "effectiveAssignments": []
    },
    {
      "_id": "bjensen",
      "_rev": "0",
      "userName": "bjensen",
      "givenName": "Babs",
      "sn": "Jensen",
      "telephoneNumber": "12345678",
      "active": "true",
      "mail": "bjensen@example.com",
      "accountStatus": "active",
      "effectiveRoles": [],
      "effectiveAssignments": []
    }
  ],
  "resultCount": 2,
  "pagedResultsCookie": "eyIvX2lkIjoiYm11cnJheSJ9",
  "totalPagedResultsPolicy": "EXACT",
  "totalPagedResults": 22,
  "remainingPagedResults": -1
}

The totalPagedResults and _remainingPagedResults parameters are not supported for all queries. Where they are not supported, their returned value is always -1. In addition, counting query results using these parameters is not currently supported for a ForgeRock Directory Services (DS) repository.

Requesting the total result count (with _totalPagedResultsPolicy=EXACT) incurs a performance cost on the query.

Queries that return large data sets will have a significant impact on heap requirements, particularly if they are run in parallel with other large data requests. To avoid out of memory errors, analyze your data requirements, set the heap configuration appropriately, and modify access controls to restrict requests on large data sets.

Sort query results

For common filter query expressions, you can sort the results of a query using the _sortKeys parameter. This parameter takes a comma-separated list as a value and orders the way the JSON result is returned based on this list.

The _sortKeys parameter is not supported for predefined queries.

  • Pagination using _pageSize is recommended if you intend to use _sortKeys. If you do not paginate your query, the data you are querying must be indexed.

  • When viewing data that is persisted in Identity Cloud’s data store and sorted by un-indexed _sortKeys, the _pageSize parameter must be less than or equal to the index-entry-limit as configured in DS (default value is 4000).

The following query returns all users with the givenName Dan and sorts the results alphabetically, according to surname (sn):

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
'https://<tenant-env-fqdn>/openidm/system/ldap/account?_queryFilter=givenName+eq+"Dan"&_fields=givenName,sn&_sortKeys=sn'
{
  "result": [
    {
      "sn": "Cope",
      "givenName": "Dan"
    },
    {
      "sn": "Langdon",
      "givenName": "Dan"
    },
    {
      "sn": "Lanoway",
      "givenName": "Dan"
    }
  ],
  "resultCount": 3,
  "pagedResultsCookie": null,
  "remainingPagedResults": -1
}

When you query a relationship field, fields that belong to the related object are not available as _sortKeys. For example, if you query a list of a manager’s reports, you cannot sort by the reports' last names. This is because the available _sortKeys are based on the object being queried, which in the case of relationships is a list of references to other objects, not the objects themselves.

Recalculate properties based on other properties (virtual) in queries

For managed objects, IDM includes an onRetrieve script hook that enables you to recalculate property values, known as virtual properties, when an object is retrieved as the result of a query. To use the onRetrieve trigger, the query must include the executeOnRetrieve parameter, for example:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
'https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=sn+eq+"Jensen"&executeOnRetrieve=true'

If a query includes executeOnRetrieve, the query recalculates virtual property values, based on the current state of the system. The result of the query will be the same as a read on a specific object, because reads always recalculate virtual property values.

If a query does not include executeOnRetrieve, the query returns the virtual properties of an object based on the value that is persisted in the repository. Virtual property values are not recalculated.

For performance reasons, executeOnRetrieve is false by default.

Virtual properties that use queryConfig for calculation instead of an onRetrieve script are not recalculated by executeOnRetrieve. These properties are recalculated only when there is a change (such as adding or removing a role affecting effectiveRoles, or a temporal constraint being triggered or changed).

Appendix A: Data models and objects reference

You can customize a variety of objects that can be addressed via a URL or URI. IDM can perform a common set of functions on these objects, such as CRUDPAQ (create, read, update, delete, patch, action, and query).

Depending on how you intend to use them, different object types are appropriate.

Table 3. Object Types
Object Type Intended Use Special Functionality

Managed objects

Serve as targets and sources for synchronization, and to build virtual identities.

For more information, refer to Managed objects.

Provide appropriate auditing, script hooks, declarative mappings and so forth in addition to the REST interface.

Configuration objects

Ideal for look-up tables or other custom configuration, which you can configure externally like any other system configuration.

Adds file view, REST interface, and so forth

Repository objects

The equivalent of arbitrary database table access. Appropriate for managing data through the underlying data store or repository API.

For information on how to access identity related data using REST, refer to REST and IDM.

Persistence and API access

System objects

Pluggable representations of objects on external systems. They follow the same RESTful resource based design principles as managed objects. There is a default implementation for the ICF framework, which allows any connector object to be represented as a system object.

For more information on system objects and connectors, refer to ForgeRock ICF.

For information on REST endpoints relating to system objects, refer to System objects.

 

Audit objects

Houses audit data in the repository.

For more information on how to access audit data in Identity Cloud, refer to Access logs with API key and secret.

 

Links

Link objects define relations between source objects and target objects, usually relations between managed objects and system objects.

The link relationship is established by provisioning activity that either results in a new account on a target system, or a reconciliation or synchronization scenario that takes a LINK action.

For more information, refer to Reuse links between mappings.

 

Managed objects

Managed objects and their properties are defined in the IDM managed object schema.

The default schema includes these types of managed objects:

Each managed object type contains properties for storing information about objects of that type. For example, the user object type has properties for storing usernames, passwords, email addresses, and so forth.

In the IDM admin UI, managed objects represent the identity-related data managed by IDM. In IDM, managed objects are stored in a DS repository.

Data consistency

Single-object operations are consistent within the scope of the operation performed, limited by the capabilities of the underlying data store. Bulk operations have no consistency guarantees. IDM does not expose any transactional semantics in the managed object access API.

For information on conditional header access through the REST API, refer to Conditional Operations.

Managed object triggers

Triggers are user-definable functions that validate or modify object or property state.

State triggers

Managed objects are resource-oriented. A set of triggers is defined to intercept the supported request methods on managed objects. Such triggers are intended to perform authorization, redact, or modify objects before the action is performed. The object being operated on is in scope for each trigger, meaning that the object is retrieved by the data store before the trigger is fired.

If retrieval of the object fails, the failure occurs before any trigger is called. Triggers are executed before any optimistic concurrency mechanisms are invoked. The reason for this is to prevent a potential attacker from getting information about an object (including its presence in the data store) before authorization is applied.

Table 4. Managed object triggers
Managed object triggers Description

onCreate

Called upon a request to create a new object. Throwing an exception causes the create to fail.

postCreate

Called after the creation of a new object is complete.

onRead

Called upon a request to retrieve a whole object or portion of an object. Throwing an exception causes the object to not be included in the result.

This method is also called when lists of objects are retrieved via requests to its container object; in this case, only the requested properties are included in the object. It allows for uniform access control for retrieval of objects, regardless of the method in which they were requested.

onUpdate

Called upon a request to store an object. The oldObject and newObject variables are in-scope for the trigger.

The oldObject represents a complete object, as retrieved from the data store. The trigger can elect to change newObject properties.

If, as a result of the trigger, the values of the oldObject and newObject are identical (that is, update is reverted), the update ends prematurely, but successfully. Throwing an exception causes the update to fail.

postUpdate

Called after an update request is complete.

onDelete

Called upon a request to delete an object. Throwing an exception causes the deletion to fail.

postDelete

Called after an object is deleted.

onSync

Object storage triggers

An object-scoped trigger applies to an entire object. Unless otherwise specified, the object itself is in scope for the trigger.

onValidate

Validates an object prior to its storage in the data store. If an exception is thrown, the validation fails and the object is not stored.

onStore

Called prior to when an object is stored in the data store. Typically used to transform an object prior to its storage (for example, encryption).

Property storage triggers

A property-scoped trigger applies to a specific property within an object. Only the property itself is in scope for the trigger. No other properties in the object should be accessed during execution of the trigger. Unless otherwise specified, the order of execution of property-scoped triggers is intentionally left undefined.

onValidate

Validates a given property value after its retrieval from and prior to its storage in the data store. If an exception is thrown, the validation fails and the property is not stored.

onRetrieve

Called on all requests that return a single object: read, create, update, patch, and delete.

onRetrieve is called on queries only if executeOnRetrieve is set to true in the query request parameters. If executeOnRetrieve is not passed, or if it is false, the query returns previously persisted values of the requested fields. This behavior avoids performance problems when executing the script on all results of a query.

onStore

Called before an object is stored in the data store. Typically used to transform a given property before its object is stored.

Storage trigger Sequences

Triggers are executed in the following order:

Object retrieval Sequence
  1. Retrieve the raw object from the data store

  2. The executeOnRetrieve boolean is used to check whether property values should be recalculated. The sequence continues if the boolean is set to true.

  3. Call object onRetrieve trigger

  4. Per-property within the object, call property onRetrieve trigger

Object storage sequence
  1. Per-property within the object:

    • Call property onValidate trigger

    • Call object onValidate trigger

  2. Per-property trigger within the object:

    • Call property onStore trigger

    • Call object onStore trigger

    • Store the object with any resulting changes to the data store

Managed object encryption

Sensitive object properties can be encrypted prior to storage, typically through the property onStore trigger. The trigger has access to configuration data, which can include arbitrary attributes that you define, such as a symmetric encryption key. Such attributes can be decrypted during retrieval from the data store through the property onRetrieve trigger.

Managed object configuration

Configuration of managed objects is provided through an array of managed object configuration objects. The object is managed-object-config.

{
  "objects": [ managed-object-config object, ... ]
}
objects

array of managed-object-config objects, required

Specifies the objects that the managed object service manages.

Managed object config properties

Specifies the configuration of each managed object.

{
  "name"      : string,
  "actions"   : script object,
  "onCreate"  : script object,
  "onDelete"  : script object,
  "onRead"    : script object,
  "onRetrieve": script object,
  "onStore"   : script object,
  "onSync"    : script object,
  "onUpdate"  : script object,
  "onValidate": script object,
  "postCreate": script object,
  "postDelete": script object,
  "postUpdate": script object,
  "schema"    : {
    "id"        : urn,
    "icon"      : string,
    "mat-icon"  : string,
    "order"     : [ list of properties],
    "properties": { property-configuration objects },
    "$schema"   : "http://json-schema.org/draft-03/schema",
    "title"     : "User",
    "viewable"  : true
  }
}
Table 5. Managed object config properties
Property Description

name

String, required.

The name of the managed object. Used to identify the managed object in URIs and identifiers.

actions

Script object, optional.

A custom script that initiates an action on the managed object. For more information, refer to Register custom scripted actions.

onCreate

Script object, optional.

A script object to trigger when the creation of an object is being requested. The object to be created is provided in the root scope as an object property. The script can change the object. If an exception is thrown, the create aborts with an exception.

onDelete

Script object, optional.

A script object to trigger when the deletion of an object is being requested. The object being deleted is provided in the root scope as an object property. If an exception is thrown, the deletion aborts with an exception.

onRead

Script object, optional.

A script object to trigger when the read of an object is being requested. The object being read is provided in the root scope as an object property. The script can change the object. If an exception is thrown, the read aborts with an exception.

onRetrieve

Script object, optional.

A script object to trigger when an object is retrieved from the repository. The object that was retrieved is provided in the root scope as an object property. The script can change the object. If an exception is thrown, then object retrieval fails.

onStore

Script object, optional.

A script object to trigger when an object is about to be stored in the repository. The object to be stored is provided in the root scope as an object property. The script can change the object. If an exception is thrown, then object storage fails.

onSync

Script object, optional.

A script object to trigger when a change to a managed object triggers an implicit synchronization operation. The script has access to the syncResults object, the request object, the state of the object before the change (oldObject) and the state of the object after the change (newObject). The script can change the object.

onUpdate

Script object, optional.

A script object to trigger when an update to an object is requested. The old value of the object being updated is provided in the root scope as an oldObject property. The new value of the object being updated is provided in the root scope as a newObject property. The script can change the newObject. If an exception is thrown, the update aborts with an exception.

onValidate

Script object, optional.

A script object to trigger when the object requires validation. The object to be validated is provided in the root scope as an object property. If an exception is thrown, the validation fails.

postCreate

Script object, optional.

A script object to trigger after an object is created, but before any targets are synchronized.

postDelete

Script object, optional.

A script object to trigger after a delete of an object is complete, but before any further synchronization. The value of the deleted object is provided in the root scope as an oldObject property.

postUpdate

Script object, optional.

A script object to trigger after an update to an object is complete, but before any targets are synchronized. The value of the object before the update is provided in the root scope as an oldObject property. The value of the object after the update is provided in the root scope as a newObject property.

schema

Json-schema object, optional.

The schema to use to validate the structure and content of the managed object, and how the object is displayed in the UI. The schema-object format is defined by the JSON Schema specification.

schema.icon

String, optional.

The name of the Font Awesome icon to display for this object in the UI. Only applies to standalone IDM.

schema.mat-icon

String, optional.

The name of the Material Icon to display for this object in the UI. Only applies to IDM as part of the ForgeRock Identity Platform.

schema.id

Urn, optional.

The URN of the managed object, for example, urn:jsonschema:org:forgerock:openidm:managed:api:Role.

schema.order

List of properties, optional.

The order in which properties of this managed object are displayed in the UI.

schema.properties

List of property configuration objects, optional.

A list of property specifications. For more information, refer to Property Configuration Properties.

schema.$schema

Url, optional.

Link to the JSON schema specification.

schema.title

String, optional.

The title of this managed object in the UI.

schema.viewable

Boolean, optional.

Whether this object is visible in the UI.

Property configuration properties

Each managed object property, identified by its property-name, can have the following configurable properties:

"property-name" : {
  "description"     : string,
  "encryption"      : property-encryption object,
  "isPersonal"      : boolean true/false,
  "isProtected"     : boolean true/false,
  "isVirtual"       : boolean true/false,
  "items"           : {
     "id"                  : urn,
     "properties"          : property-config object,
     "resourceCollection"  : property-config object,
     "reversePropertyName" : string,
     "reverseRelationship" : boolean true/false,
     "title"               : string,
     "type"                : string,
     "validate"            : boolean true/false,
  },
  "onRetrieve"      : script object,
  "onStore"         : script object,
  "onValidate"      : script object,
  "pattern"         : string,
  "policies"        : policy object,
  "required"        : boolean true/false,
  "returnByDefault" : boolean true/false,
  "scope"           : string,
  "searchable"      : boolean true/false,
  "secureHash"      : property-hash object,
  "title"           : string,
  "type"            : data type,
  "usageDescription": string,
  "userEditable"    : boolean true/false,
  "viewable"        : boolean true/false,
}
Table 6. Property config properties
Property Description

description

String, optional.

A brief description of the property.

encryption

Property-encryption object, optional.

Specifies the configuration for encryption of the property in the repository. If omitted or null, the property is not encrypted.

isPersonal

Boolean, true/false.

Designed to highlight personally identifying information. By default, isPersonal is set to true for userName and postalAddress.

isProtected

Boolean, true/false.

Specifies whether reauthentication is required if the value of this property changes.

isVirtual

Boolean, true/false.

Specifies whether the property takes a static value, or whether its value is calculated dynamically as the result of a script.

The most recently calculated value of a virtual property is persisted by default. The persistence of virtual property values allows IDM to compare the new value of the property against the last calculated value, and therefore to detect change events during synchronization.

Virtual property values are not persisted by default if you are using an explicit mapping.

items

Property-configuration object, optional.

For array type properties, defines the elements in the array.

items.id

Urn, optional.

The URN of the property, for example, urn:jsonschema:org:forgerock:openidm:managed:api:Role:members:items.

items.properties

Property configuration object, optional.

A list of properties, and their configuration, that make up this items array. For example, for a relationship type property:

"properties" : {
    "_ref" : {
        "description" : "References a relationship from a managed object",
        "type" : "string"
    },
    "_refProperties" : {
        "description" : "Supports metadata within the relationship",
        ...
    }
}

items.resourceCollection

Property configuration object, optional.

The collection of resources (objects) on which this relationship is based (for example, managed/realm-name_user objects).

items.reversePropertyName

String, optional

For relationship type properties, specifies the corresponding property name in the case of a reverse relationship. For example, a roles property might have a reversePropertyName of members.

items.reverseRelationship

Boolean, true or false.

For relationship type properties, specifies whether the relationship exists in both directions.

items.title

String, optional.

The title of array items, as displayed in the UI, for example Role Members Items.

items.type

String, optional.

The array type, for example relationship.

items.validate

Boolean, true/false.

For reverse relationships, specifies whether the relationship should be validated.

onRetrieve

Script object, optional.

A script object to trigger once a property is retrieved from the repository. That property may be one of two related variables: property and propertyName. The property that was retrieved is provided in the root scope as the propertyName variable; its value is provided as the property variable. If an exception is thrown, then object retrieval fails.

onStore

Script object, optional.

A script object to trigger when a property is about to be stored in the repository. That property may be one of two related variables: property and propertyName. The property that was retrieved is provided in the root scope as the propertyName variable; its value is provided as the property variable. If an exception is thrown, then object storage fails.

onValidate

Script object, optional.

A script object to trigger when the property requires validation. The value of the property to be validated is provided in the root scope as the property property. If an exception is thrown, validation fails.

pattern

String, optional.

Any specific pattern to which the value of the property must adhere. For example, a property whose value is a date might require a specific date format. Patterns specified here must follow regular expression syntax.

policies

Policy object, optional.

Any policy validation that must be applied to the property.

required

Boolean, true/false.

Specifies whether the property must be supplied when an object of this type is created.

returnByDefault

Boolean, true/false.

For virtual properties, specifies whether the property will be returned in the results of a query on an object of this type if it is not explicitly requested. Virtual attributes are not returned by default.

scope

String, optional.

Specifies whether the property should be filtered from HTTP/external calls. The value can be either "public" or "private". "private" indicates that the property should be filtered, "public" indicates no filtering. If no value is set, the property is assumed to be public and thus not filtered.

searchable

Boolean, true/false.

Specifies whether this property can be used in a search query on the managed object. A searchable property is visible in the End User UI. False by default.

Do not modify the searchable setting on properties in the Identity Cloud managed object schema.

secureHash

Property-hash object, optional.

Specifies the configuration for hashing of the property value in the repository. If omitted or null, the property is not hashed.

title

String, required.

A human-readable string, used to display the property in the UI.

type

Data type, required.

The data type for the property value; can be String, Array, Boolean, Number, Object, or Resource Collection.

usageDescription

String, optional.

Designed to help end users understand the sensitivity of a property such as a telephone number.

userEditable

Boolean, true/false.

Specifies whether users can edit the property value in the UI. This property applies in the context of the end-user UI, in which users are able to edit certain properties of their own accounts. False by default.

viewable

Boolean, true/false.

Specifies whether this property is viewable in the object’s profile in the UI. True by default.

Script object properties

{
  "type"  : "text/javascript",
  "source": string
}
type

String, required.

IDM supports "text/javascript".

source

String, required.

Specifies the source code of the script to be executed (if the keyword is "source").

Property encryption object

{
  "cipher": string,
  "key"   : string
}
cipher

String, optional.

The cipher transformation used to encrypt the property. If omitted or null, the default cipher of "AES/CBC/PKCS5Padding" is used.

key

String, required.

The alias of the key in the IDM cryptography service keystore used to encrypt the property.

Property hash object

{
    "algorithm" : string,
    "type" : string
}
algorithm

String, required.

The algorithm that should be used to hash the value.

type

String, optional.

The type of hashing. Currently, only salted hash is supported. If this property is omitted or null, the default "salted-hash" is used.

Access managed objects using REST

IDM exposes all managed object functionality through the REST API unless you configure a policy to prevent such access. In addition to the ForgeRock REST functionality of create, read, update, delete, patch, and query, the REST API also supports patch by query. For more information, refer to the REST API reference.

Copyright © 2010-2024 ForgeRock, all rights reserved.