Object modeling
Guide to creating and managing objects in ForgeRock® Identity Cloud.
Identity Cloud provides a default schema for typical managed object types, such as users and roles. This section shows you how to change and add to the managed object schema, how to establish relationships between objects, and how to use policies to validate objects. You will also learn how to access Identity Cloud objects using queries.
ForgeRock Identity Platform™ serves as the basis for our simple and comprehensive Identity and Access Management solution. We help our customers deepen their relationships with their customers, and improve the productivity and connectivity of their employees and partners. For more information about ForgeRock and about the platform, see https://www.forgerock.com.
The ForgeRock Common REST API works across the platform to provide common ways to access web resources and collections of resources.
Managed objects
These topics describe how to work with managed object types:
The Identity Cloud object model includes other object types besides managed objects. For more information, see Data models and objects reference.
Identity Cloud managed object schema
Managed objects and their properties are defined in the default Identity Cloud 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 Identity Cloud managed object schema to meet your needs:
-
Add new managed object types. See Create and modify object types.
-
Specify default values for object properties. See Default Values.
-
Derive object property values from other object property values. See Virtual properties.
-
Validate property values. See Use policies to validate data.
To store custom data for users, you do not extend the default Identity Cloud managed object schema. Instead, use one of the generic extension attributes provided in the default user object schema. For a list of generic extension attributes, see the tables here.
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 Identity Cloud, you must modify the IDM admin UI
code accordingly. For example, if you remove the |
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 managed object types. The easiest way to create a new managed object type is to use the IDM admin UI, as follows:
-
Select Configure > Managed Objects > New Managed Object.
-
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.
-
On the Properties tab, specify the schema for the object type (the properties that make up the object).
-
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.
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 Also, managed object properties that contain an underscore ( |
A property definition typically includes the following 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
orfalse
(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
orfalse
(false
by default).Do not modify the searchable setting on properties in the Identity Cloud managed object schema. 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
orfalse
(false
by default). isProtected
-
Specifies whether reauthentication is required if the value of this property changes.
For certain properties, such as passwords, changing the value of the property should force an end user to reauthenticate. These properties are referred to as protected properties. Depending on how the user authenticates (which authentication module is used), the list of protected properties is added to the user’s security context. For example, if a user logs in with the login and password of their managed user entry (
MANAGED_USER
authentication module), their security context will include this list of protected properties. The list of protected properties is not included in the security context if the user logs in with a module that does not support reauthentication (such as through a social identity provider). 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. For more information on managed object policies, see Default policy for managed objects.
required
-
Specifies whether the property must be supplied when an object of this type is created. Boolean,
true
orfalse
.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 bothrequired
andnotEmpty
totrue
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
, ornull
.If any user might not have a value for a specific property (such as a
telephoneNumber
), you must includenull
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, setNullable
totrue
).You can also set a null property type in your managed object configuration by setting
"type" : '[ "string","null" ]'
for that property (wherestring
can be any other valid property type. This information is validated by the policy service, as described in Validate Managed Object Data Types.If you’re configuring a data
type
ofarray
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
orfalse
. returnByDefault
-
For non-core attributes (virtual attributes and relationship fields), 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 and relationship fields are not returned by default. Boolean,
true
orfalse
. When the property is in an array within a relationship, always set tofalse
. relationshipGrantTemporalConstraintsEnforced
-
For attributes with relationship fields. Specifies whether this relationship should have temporal constraints enforced. Boolean,
true
orfalse
. For more information about temporal constraints, see Use temporal constraints to restrict effective roles. 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
Identity Cloud assumes all default values are valid for the schema. -
Default values
You can specify default values in the Identity Cloud managed object schema. If you omit a default 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 Identity Cloud 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 Identity Cloud 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"
}
Identity Cloud assumes all default values are valid for the schema. Although Identity Cloud skips policy validation for objects with default values, you can force validation on property values. |
Virtual properties
Properties can be derived from other properties within an object. This lets computed and composite values be created in the object. Such derived properties are named virtual properties. The value of a virtual property can be calculated in two ways:
-
Using a script called by the
onRetrieve
script hook. This script then calculates the current value of the virtual property based on the related properties. -
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.
Do not extend the Identity Cloud default managed object schema for the user object type by adding a new virtual property. Instead, use one of the generic extension attributes provided in the default user object schema. For a list of generic extension attributes, see the tables here. |
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, see Run scripts on managed objects.
Relationship-Derived Virtual Properties
Virtual properties can be calculated by Identity Cloud 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 Identity Cloud 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 Identity Cloud 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.For example, the
referencedRelationshipFields
foreffectiveAssignments
is["roles","assignments"]
. The first field refers to theroles
relationship field inmanaged/realm-name_user
, which references themanaged/realm-name_role
object. It then refers to theassignments
relationship inmanaged/realm-name_role
, which references themanaged/realm-name_assignment
object. Changes to either related object (managed/realm-name_role
ormanaged/realm-name_assignment
) will cause the virtual property value to be recalculated, due to thenotify
,notifySelf
, andnotifyRelationships
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 theireffectiveRoles
andeffectiveAssignments
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 isfalse
by default.With
flattenProperties
set tofalse
, andreferencedObjectFields
set toname
, the response to a query on a user’seffectiveAssignments
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 totrue
, andreferencedObjectFields
set toname
, the response to the same query looks like this:"effectiveAssignments": [ "MyFirstAssignment", "MySecondAssignment" ]
Setting
flattenProperties
totrue
also lets singleton relationship-derived virtual properties be initialized tonull
.
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 |
Run scripts on managed objects
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), updated (onUpdate), retrieved (onRetrieve), deleted (onDelete), validated (onValidate), or stored in the repository (onStore). You can also trigger a script when a change to a managed object triggers an implicit synchronization operation (onSync).
Post-action scripts let you manipulate objects after they are created (postCreate), updated (postUpdate), and deleted (postDelete).
The following sample schema runs a script to check that a role has no members before attempting to delete the role:
{
"name" : "role",
"onDelete" : {
"type" : "text/javascript",
"file" : "roles/onDelete-roles.js"
},
Track 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. Such data might include when the object was created, or the date of the most recent change, for example. This metadata is not stored within the object itself, but in a separate resource location.
Because object metadata is stored outside the managed object, state change situations (such as the time of an update) are separate from object changes (the update itself). This separation reduces unnecessary synchronization to targets when the only data that has changed is metadata. Metadata is not returned in a query unless it is specifically requested. Therefore, the volume of data that is retrieved when metadata is not required, is reduced.
To specify which metadata you want to track for an object, add a meta
stanza to the object definition in your managed object configuration. The following default configuration tracks the createDate
and lastChanged
date for managed user objects:
{
"objects" : [
{
"name" : "user",
...
"schema" : {
...
},
"meta" : {
"property" : "_meta",
"resourceCollection" : "internal/usermeta",
"trackedProperties" : [
"createDate",
"lastChanged"
]
},
...
},
...
]
}
If you are not using the self-service features that require metadata, you can remove the |
The metadata configuration includes the following properties:
property
-
The property that will be dynamically added to the managed object schema for this object.
resourceCollection
-
The resource location in which the metadata will be stored.
Adjust your repository to match the location you specify here. It’s recommended that you use an
internal
object path and define the storage in yourrepo.jdbc.json
orrepo.ds.json
file.For a JDBC repository, metadata is stored in the
metaobjects
table by default. Themetaobjectproperties
table is used for indexing.For a DS repository, metadata is stored under
ou=usermeta,ou=internal,dc=openidm,dc=forgerock,dc=com
by default.User objects stored in a DS repository must include the
ou
specified in the precedingdnTemplate
attribute. trackedProperties
-
The properties that will be tracked as metadata for this object. In the previous example, the
createDate
(when the object was created) and thelastChanged
date (when the object was last modified) are tracked.
You cannot search on metadata and it is not returned in 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-name.forgeblocks.com/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 their metadata:
curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "https://tenant-name.forgeblocks.com/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 |
The request also returns a _meta
property that includes relationship information. Identity Cloud 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.
Users
In the IDM admin UI, user identities are referred to as user managed objects, also known as managed users.
You can retrieve, add, change, and delete managed users:
-
By using the Identities > Manage option in the IDM admin UI.
-
By using one of the Manage > realm-name_user options in the IDM admin UI.
-
By using 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 a reference of all managed user endpoints and actions, see the Managed users endpoint.
When viewing users with the IDM admin UI, the User List page supports specialized filtering with the Advanced Filter option. This page can help you build user queries, such as the ones in these examples.
Some examples in this documentation use client-assigned IDs (such as |
Retrieve the IDs of all managed users in the repository
curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_user?_queryFilter=true&_fields=_id" { "result": [ { "_id": "bjensen", "_rev": "0000000079b78ace" }, { "_id": "scarter", "_rev": "0000000070e587a7" }, ... ], ... }
Query managed users for a specific user
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-name.forgeblocks.com/openidm/managed/realm-name_user?_queryFilter=userName+eq+%22scarter%22" { "result": [ { "_id": "scarter", "_rev": "0000000070e587a7", "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-name.forgeblocks.com/openidm/managed/realm-name_user?_queryFilter=userName+eq+"scarter"' { "result": [ { "_id": "scarter", "_rev": "0000000070e587a7", "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
curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_user/scarter" { "_id": "scarter", "_rev": "0000000070e587a7", "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
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-name.forgeblocks.com/openidm/managed/realm-name_user/bjackson" { "_id": "bjackson", "_rev": "0000000055c185c5", "userName": "bjackson", "sn": "Jackson", "givenName": "Barbara", "mail": "bjackson@example.com", "telephoneNumber": "082082082", "accountStatus": "active", "effectiveAssignments": [], "effectiveRoles": [] }
Add a user with a system-generated ID
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-name.forgeblocks.com/openidm/managed/realm-name_user?_action=create" { "_id": "9d92cdc8-8b22-4037-a344-df960ea66194", "_rev": "00000000a4bf9006", "userName": "pjensen", "sn": "Jensen", "givenName": "Pam", "mail": "pjensen@example.com", "telephoneNumber": "082082082", "accountStatus": "active", "effectiveAssignments": [], "effectiveRoles": [] }
Update a user
This example checks whether user bjensen
exists, then replaces her telephone number 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-name.forgeblocks.com/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": "000000008c0f8617", "_id": "bjackson" }
Delete a user
curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request DELETE \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_user/bjackson" { "_id": "bjackson", "_rev": "000000008c0f8617", "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 Identity Cloud schema defines several user properties as relationships. Adding properties to the user schema is not supported, so you cannot define additional user properties as relationships. |
Create a relationship between two objects
In the default Identity Cloud 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 as9dce06d4-2fc1-4830-a92b-bd35c2f6bcbb
. For clarity, this section uses client-assigned IDs such asbjensen
andpsmith
. -
_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 will be bjensen. You would add psmith’s user entry, and reference bjensen’s entry with the _ref
property, as follows:
curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --header "If-None-Match: *" \ --header "Content-Type: application/json" \ --request PUT \ --data '{ "sn":"Smith", "userName":"psmith", "givenName":"Patricia", "displayName":"Patti Smith", "description" : "psmith - new user", "mail" : "psmith@example.com", "phoneNumber" : "0831245986", "password" : "Passw0rd", "manager" : {"_ref" : "managed/realm-name_user/bjensen"} }' \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_user/psmith" { "_id": "psmith", "_rev": "00000000ec41097c", "sn": "Smith", "userName": "psmith", "givenName": "Patricia", "displayName": "Patti Smith", "description": "psmith - new user", "mail": "psmith@example.com", "phoneNumber": "0831245986", "accountStatus": "active", "effectiveRoles": [], "effectiveAssignments": [] }
Note that relationship information is not returned by default. To show the relationship in psmith’s entry, you must explicitly request her manager entry, as follows:
curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_user/psmith?_fields=manager" { "_id": "psmith", "_rev": "00000000ec41097c", "manager": { "_ref": "managed/realm-name_user/bjensen", "_refResourceCollection": "managed/realm-name_user", "_refResourceId": "bjensen", "_refProperties": { "_id": "ffc6f0f3-93db-4939-b9eb-1f8389a59a52", "_rev": "0000000081aa991a" } } }
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, a query on bjensen’s user entry will show a reference to psmith’s entry in her reports
property (because the reports
property is configured as the reversePropertyName
of the manager
property). The following query shows the updated relationship state for bjensen:
curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_user/bjensen?_fields=reports" { "_id": "bjensen", "_rev": "0000000057b5fe9d", "reports": [ { "_ref": "managed/realm-name_user/psmith", "_refResourceCollection": "managed/realm-name_user", "_refResourceId": "psmith", "_refProperties": { "_id": "ffc6f0f3-93db-4939-b9eb-1f8389a59a52", "_rev": "0000000081aa991a" } } ] }
Identity Cloud 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.
Configure relationship change notification
A relationship exists between two managed objects. By default, when a relationship changes (when it is created, updated, or deleted), 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 in the case where many objects are affected by a single relationship change.
For roles
, a special kind of relationship, change notification is configured by default. The purpose of this default configuration is to notify managed users when any of the relationships that link users, roles, and assignments are manipulated. For more information about relationship change notification in the specific case of managed roles, see Roles and relationship change notification.
To change the default configuration, or to set up notification for other relationship changes, use the notify*
properties in the relationship definition, as described in this section.
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, see Create a relationship between two objects.
In the previous example, a PUT on managed/realm-name_user/psmith
with "manager" : {_ref : "managed/realm-name_user/bjensen"}
, 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, as shown in the following illustration:
Note that for the reverse relationship (a PUT 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 PUT on managed/realm-name_user/psmith
with "manager" : {_ref : "managed/realm-name_user/bjensen"}
, neither psmith’s object nor bjensen’s object is notified.
Auditing is not tied to relationship change notification and is always triggered when a relationship changes. Therefore, relationship changes are audited, regardless of the |
To configure relationship change notification, set the notify
and notifySelf
properties in your managed object schema. These 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. For example, for a CREATE, UPDATE or DELETE request on thepsmith/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 thereports
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 aresourceCollection
with apath
ofmanaged/realm-name_user
, and that this object specifies"notify" : true
. If the relationship changes through a CREATE, UPDATE, or DELETE on the URLpsmith/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’s
notifyRelationships
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, look at theattributes
property in the defaultmanaged/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 theroles
connected to that assignment are notified. Because therole
managed object has"notifyRelationships" : ["members"]
defined on itsassignments
field, the notification that originated from the change to the assignment attribute is propagated to the connectedroles
, and then out to themembers
of those roles.So, the
role
is notified through itsassignments
field because anattribute
in the assignment changed. This notification is propagated out of themembers
field because the role definition has"notifyRelationships" : ["members"]
on itsassignments
field.
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 will be notified of the change. For example, if there is a CREATE on managed/realm-name_user/psmith/roles
which specifies a set of references to existing roles, user psmith
will be notified of the change.
Similarly, the role
object 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) that are identified as members
of that role must be notified of the change.
|
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
In most cases, relationships between two objects in the Identity Cloud schema are defined in both directions. For example, a relationship between a user and his manager might indicate a reverse relationship between the manager and her direct report. Reverse relationships are particularly useful for queries. You might 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.
A reverse relationship is part of the 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
between users and managers. So, you can refer to a managed user’s reports by referencing the reports
. However, the reports property is also a reverse relationship ("reverseRelationship" : true
) which means that 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, themembers
relationship onmanaged/realm-name_role
specifies that there is a conditional association with themanaged/realm-name_user
resource:"resourceCollection" : [ { "notify" : true, "conditionalAssociation" : true, "path" : "managed/realm-name_user", "label" : "User", "query" : { "queryFilter" : "true", "fields" : [ "userName", "givenName", "sn" ] } } ]
conditionalAssociationField
-
This property is a string, specifying 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, theroles
relationship onmanaged/realm-name_user
specifies that the conditional association withmanaged/realm-name_role
is defined by thecondition
field inmanaged/realm-name_role
:"resourceCollection" : [ { "path" : "managed/realm-name_role", "label" : "Role", "conditionalAssociationField" : "condition", "query" : { "queryFilter" : "true", "fields" : [ "name" ] } } ]
The field name specified will usually be
condition
if you are using default schema, but can be any field that evaluates a condition and has been flagged asisConditional
. isConditional
-
Boolean. This is applied to the field you wish to check to determine whether membership in a relationship is granted. Only one field on a resource can be marked as
isConditional
. For example, in the relationship betweenmanaged/realm-name_user
andmanaged/realm-name_role
, conditional membership in the relationship is determined by the query filter specified in themanaged/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:
curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_user/psmith?_fields=manager" { "_id": "psmith", "_rev": "0000000014c0b68d", "manager": { "_ref": "managed/realm-name_user/bjensen", "_refResourceCollection": "managed/realm-name_user", "_refResourceId": "bjensen", "_refProperties": { "_id": "42418f09-ad6c-4b77-bf80-2a12d0c44678", "_rev": "00000000288b921e" } } }
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-name.forgeblocks.com/openidm/managed/realm-name_user/psmith?_fields=manager/mail,manager/telephoneNumber" { "_id": "psmith", "_rev": "0000000014c0b68d", "manager": { "_rev": "000000005bac8c10", "_id": "bjensen", "telephoneNumber": "12345678", "mail": "bjensen@example.com", "_ref": "managed/realm-name_user/bjensen", "_refResourceCollection": "managed/realm-name_user", "_refResourceId": "bjensen", "_refProperties": { "_id": "42418f09-ad6c-4b77-bf80-2a12d0c44678", "_rev": "00000000288b921e" } } }
To query all the relationships associated with a managed object, query the reference (*_ref
) property of that object. For example, the following query shows all the objects that are referenced by psmith’s entry:
curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_user/psmith?_fields=*_ref" { "_id": "psmith", "_rev": "0000000014c0b68d", "reports": [], "manager": { "_ref": "managed/realm-name_user/bjensen", "_refResourceCollection": "managed/realm-name_user", "_refResourceId": "bjensen", "_refProperties": { "_id": "42418f09-ad6c-4b77-bf80-2a12d0c44678", "_rev": "00000000288b921e" } }, "roles": [], "_meta": { "_ref": "internal/usermeta/601a3086-8c64-4966-b33c-7a213b13d859", "_refResourceCollection": "internal/usermeta", "_refResourceId": "601a3086-8c64-4966-b33c-7a213b13d859", "_refProperties": { "_id": "9de71bd7-1e1b-462e-b565-ac0a7d2f9269", "_rev": "0000000037f79a00" } }, "authzRoles": [], "_notifications": [ { "_ref": "internal/notification/3000bb64-4619-490a-8c4b-50ae7ca6b20c", "_refResourceCollection": "internal/notification", "_refResourceId": "3000bb64-4619-490a-8c4b-50ae7ca6b20c", "_refProperties": { "_id": "f54b6f84-7d3f-4486-a7c1-676fca03eeab", "_rev": "00000000748da107" } } ] }
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-name.forgeblocks.com/openidm/managed/realm-name_user/psmith?_fields=*_ref/*"
Which outputs the following:
{
"_id": "psmith",
"_rev": "0000000014c0b68d",
"reports": [],
"manager": {
"_rev": "000000005bac8c10",
"_id": "bjensen",
"userName": "bjensen",
"givenName": "Babs",
"sn": "Jensen",
"telephoneNumber": "12345678",
"active": "true",
"mail": "bjensen@example.com",
"accountStatus": "active",
"effectiveAssignments": [],
"effectiveRoles": [],
"_ref": "managed/realm-name_user/bjensen",
"_refResourceCollection": "managed/realm-name_user",
"_refResourceId": "bjensen",
"_refProperties": {
"_id": "42418f09-ad6c-4b77-bf80-2a12d0c44678",
"_rev": "00000000288b921e"
}
},
"roles": [],
"_meta": {
"_rev": "0000000079e86d8d",
"_id": "601a3086-8c64-4966-b33c-7a213b13d859",
"createDate": "2020-07-29T08:52:20.061794Z",
"lastChanged": {
"date": "2020-07-29T11:52:16.424167Z"
},
"loginCount": 0,
"_ref": "internal/usermeta/601a3086-8c64-4966-b33c-7a213b13d859",
"_refResourceCollection": "internal/usermeta",
"_refResourceId": "601a3086-8c64-4966-b33c-7a213b13d859",
"_refProperties": {
"_id": "9de71bd7-1e1b-462e-b565-ac0a7d2f9269",
"_rev": "0000000037f79a00"
}
},
"authzRoles": [],
"_notifications": [
{
"_rev": "00000000d93a6598",
"_id": "3000bb64-4619-490a-8c4b-50ae7ca6b20c",
"notificationType": "info",
"message": "Your profile has been updated.",
"createDate": "2020-07-29T11:52:16.517200Z",
"_ref": "internal/notification/3000bb64-4619-490a-8c4b-50ae7ca6b20c",
"_refResourceCollection": "internal/notification",
"_refResourceId": "3000bb64-4619-490a-8c4b-50ae7ca6b20c",
"_refProperties": {
"_id": "f54b6f84-7d3f-4486-a7c1-676fca03eeab",
"_rev": "00000000748da107"
}
}
]
}
Metadata is implemented using the relationships mechanism so when you request all relationships for a user (with |
Roles
The managed role object is a default managed object type that uses the relationships mechanism. You should understand how relationships work before you read about Identity Cloud roles.
In the ForgeRock Identity Cloud®, the default |
Identity Cloud role types
Identity Cloud 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’sroles
property. -
Authorization roles : used to specify the authorization rights of a managed object internally, within Identity Cloud.
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’sauthzRoles
property.
Provisioning roles and authorization roles use relationships to link the role to the managed object to which it applies. Authorization roles can also be granted statically, during authentication, with the defaultUserRoles
property.
Managed roles
For information about internal authorization roles, and how Identity Cloud controls authorization to its own endpoints, see 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 sales-role
dynamically, if that user is in the sales
organization.
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
is the container that holds the 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.
Some of the examples in this documentation set use client-assigned IDs (such as |
Manipulate roles
These sections show the REST calls 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, see Use assignments to provision users.
Create a role
Using the IDM admin UI
-
From the navigation bar, click Manage > Role.
-
On the Roles page, click New Role.
-
On the New Role page, enter a name and description, and click Save.
-
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.
For more information, see Use temporal constraints to restrict effective roles and Grant Roles Dynamically.
-
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-name.forgeblocks.com/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" }
By default, the role |
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, see Use assignments to provision users.
List roles
To list all 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-name.forgeblocks.com/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" } ], ... }
To display all configured managed roles in the IDM admin UI, select Manage > Role.
If you have a large number of roles, select Advanced Filter to build a more complex query filter to display only the roles you want.
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, see 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.
Grant roles statically
Grant a role to a user statically using the REST interface or the IDM admin UI as follows:
Using REST
Use one of the following methods to grant a role to a user over REST:
-
Add the user as a role member. The following example adds user scarter 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/scarter", "_refProperties":{} }' \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_role/5790220a-719b-49ad-96a6-6571e63cbaf1/members?_action=create" { "_id": "4c32ae53-abed-45f8-bc84-c367e2b0e194", "_rev": "00000000c67a99ce", "_ref": "managed/realm-name_user/scarter", "_refResourceCollection": "managed/realm-name_user", "_refResourceId": "scarter", "_refProperties": { "_id": "4c32ae53-abed-45f8-bc84-c367e2b0e194", "_rev": "00000000c67a99ce" } }
This preferred method does not incur an unnecessary performance cost when working with a role that contains many members. -
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-name.forgeblocks.com/openidm/managed/realm-name_user/scarter" { "_id": "scarter", "_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, see 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, see Set semantic arrays in Patch Operation: Add. -
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/scarter"} } ]' \ "https://tenant-name.forgeblocks.com/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 theemployee
role (currently only scarter):curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "https://tenant-name.forgeblocks.com/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/scarter", "_refResourceCollection": "managed/realm-name_user", "_refResourceId": "scarter", "_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 theemployee
role (ID5790220a-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-name.forgeblocks.com/openidm/managed/realm-name_user/scarter" { "_id": "scarter", "_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": [] }
Using the IDM admin UI
Use one of the following UI methods to grant a role to a user:
Update the user entry:
-
Select Manage > User, and select the user to whom you want to grant the role.
-
Select the Provisioning Roles tab, and select Add Provisioning Roles.
-
Select the role from the drop-down list, and select Add.
Update the role entry:
-
Select Manage > Role, and select the role that you want to grant.
-
Select the Role Members tab, and select Add Role Members.
-
Select the user from the drop-down list, and select Add.
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 Role Based on a Condition
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 create a conditional 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 create a conditional 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 only to those 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-employee", "description": "Role granted to employees resident in France", "condition": "/country eq \"FR\"" }' \ "https://tenant-name.forgeblocks.com/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 conditional role is created or updated, Identity Cloud automatically assesses all managed users, and recalculates the value of their roles
property, if they 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 conditional role 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:
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
To query user roles over REST, query the user’s roles
property. 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-name.forgeblocks.com/openidm/managed/realm-name_user/scarter/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-name.forgeblocks.com/openidm/managed/realm-name_user/scarter?_fields=effectiveRoles"
Alternatively, to check which roles have been granted to a user, either statically or dynamically, look at the user’s entry in the IDM admin UI:
-
Select Manage > User, then select the user whose roles you want to see.
-
Select the Provisioning Roles tab.
-
If you have a large number of managed roles, use the Advanced Filter option on the Role List page to build a custom query.
Delete 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. |
Over 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 isb8783543-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-name.forgeblocks.com/openidm/managed/realm-name_user/scarter/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-name.forgeblocks.com/openidm/managed/realm-name_user/scarter" { "_id": "scarter", "_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-name.forgeblocks.com/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-name.forgeblocks.com/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" } }
Using the IDM admin UI
Use one of the following methods to remove a user’s roles:
Method 1:
-
Select Manage > User, and select the user whose roles you want to remove.
-
Select the Provisioning Roles tab, select the role that you want to remove, then select Remove Selected Provisioning Roles.
Method 2:
-
Select Manage > Role, and select the role whose members you want to remove.
-
Select the Role Members tab, select the members that you want to remove, then select Remove Selected Role Members.
Delete a Role Definition
To delete a role over the REST interface, simply delete that managed object. The following command 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-name.forgeblocks.com/openidm/managed/realm-name_role/b8783543-869a-4bd4-907e-9c1d89f826ae" { "_id": "b8783543-869a-4bd4-907e-9c1d89f826ae", "_rev": "0000000027a959cf", "privileges": [], "name": "employee", "description": "All employees" }
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), Identity Cloud returns an error. The following example attempts to remove a role that is still granted to a user: curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request DELETE \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_role/01ee6191-75d8-4d4b-9291-13a46592c57a" { "code": 409, "reason": "Conflict", "message": "Cannot delete a role that is currently granted" } |
To delete a role through the IDM admin UI, select Manage > Role, select the role you want to remove, then click Delete Selected.
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 might 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 might 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, see the ISO 8601 standard.
The following example adds a contractor
role over the REST interface. The role is effective from March 1st, 2020 to August 31st, 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-name.forgeblocks.com/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 that is seven hours behind UTC.
When the period defined by the constraint has ended, 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 that user scarter has been granted a role contractor-march
. A temporal constraint has been 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-name.forgeblocks.com/openidm/managed/realm-name_user/scarter?_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 during which a role is valid by using the IDM admin UI, select Temporal Constraint on the role Details tab, then select a timezone 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 that are defined at the grant level can be different 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 that she be a member of the role for one year only, from January 1st, 2020 to January 1st, 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-name.forgeblocks.com/openidm/managed/realm-name_role/ed761370-b24f-4e21-8e58-a3230942da67" { "_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 that the temporal constraint has been applied to this grant:
curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_user/bjensen/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 during which 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 be 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 Identity Cloud itself. Provisioning roles define rules for how attribute values are updated on external systems. These rules are configured through assignments that are attached to a provisioning role definition. The purpose of an assignment is to provision an attribute or set of attributes, based on an object’s role membership.
The synchronization mapping configuration between two resources provides the basic account provisioning logic (how an account is mapped from a source to a target system). Role assignments provide additional provisioning logic that is not covered in the basic mapping configuration. 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 manipulate assignments over the REST interface, and by using the IDM admin UI. When you have created an assignment, and attached 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 The following mapping excerpt indicates that the target query must return the
For more information about preloading the result set for reconciliation operations, see Improve Reconciliation Query Performance. |
Create an Assignment
You can create assignments over the REST interface or using the IDM 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
managedUser_systemLdapAccounts
, so attributes will be updated on the external LDAP system specified in this mapping. -
The name of the attribute on the external system whose value will be set is
employeeType
, and its value will be set toEmployee
. -
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 valueEmployee
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": "managedUser_systemLdapAccounts", "attributes": [ { "name": "employeeType", "value": [ "Employee" ], "assignmentOperation": "mergeWithTarget", "unassignmentOperation": "removeFromTarget" } ] }' \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_assignment?_action=create" { "_id": "1a6a3af3-024f-4cf1-b4f6-116b98053816", "_rev": "00000000b2329649", "name": "employee", "description": "Assignment for employees.", "mapping": "managedUser_systemLdapAccounts", "attributes": [ { "name": "employeeType", "value": [ "Employee" ], "assignmentOperation": "mergeWithTarget", "unassignmentOperation": "removeFromTarget" } ] }
Note that at this stage, the assignment is not linked to any role, so no user can make use of the assignment. You must add the assignment to a role, as described in Add an Assignment to a Role.
-
- Using the IDM admin UI
-
-
Select Manage > Assignment > New Assignment.
-
Enter a name and description for the new assignment.
-
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.
-
Select Save to add the assignment.
-
Select the Attributes tab and select the attribute or attributes whose values will be adjusted by this assignment. The attribute you select here will determine what is displayed next:
-
Regular text field—specify what the value of the attribute should be, when this assignment is applied.
-
Item button—specify a managed object type, such as an object, relationship, or string.
-
Properties button—specify additional information, such as an array of role references.
-
-
Select the assignment operation from the dropdown list:
-
Merge With Target
: the attribute value will be 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 will overwrite any existing values for that attribute. The value from the assignment becomes the authoritative source for the attribute.
-
-
Select the unassignment operation from the drop-down list:
-
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
: removing the assignment from the user’seffectiveAssignments
has no effect on the current state of the attribute in the system object.
-
-
Select the Events tab to specify any scriptable events associated with this assignment.
The assignment and unassignment operations described in the previous step operate at the attribute level. That is, you specify what should happen with each attribute affected by the assignment when the assignment is applied to a user, or removed from a user.
The scriptable On assignment and On unassignment events operate at the assignment level, rather than the attribute level. Define scripts here to apply additional logic or operations that should be performed when a user (or other object) receives or loses an entire assignment. This logic can be anything that is not restricted to an operation on a single attribute.
For information about the variables available to these scripts, see Variables available to role assignment scripts.
-
Select the Roles tab to attach this assignment to an existing role definition.
-
Add an Assignment to a Role
After you have created a role, and an assignment, you 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 IDM 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 theemployee
assignment (ID1a6a3af3-024f-4cf1-b4f6-116b98053816
) to an existingemployee
role (ID2243f5f8-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-name.forgeblocks.com/openidm/managed/realm-name_role/2243f5f8-ed75-4c3b-b4b3-058d5c58fbb4" { "_id": "2243f5f8-ed75-4c3b-b4b3-058d5c58fbb4", "_rev": "00000000e85263c7", "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-name.forgeblocks.com/openidm/managed/realm-name_role/2243f5f8-ed75-4c3b-b4b3-058d5c58fbb4/assignments?_queryFilter=true&_fields=_ref/*,name,assignments" { "result": [ { "_id": "d15822f0-05bc-464a-927d-8e5018a234d3", "_rev": "0000000010eea343", "_refResourceCollection": "managed/realm-name_assignment", "_refResourceId": "1a6a3af3-024f-4cf1-b4f6-116b98053816", "_refResourceRev": "00000000b2329649", "name": "employee", "_ref": "managed/realm-name_assignment/1a6a3af3-024f-4cf1-b4f6-116b98053816", "_refProperties": { "_id": "d15822f0-05bc-464a-927d-8e5018a234d3", "_rev": "0000000010eea343" } } ], ... }
Note that the
assignments
property references the assignment that you created 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 IDM admin UI
-
-
Select Manage > Role, and select the role to which you want to add an assignment.
-
Select the Managed Assignments tab, and select Add Managed Assignments.
-
Select the assignment that you want to add to the role, then select Add.
-
Delete an Assignment
Delete assignments over the REST interface, or using the IDM admin UI:
- 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-name.forgeblocks.com/openidm/managed/realm-name_assignment/1a6a3af3-024f-4cf1-b4f6-116b98053816" { "_id": "1a6a3af3-024f-4cf1-b4f6-116b98053816", "_rev": "00000000b2329649", "name": "employee", "description": "Assignment for employees.", "mapping": "managedUser_systemLdapAccounts", "attributes": [ { "name": "employeeType", "value": [ "Employee" ], "assignmentOperation": "mergeWithTarget", "unassignmentOperation": "removeFromTarget" } ] }
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, see Effective roles and effective assignments. - Using the IDM admin UI
-
To delete an assignment using the IDM admin UI, select Manage > Assignment.
Select the assignment you want to remove, then select Delete.
Effective roles and effective assignments
Effective roles and effective assignments are virtual properties of a user object. Their values are calculated by Identity Cloud, using relationships between related objects to know when to recalculate when changes occur. 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
. Which related objects to traverse for calculation is configured using queryConfig
. Calculation or recalculation is triggered when the roles or assignments for a managed user are added, removed, or changed, including by changes from temporal constraints, and notification of that change is sent to the related objects.
The following excerpt of the Identity Cloud 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 role references an assignment, and a user references the role, that user automatically references the assignment in its list of effective assignments.
effectiveRoles
uses the roles
relationship to calculate the grants that are 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, Identity Cloud calculates the effectiveRoles
and effectiveAssignments
for that user based on the current value of the user’s roles
property, and the assignments
property of any roles referenced by the roles
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-name.forgeblocks.com/openidm/managed/realm-name_user/bjensen?_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
.
Managed role script hooks
Like any other managed object, you can use script hooks to configure role behavior. The default role configuration includes an onDelete
hook that calls a script to prevent the role from being deleted if it is currently assigned to users:
{
"name" : "role",
"onDelete" : {
"type" : "text/javascript",
"file" : "roles/onDelete-roles.js"
},
...
Map roles to external groups
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:
-
Roles set specifically in the user’s
userRoles
property -
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 isldapGroups
by default. In an Active Directory server, the property ismemberOf
by default. For example:"groupMembership" : "ldapGroups"
Note that 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. -
groupRoleMapping
: a mapping between an Identity Cloud 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 Identity Cloud roles depending on their membership in groups on the external system. In the following example, users who are members of the groupcn=admins,ou=Groups,dc=example,dc=com
are given the internalopenidm-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 Identity Cloud role (in thegroupRoleMapping
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 thegroupComparisonMethod
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
The managed group object is a default managed object type, and is defined like any other managed object type. Users are made members of groups through the relationships mechanism. You should understand how relationships work before you read about Identity Cloud 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/group/supervisors",
"_refResourceCollection": "managed/group",
"_refResourceId": "supervisors",
"_refProperties": {
"_id": "61315165-9269-4944-8db9-98f681c6b0a9",
"_rev": "00000000586a94fd"
}
},
{
"_ref": "managed/group/employees",
"_refResourceCollection": "managed/group",
"_refResourceId": "employees",
"_refProperties": {
"_id": "2a965519-5788-428c-92d1-19fac497db8f",
"_rev": "000000001e1793bc"
}
}
]
The _refResourceCollection
is the container that holds the group. The _refResourceId
is the ID of the group. 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.
Some of the examples in this documentation set use client-assigned IDs (such as |
Manage groups
These sections show the REST calls to create, read, update, and delete groups, and to assign groups to users.
Create a group
Using the IDM admin UI
-
From the navigation bar, click Manage > Group.
-
On the Groups page, click New Group.
-
On the New Group page, enter a name and description, and click Save.
Using REST
To create a group, send a PUT or POST request to the /openidm/managed/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 '{ "_id": "employees", "name": "employees", "description": "Group that includes temporary and permanent employees" }' \ "https://tenant-name.forgeblocks.com/openidm/managed/group?_action=create" { "_id": "employees", "_rev": "0000000067dba53b", "name": "employees", "description": "Group that includes temporary and permanent employees" }
The following example creates a group with a system-generated ID:
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-name.forgeblocks.com/openidm/managed/group" { "_id": "444940e2-e0e8-4f02-98d5-30b3e74dbb98", "_rev": "0000000067dba53b", "name": "employees", "description": "Group that includes temporary and permanent employees" }
List groups
To list groups over REST, query the openidm/managed/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-name.forgeblocks.com/openidm/managed/group?_queryFilter=true" { "result": [ { "_id": "employees", "_rev": "0000000067dba53b", "name": "employees", "description": "Group that includes temporary and permanent employees" } ], ... }
To list the managed groups in the IDM admin UI, select Manage > Group.
If you have a large number of groups, select Advanced Filter to build a more complex query filter to display only the groups you want.
Add users to a group
You add users to a group through the relationship mechanism. Relationships are essentially references from one managed object to another; in this case, from a user object to a group object. For more information about relationships, see Relationships between objects.
You can add group members statically or dynamically.
To add members statically, you must do one of the following:
-
Update the value of the user’s
groups
property to reference the group. -
Update the value of the groups’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 IDM admin UI as follows:
Using REST
Use one of these 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/scarter", "_refProperties":{} }' \ "https://tenant-name.forgeblocks.com/openidm/managed/group/employees/members?_action=create" { "_id": "105cdbdb-a3c2-489b-9082-6e1aaff16d31", "_rev": "000000008a2c93f9", "_ref": "managed/realm-name_user/scarter", "_refResourceCollection": "managed/realm-name_user", "_refResourceId": "scarter", "_refProperties": { "_id": "105cdbdb-a3c2-489b-9082-6e1aaff16d31", "_rev": "000000008a2c93f9" } }
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/group/employees"} } ]' \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_user/scarter" { "_id": "scarter", "_rev": "00000000788ed06a", "mail": "scarter@example.com", "givenName": "Steven", "sn": "Carter", "description": "Example User", "userName": "scarter", "telephoneNumber": "1234567", "accountStatus": "active", "memberOfOrgIDs": [], "effectiveRoles": [], "effectiveAssignments": [] }
When you update a user’s existing groups array, use the
-
special index to add the new value to the set. For more information, see Set semantic arrays in Patch Operation: Add. -
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/scarter"} } ]' \ "https://tenant-name.forgeblocks.com/openidm/managed/group/employees" { "_id": "employees", "_rev": "0000000067dba53b", "name": "employees", "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 relationship properties (*_ref
) in your query. The following example lists the members of theemployees
group:curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "https://tenant-name.forgeblocks.com/openidm/managed/group/employees?_fields=*_ref,name" { "_id": "employees", "_rev": "0000000067dba53b", "name": "employees", "members": [ { "_ref": "managed/realm-name_user/scarter", "_refResourceCollection": "managed/realm-name_user", "_refResourceId": "scarter", "_refProperties": { "_id": "9a3c7b7f-29a8-4b56-99c3-698fd0cd6b65", "_rev": "00000000ae8194c1" } }, { "_ref": "managed/realm-name_user/bjensen", "_refResourceCollection": "managed/realm-name_user", "_refResourceId": "bjensen", "_refProperties": { "_id": "2a965519-5788-428c-92d1-19fac497db8f", "_rev": "000000001e1793bc" } } ] }
Using the UI
Use one of the following UI methods to add members to a group:
-
Update the user entry:
-
Select Manage > User and select the user that you want to add.
-
Select the Groups tab and click Add Groups.
-
Select the group from the dropdown list and click Add.
-
-
Update the group entry:
-
Select Manage > Group and select the group to which you want to add members.
-
Select the Members tab and click Add Members.
-
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 particular member, that member is added to the group.
A group whose membership is based on a defined condition is called a conditional group. To create a conditional group, include a query filter in the group definition.
Properties that are used as the basis of a conditional group query must be configured as |
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-name.forgeblocks.com/openidm/managed/group?_action=create" { "_id": "fr-employees", "_rev": "00000000092faa7f", "condition": "/country eq \"FR\"", "name": "fr-employees", "description": "Group for employees resident in France" }
When a conditional group is created or updated, Identity Cloud assesses all managed users, and recalculates the value of their groups
property, if they are members of that group. When a condition is removed from a group, that is, when the group becomes an unconditional group, all members are removed from the group. So, users who became members based on the condition, have that group removed from their groups
property.
When a conditional group is defined in an existing data set, every user entry (including the mapped entries on remote systems) must be updated 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 very large number of users, creating a new conditional group can therefore incur a significant performance cost when you create it. Ideally, you should set up your conditional groups at the beginning of your deployment to avoid performance issues later. |
Query a user’s group memberships
To list a user’s groups, query their groups
property. 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-name.forgeblocks.com/openidm/managed/realm-name_user/scarter/groups?_queryFilter=true&_fields=_ref/*,name" { "result": [ { "_id": "9a3c7b7f-29a8-4b56-99c3-698fd0cd6b65", "_rev": "00000000ae8194c1", "_refResourceCollection": "managed/group", "_refResourceId": "employees", "_refResourceRev": "0000000067dba53b", "name": "employees", "_ref": "managed/group/employees", "_refProperties": { "_id": "9a3c7b7f-29a8-4b56-99c3-698fd0cd6b65", "_rev": "00000000ae8194c1" } }, { "_id": "431f7a46-a5ca-4ad6-9d0e-666d5fad1be6", "_rev": "000000002df096de", "_refResourceCollection": "managed/group", "_refResourceId": "supervisors", "_refResourceRev": "00000000f220b6bf", "name": "supervisors", "_ref": "managed/group/supervisors", "_refProperties": { "_id": "431f7a46-a5ca-4ad6-9d0e-666d5fad1be6", "_rev": "000000002df096de" } }, ... ] }
To view a user’s group membership in the IDM admin UI:
-
Select Manage > User, then select the user whose groups you want to see.
-
Select the Groups tab.
-
If you have a large number of groups, use the Advanced Filter option on the Group List page to build a custom query.
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 groups’s
members
property to remove the reference to that user.
You can use both of these methods over REST, or use the IDM 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 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. Note that 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-name.forgeblocks.com/openidm/managed/realm-name_user/scarter/groups/9a3c7b7f-29a8-4b56-99c3-698fd0cd6b65" { "_id": "9a3c7b7f-29a8-4b56-99c3-698fd0cd6b65", "_rev": "00000000ae8194c1", "_ref": "managed/group/employees", "_refResourceCollection": "managed/group", "_refResourceId": "employees", "_refProperties": { "_id": "9a3c7b7f-29a8-4b56-99c3-698fd0cd6b65", "_rev": "00000000ae8194c1" } }
-
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/group/employees", "_refResourceCollection": "managed/group", "_refResourceId": "employees", "_refProperties": { "_id": "9a3c7b7f-29a8-4b56-99c3-698fd0cd6b65", "_rev": "00000000ae8194c1" } } } ]' \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_user/scarter" { "_id": "scarter", "_rev": "000000007631d204", "mail": "scarter@example.com", "givenName": "Steven", "sn": "Carter", "description": "Created By CSV", "userName": "scarter", "telephoneNumber": "1234567", "accountStatus": "active", "memberOfOrgIDs": [], "effectiveRoles": [], "effectiveAssignments": [] }
-
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 bjensen’s membership from that group:curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "https://tenant-name.forgeblocks.com/openidm/managed/group/employees/members?_queryFilter=true&_fields=_ref/*,name" { "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-name.forgeblocks.com/openidm/managed/group/employees/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" } }
Using the UI
Use one of the following methods to remove a group member:
-
Select Manage > User and select the user whose group or groups you want to remove.
Select the Groups tab, select the group that you want to remove, then select Remove Selected Groups.
-
Select Manage > Group, and select the group whose members you want to remove.
Select the Members tab, select the member or members that that you want to remove, then select Remove Selected Members.
Delete a group
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-name.forgeblocks.com/openidm/managed/group/employees" { "_id": "employees", "_rev": "0000000067dba53b", "name": "employees", "description": "Group that includes temporary and permanent employees" }
To delete a group using the IDM admin UI, select Manage > Group, select the group you want to remove, then Delete Selected.
Organizations
Organization objects let you arrange and manage users in hierarchical trees. Organizations also let you 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.
An organization object (defined in the Identity Cloud managed object schema) has an array of admins
, an array of owners
, and an array of members
. These relationship properties 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 Identity Cloud 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.
The following diagram gives a high-level overview of how privileges are assigned to various entities in the organization hierarchy:

-
An organization owner can manipulate all organizations, members, and admins in their ownership area. The ownership area includes any part of the tree in or beneath the organization that they own. So, in the preceding image, the owner of Org A can do the following anywhere within their ownership area (the pale green region):
-
Add and update members.
Organization owners only have access to the members in their ownership area. So, an owner can create a new user as a member of their organization, but cannot add an existing managed user to their organization if that user is outside of their ownership area (that is, in any part of the tree not in or beneath the organization that they own). -
Add and update sub-organizations, such as Org B and Org C.
-
Give an organization member the
admin
privilege for the parent organization or any sub-organizations.An organization owner cannot create additional owners in their root organization.
An organization owner does not have to be a member of the organization. If the organization owner is a member of the organization, that owner is automatically in the administrative area of any admins of that organization, and can therefore be manipulated by an organization admin. To avoid accidentally giving organization admins privileges over an organization owner, do not make the owner a member of the organization.
-
-
An organization admin has control over their administrative area. The administrative area includes any part of the tree in or beneath the organization that they administer. In the preceding diagram, the administrative area of Admin A is shaded red. The administrative areas of Admins B and C are shaded grey. An admin can do the following in their administrative area:
-
Add and update members.
Organization admins only have access to the members in their administrative area. So, an admin can create a new user as a member of their organization, but cannot add an existing managed user to their organization if that user is outside of their administrative area (that is, in any part of the tree not in or beneath the organization that they administer). -
Add and update sub-organizations of the organization they administer.
Notice that Admin B and C are outside of the administrative area of Admin A. An organization admin cannot create additional admins in their administrative areas.
An organization admin must be a member of the organization, so must either be an existing member of the organization, or must be given the
memberOfOrg
relationship at the time they are created.
-
-
Organization members are regular users, with no special privileges in the organization hierarchy.
Managed users have a
memberOfOrgIDs
virtual property that lists the organizations to which the user belongs (either directly, or through any parent organizations). -
Parent and child organizations are essentially relationships between an organization and existing organizations in the tree.
Manage organizations over REST
Identity Cloud 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 following examples show how to add, change, and delete organizations over the REST interface. For a reference of all managed organization endpoints and actions, see Managed organizations.
Add an organization
Only Identity Cloud administrators can create top level organizations.
curl \ --header "Content-Type: application/json" \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --header "If-None-Match: *" \ --request PUT \ --data '{ "name": "example-org" }' \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_organization/example-org" { "_id": "example-org", "_rev": "00000000bc9871c8", "adminIDs": [], "ownerIDs": [], "parentAdminIDs": [], "parentIDs": [], "parentOwnerIDs": [], "name": "example-org" }
Add an organization owner
Identity Cloud administrators can create owners for an organization. This example makes bjensen the owner of the organization created previously. The example assumes that the managed user bjensen already exists:
curl \ --header "Content-Type: application/json" \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request POST \ --data '{"_ref":"managed/realm-name_user/bjensen"}' \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_organization/example-org/owners?_action=create" { "_id": "fcb0f4d0-dad2-4138-a80c-62407a8e831e", "_rev": "00000000496d9920", "_ref": "managed/realm-name_user/bjensen", "_refResourceCollection": "managed/realm-name_user", "_refResourceId": "bjensen", "_refProperties": { "_id": "fcb0f4d0-dad2-4138-a80c-62407a8e831e", "_rev": "00000000496d9920" } }
List an owner’s organizations
This example lists the organizations of which bjensen is an owner:
curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_user/bjensen/ownerOfOrg?_queryFilter=true" { "result": [ { "_id": "fcb0f4d0-dad2-4138-a80c-62407a8e831e", "_rev": "00000000496d9920", "_ref": "managed/realm-name_organization/example-org", "_refResourceCollection": "managed/realm-name_organization", "_refResourceId": "example-org", "_refProperties": { "_id": "fcb0f4d0-dad2-4138-a80c-62407a8e831e", "_rev": "00000000496d9920" } } ], ... }
Add an organization member
Organization owners can create members in the organizations that they own. In this example bjensen creates user scarter and makes him a member of the organization created previously:
curl \ --header "Content-Type: application/json" \ --header "X-OpenIDM-Username: bjensen" \ --header "X-OpenIDM-Password: Th3Password" \ --header "Accept-API-Version: resource=1.0" \ --request PUT \ --data '{ "userName": "scarter", "sn": "Carter", "givenName": "Steven", "mail": "scarter@example.com", "password": "Th3Password", "memberOfOrg": [{"_ref": "managed/realm-name_organization/example-org"}] }' \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_user/scarter" { "_id": "scarter", "_rev": "00000000eac81c23" }
List the members of an organization
Organization owners can view the members of the organizations that they own. In this example, bjensen lists the members of example-org:
curl \ --header "X-OpenIDM-Username: bjensen" \ --header "X-OpenIDM-Password: Th3Password" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_organization/example-org/members?_queryFilter=true" { "result": [ { "_id": "b71e8dd9-6224-466f-9630-4358a69c69fd", "_rev": "0000000038ea999e", "_ref": "managed/realm-name_user/scarter", "_refResourceCollection": "managed/realm-name_user", "_refResourceId": "scarter", "_refProperties": { "_id": "b71e8dd9-6224-466f-9630-4358a69c69fd", "_rev": "0000000038ea999e" } } ], ... }
Add an organization admin
Organization owners can create admins of the organizations that they own. An organization admin must be a member of the organization. In this example, bjensen makes scarter an admin of example-org:
curl \ --header 'Content-Type: application/json' \ --header "Accept-API-Version: resource=1.0" \ --header 'X-OpenIDM-Username: bjensen' \ --header 'X-OpenIDM-Password: Th3Password' \ --request PATCH \ --data '[ { "operation": "add", "field": "/admins/-", "value": { "_ref": "managed/realm-name_user/scarter" } } ]' \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_organization/example-org" { "_id": "example-org", "_rev": "000000009c248a4a", "adminIDs": [ "scarter" ], "ownerIDs": [ "bjensen" ], "parentAdminIDs": [], "parentIDs": [], "parentOwnerIDs": [], "name": "example-org" }
List an admin’s organizations
An organization owner, or admin, can only see the organizations that they own or administer. In this example, the admin scarter lists the organizations, and sees only those of which he is an admin:
curl \ --header "X-OpenIDM-Username: scarter" \ --header "X-OpenIDM-Password: Th3Password" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_organization?_queryFilter=true" { "result": [ { "_id": "example-org", "_rev": "000000009c248a4a", "adminIDs": [ "scarter" ], "ownerIDs": [ "bjensen" ], "parentAdminIDs": [], "parentIDs": [], "parentOwnerIDs": [], "name": "example-org" } ], ... }
Add a member as an organization admin
Organization admins can also add members to the organizations they administer. In this example, the organization admin, scarter, creates a new member, jsanchez, and makes her a member of example-org:
curl \ --header "Content-Type: application/json" \ --header "X-OpenIDM-Username: scarter" \ --header "X-OpenIDM-Password: Th3Password" \ --header "Accept-API-Version: resource=1.0" \ --request PUT \ --data '{ "userName": "jsanchez", "sn": "Sanchez", "givenName": "Juanita", "mail": "jsanchez@example.com", "password": "Th3Password", "memberOfOrg": [{"_ref": "managed/realm-name_organization/example-org"}] }' \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_user/jsanchez" { "_id": "jsanchez", "_rev": "00000000f9341bd6" }
List a member’s organizations
Organization owners and admins can list the organizations of which a user is a member, as long as those organizations are owned or administrated by them. In this example, scarter lists the organizations of which jsanchez is a member:
curl \ --header "X-OpenIDM-Username: scarter" \ --header "X-OpenIDM-Password: Th3Password" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_user/jsanchez?_fields=memberOfOrg" { "_id": "jsanchez", "_rev": "00000000f9341bd6", "memberOfOrg": [ { "_ref": "managed/realm-name_organization/example-org", "_refResourceCollection": "managed/realm-name_organization", "_refResourceId": "example-org", "_refProperties": { "_id": "078d14b2-e5f1-4b21-9801-041138e691f4", "_rev": "00000000ac2e9927" } } ] }
The organization established by the previous set of examples can be represented as follows:

In this organization, both bjensen and scarter can create and delete sub-organizations, also known as child organizations, of example-org, and can create and delete members within these child organizations.
The following example shows how to add and delete child organizations over the REST interface:
Add a child organization
Organization owners and admins can create and manage child organizations of the organizations that 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 example-org
:
curl \ --header "Content-Type: application/json" \ --header "X-OpenIDM-Username: bjensen" \ --header "X-OpenIDM-Password: Th3Password" \ --header "Accept-API-Version: resource=1.0" \ --header "If-None-Match: *" \ --request PUT \ --data '{ "name": "example-child-org", "parent": {"_ref": "managed/realm-name_organization/example-org"} }' \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_organization/example-child-org" { "_id": "example-child-org", "_rev": "00000000db852a9d" }
The organization model is based on delegated administration. As with delegated administration, you cannot explicitly change the relationship endpoints. So, for example, so you cannot create, update, delete, or patch relationship edges. The following type of request is therefore not possible with the organization model: curl \ --header "Content-Type: application/json" \ --header "X-OpenIDM-Username: bjensen" \ --header "X-OpenIDM-Password: Th3Password" \ --header "Accept-API-Version: resource=1.0" \ --header "If-None-Match: *" \ --request PUT \ --data '{ "name": "example-child-org", "parent": {"_ref": "managed/realm-name_organization/example-org"} }' \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_organization/children?_action=create" |
When creating a child organization, custom attributes need to be added to the access flags for the For more information on adding and updating privileges that apply to managed organizations, see Server configuration |
List an owner’s organizations and child organzations
Organization owners and admins have access to any organizations that are child organizations of their own orgs. In this example, admin scarter lists his visible organizations again:
curl \ --header "X-OpenIDM-Username: scarter" \ --header "X-OpenIDM-Password: Th3Password" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "https://tenant-name.forgeblocks.com/openidm/managed/realm-name_organization?_queryFilter=true" { "result": [ { "_id": "example-org", "_rev": "000000009c248a4a", "adminIDs": [ "scarter" ], "ownerIDs": [ "bjensen" ], "parentAdminIDs": [], "parentIDs": [], "parentOwnerIDs": [], "name": "example-org" }, { "_id": "example-child-org", "_rev": "00000000db852a9d", "adminIDs": [], "ownerIDs": [], "parentAdminIDs": [ "scarter" ], "parentIDs": [ "example-org" ], "parentOwnerIDs": [ "bjensen" ], "name": "example-child-org" } ], ... }
Notice that scarter can now see the example-child-org that bjensen created in the previous example.
Organizations in high latency environments
The relationship-derived virtual properties that support the organization model are generally calculated in response to relationship signals that travel down the organization tree hierarchy. Imagine, for example, that a new root organization is added to an existing organization hierarchy (or that a new admin or owner is added to the root of an existing organization hierarchy). The relationship signals that trigger relationship-derived virtual property calculation are propagated down the organization hierarchy, and to all members of the organizations in this hierarchy. This, in turn, updates their relationship-derived virtual property state.
If there are many thousands of members of the organizations in the hierarchy, this operation can take a long time to complete. It is therefore best practice to grow an organization hierarchy downwards, adding new organizations as leaves to 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 growing the hierarchy up towards the root.
If you must add a new root to an existing organization hierarchy with many organizations and many members, or a new admin or owner to an organization near the top of the hierarchy, rather perform this request over the command-line, using the examples provided in the previous section.
Use policies to validate data
Identity Cloud provides an extensible policy service that lets you apply specific validation requirements to various components and properties. This chapter describes the policy service, and provides instructions on configuring policies for managed objects.
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 application 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, see Script triggers defined in the router configuration.
A configurable default policy applies to all managed objects.
Default policy for managed objects
Policies applied to managed objects are configured in two places:
-
A policy script that defines each policy and specifies how policy validation is performed.
-
A managed object policy element, defined in your managed object schema, that specifies which policies are applicable to each managed resource. For more information, see Policy Configuration Element.
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.
Default policy reference
Identity Cloud includes the following default policies and parameters:
Policy Id | Parameters | |
---|---|---|
The property is required; not optional. |
||
The property can’t be empty. |
||
The property can’t be null. |
||
The property must be unique. |
||
Tests for uniqueness and internal user conflicts. |
||
Tests for internal user conflicts. |
||
Matches a regular expression. |
|
The regular expression pattern. |
Tests for the specified types. |
|
|
Tests for a valid query filter. |
||
Tests for valid array items. |
||
Tests for a valid date. |
||
Tests for a valid date format. |
||
Tests for a valid time. |
||
Tests for a valid date and time. |
||
Tests for a valid duration format. |
||
Tests for a valid email address. |
||
Tests for a valid name format. |
||
Tests for a valid phone number format. |
||
The property must contain the minimum specified number of capital letters. |
|
Minimum number of capital letters. |
The property must contain the minimum specified number of numbers. |
|
Minimum number of numbers. |
Tests for a valid number. |
||
The property value must be greater than the |
|
The minimum value. |
The property value must be less than the |
|
The maximum value. |
The property’s minimum string length. |
|
The minimum string length. |
The property’s maximum string length. |
|
The maximum string length. |
The property cannot contain values of the specified fields. |
|
A comma-separated list of the fields to check against. For example, the default managed user password policy specifies |
The property cannot contain the specified characters. |
|
A comma-separated list of disallowed characters. For example, the default managed user |
The property cannot contain duplicate characters. |
||
A sync mapping must exist for the property. |
||
Tests for valid permissions. |
||
Tests for valid access flags. |
||
Tests for a valid privilege path. |
||
Tests for valid temporal constraints. |
Policy Configuration Element
Properties defined in the Identity Cloud managed object schema 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 password
and _id
properties 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 policy 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,
"policies" : [
{
"policyId" : "minimum-length",
"params" : {
"minLength" : 8
}
},
{
"policyId" : "at-least-X-capitals",
"params" : {
"numCaps" : 1
}
},
{
"policyId" : "at-least-X-numbers",
"params" : {
"numNums" : 1
}
},
{
"policyId" : "cannot-contain-others",
"params" : {
"disallowedFields" : [
"userName",
"givenName",
"sn"
]
}
}
]
}
}
}
}
Note that the policy for the _id
property references the function cannot-contain-characters
, which is defined in the policy. The policy for the password
property references the functions minimum-length
, at-least-X-capitals
, at-least-X-numbers
, and cannot-contain-others
, that are defined in the policy. The parameters that are passed to these functions (number of capitals required, and so forth) are specified in the same element.
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, see 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 schema.
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 schema:
"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 valid-type
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 IDM admin UI
To configure policy validation for a managed object type using the IDM admin UI, update the configuration of the object type—a high-level overview:
-
Go to the managed object, and edit or create a property.
-
Click the Validation tab, and add the policy.
Show Me

-
From the navigation bar, click Configure > Managed Objects.
-
On the Managed Objects page, edit or create a managed object.
-
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.
-
Now click the property.
-
-
-
From the Validation tab, click Add Policy.
-
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, see Policy Reference.
- Parameter Name
-
Refers to the parameters for the
PolicyId
. For a list of the default policy parameters, see Policy Reference. - Value
-
The parameter’s value to validate.
Be cautious when using Validation Policies. If a policy relates to an array of relationships, such as between a user and multiple devices, Return by Default should always be set to |
Extend the policy service
You can extend the policy service by adding policies that are applied only under certain conditions.
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 schema. 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" : "max-age",
"params" : {
"maxDays" : ["90"]
}
}
]
},
{
"condition" : {
"type" : "text/javascript",
"source" : "(fullObject.org === 'employees')"
},
"dependencies" : [ "org" ],
"policies" : [
{
"policyId" : "max-age",
"params" : {
"maxDays" : ["30"]
}
}
]
}
],
"fallbackPolicies" : [
{
"policyId" : "max-age",
"params" : {
"maxDays" : ["7"]
}
}
]
}
...
}
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 max-age
policy is applied to the password
attribute of the user object, and the maximum number of days that a password may remain unchanged is set to 90
.
The second condition asserts that the user object is a member of the employees
org. If that assertion is true, the max-age
policy is applied to the password
attribute of the user object, and the maximum number of days that a password may remain unchanged is set to 30
.
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 max-age
policy and specifies that for such users, their password must be changed after 7 days.
The dependencies
field prevents the condition scripts from being run at all, if the user object does not include an org
attribute.
Manage policies over REST
Manage the policy service over the REST interface at the openidm/policy
endpoint.
List the defined policies
The following REST call displays a list of all the policies defined in Identity Cloud that are not associated with a specific resource. 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-name.forgeblocks.com/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-name.forgeblocks.com/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-name.forgeblocks.com/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-name.forgeblocks.com/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-name.forgeblocks.com/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-name.forgeblocks.com/openidm/policy/managed/realm-name_user/ca5a3196-2ed3-4a76-8881-30403dee70e9?_action=validateProperty"
Because givenName
is a required field, Identity Cloud returns a failed policy validation:
{
"result": false,
"failedPolicyRequirements": [
{
"policyRequirements": [
{
"policyRequirement": "REQUIRED"
}
],
"property": "givenName"
}
]
}
Force validation of default values
Identity Cloud 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.
-
Always pass the object and properties content in the POST body because Identity Cloud has no object to look up.
-
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
:"password" : { ... "conditionalPolicies" : [ { "condition" : { "type" : "text/javascript", "source" : "(fullObject.description === 'test1')" }, "dependencies" : [ "description" ], "policies" : [ { "policyId" : "at-least-X-capitals", "params" : { "numCaps" : 1 } } ] } ],
-
Using the above conditional policy, you could perform a
validateProperty
action tomanaged/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": { "password": "passw0rd" } }' \ "https://tenant-name.forgeblocks.com/openidm/policy/managed/realm-name_user/*?_action=validateProperty" { "result": false, "failedPolicyRequirements": [ { "policyRequirements": [ { "params": { "numCaps": 1 }, "policyRequirement": "AT_LEAST_X_CAPITAL_LETTERS" } ], "property": "password" } ] }
Access data objects using scripts
Identity Cloud’s uniform programming model means that all objects are queried and manipulated in the same way, using the Resource API. The URL or URI that is used to identify the target object for an operation depends on the object type. For more information about scripts and the objects available to scripts, see 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, see URI Scheme.
You can update entire objects with the update()
function, as follows:
openidm.update("managed/realm-name_organization/mysampleorg", rev, object)
openidm.update("system/mysystem/account", rev, object)
You can apply a partial update to a managed or system object by using the patch()
function:
openidm.patch("managed/realm-name_organization/mysampleorg", rev, value)
The create()
, delete()
, and query()
functions work the same way.
Access data objects using the REST API
Identity Cloud provides RESTful access to data objects through the ForgeRock Common 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.
For a comprehensive overview of the REST API, see the REST API reference.
To obtain a managed object through the REST API, depending on your security settings and authentication configuration, perform an HTTP GET on the corresponding URL, for example https://tenant-name.forgeblocks.com/openidm/managed/realm-name_organization/mysampleorg
.
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. The following example shows how the parameters provided in an openidm.query
request correspond with the key-value pairs that you would include in a similar HTTP GET request:
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-name.forgeblocks.com/openidm/managed/realm-name_user?_queryFilter=true&_fields=userName,sn"
Access data objects by remote proxy
You can proxy REST requests to a remote IDM instance using the /external/idm/factoryPid
endpoint. This lets you treat any other IDM instance as a resource within the one you are managing. You can then use it in a sync mapping, call actions on it, use it within scripts, or use it in any other way that you might use a resource in IDM. You can call any endpoint in the remote IDM system using this proxy.
A few situations where this feature may be useful include:
-
Situations where a development or testing environment has data that needs to be synced into the production environment.
-
Situations where data is deployed in geographically diverse data centers and changes need to be kept in sync with one another.
-
Situations where a new instance needs to sync data between existing on-premises and cloud instances.
This feature does not support liveSync/implicit sync from the remote IDM resources. This means that you will be limited to using recon when it comes to pulling data from a remote system.
Prerequisites
To connect to a remote instance over SSL, you must import the remote instance’s server certificate into your local instance’s truststore. For further information, see Configure a self-managed SSL certificate.
Use in a sync mapping
To use the remote IDM 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-name.forgeblocks.com/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-name.forgeblocks.com/openidm/config/sync"
Authentication
Authentication against the remote IDM instance is supported via basic
authentication, or bearer
token authentication when IDM is configured to use rsFilter. The authentication strategy determines some of the parameters required for the request.
Property | Required? | Definition |
---|---|---|
enabled |
No |
The enable state of the service. Default is |
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 |
instanceUrl |
Yes |
The URL of the remote instance to relay the request to. |
userName |
With |
The basic authentication user name. |
password |
With |
The basic authentication password. |
clientId |
With |
The clientId used to request an access token from the token endpoint. |
clientSecret |
With |
The client secret used to request an access token from the token endpoint. |
tokenEndpoint |
With |
The OAuth2 token endpoint. |
Examples
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" : " "
}
Sample request
curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ 'https://tenant-name.forgeblocks.com/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 }
Define and call data queries
An advanced query model enables you to define queries and to call them over the REST or Resource API. The following types of queries are supported, on both managed, and system objects:
-
Common filter expressions
-
Parameterized, or predefined queries
Special characters in queries
JavaScript query invocations are not subject to the same URL-encoding requirements as GET requests. Because 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"
}
Common filter expressions
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 in that they do not require knowledge of how the object is stored and 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-name.forgeblocks.com/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"' });
Note that, this JavaScript invocation is internal and is not subject to the same URL-encoding requirements that a GET request would be. Also, because JavaScript supports the use of single quotes, it is not necessary to escape the double quotes in this example.
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 on which the query should be performed, and params
provides the parameters that are 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-name.forgeblocks.com/openidm/managed/realm-name_user?_queryFilter=userName+eq+"Smith"'
In |
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 ( |
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
.
"_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-name.forgeblocks.com/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" } ], ... }
"_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-name.forgeblocks.com/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
.
"_queryFilter" : '/givenName co "Da"'
The following REST call returns the user name 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-name.forgeblocks.com/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
.
"_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-name.forgeblocks.com/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
.
"_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-name.forgeblocks.com/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
.
"_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-name.forgeblocks.com/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
"_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-name.forgeblocks.com/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
.
"_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-name.forgeblocks.com/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 |
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-name.forgeblocks.com/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-name.forgeblocks.com/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" ( |
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-name.forgeblocks.com/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
Identity Cloud 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:
|
curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "https://tenant-name.forgeblocks.com/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 directly 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-name.forgeblocks.com/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 last name Jensen:
curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ 'https://tenant-name.forgeblocks.com/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 }
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 Identity Cloud effectively 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 thetotalPagedResults
, in accordance with thetotalPagedResultsPolicy
, and provides the value as part of the response. If a count policy is specified (_totalPagedResultsPolicy=EXACT
, ThetotalPagedResults
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 fortotalPagedResults
. The following example shows a query that requests two results with atotalPagedResultsPolicy
ofEXACT
:curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "https://tenant-name.forgeblocks.com/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 in which the JSON result is returned, based on this list.
The _sortKeys
parameter is not supported for predefined queries.
|
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-name.forgeblocks.com/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 |
Recalculate virtual property values in queries
For managed objects Identity Cloud includes an onRetrieve
script hook that enables you to recalculate property values 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-name.forgeblocks.com/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 |
Import bulk data
The bulk import facility lets you import large numbers of external entries over REST. You import entries from a comma-separated values (CSV) file, to a specified managed object type in the Identity Cloud repository. Bulk import works as follows:
-
Loads bulk CSV entries and stores them temporarily (in the Identity Cloud repository) as JSON objects
-
Creates a temporary mapping between those entries and the managed object store in the repository
-
Performs a reconciliation between the JSON objects and the objects in the repository
The bulk import mechanism assumes that the CSV file is the authoritative data source. If you run an import more than once, the import overwrites all of the properties of the managed object (including timestamps) with the values in the CSV file. |
To import bulk CSV entries into the repository, using the REST API, follow these steps:
Generate a CSV Template
The first time you upload entries, you must generate a CSV template. The template is essentially an empty CSV file with one header row that matches the managed object type to which you are importing. In most cases, you will be importing data that fits the managed/realm-name_user
object model, but you can import any managed object type, such as roles and assignments.
To generate the CSV template, send a GET request to the openidm/csv/template
endpoint. The following request generates a CSV template for the managed user object type:
curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "https://tenant-name.forgeblocks.com/openidm/csv/template?resourceCollection=managed/realm-name_user&_fields=header&_mimeType='text/plain'" { "_id": "template", "header": "\"userName\",\"givenName\",\"sn\",\"mail\",\"description\",\"accountStatus\",\"telephoneNumber\", \"postalAddress\",\"city\",\"postalCode\",\"country\",\"stateProvince\",\"preferences/updates\", \"preferences/marketing\"" }
The template is generated based on the specified resourceCollection
, and includes a single header row. The names of each header column are derived from the schema of the managed object type. The template includes only a subset of managed user properties that can be represented by CSV fields.
Only the following managed object properties are included in the header row:
-
Properties of type
string
,boolean
, andnumber
-
Properties that do not start with an underscore (such as
_id
or_rev
)If you are importing entries to
managed/realm-name_user
, the bulk import facility assumes that self-service password reset is enabled. This is because the import does not support upload of hashed passwords. -
Properties whose
scope
is notprivate
Set the parameters _fields=header
and _mimeType=text/csv
to download the template as a CSV file.
When you have generated the template, export your external data to CSV format, using the headers in the generated template.
Upload a CSV File
The default maximum file size for bulk import is 50MBytes. If you need to import a number of records that exceeds this size, divide the data into chunks and import each file separately.
When you have a CSV file, with the structure of the template generated in the previous example, upload the file to the Identity Cloud repository with the following request:
curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --form upload=@/path/to/example-users.csv \ --request POST \ "https://tenant-name.forgeblocks.com/upload/csv/managed/realm-name_user?uniqueProperty=userName" { "importUUIDs": [ "3ebd514f-bdd7-491f-928f-21b72f44e381" ] }
--form
(-F
)-
This option causes
curl
to POST data using the Content-Typemultipart/form-data
, which lets you upload binary files. To indicate that the form content is a file, prefix the file name with an@
sign.To import more than one file at once, specify multiple
--form
options, for example:--form upload=@/path/to/example-users-a-j.csv \ --form upload=@/path/to/example-users-k-z.csv \
uniqueProperty
(required)-
This parameter lets you correlate existing entries, based on a unique value field. This is useful if you need to upload the same file a number of times (for example, if data in the file changes, or if some entries in the file contained errors). You can specify any unique value property here. You can also correlate on more than one property by specifying multiple, comma-delimited unique properties.
A successful upload generates an array of importUUID
s. You need these UUIDs to perform other operations on the import records.
Note that the endpoint ( |
Query Bulk Imports
A query on the csv/metadata
endpoint returns the import ID, the data structure (header fields in the CSV file), a recon ID, and a number of fields indicating the status of the import:
curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ "https://tenant-name.forgeblocks.com/openidm/csv/metadata/?_queryFilter=true" { "result": [ { "_id": "3ebd514f-bdd7-491f-928f-21b72f44e381", "_rev": "000000003e8ef4f7", "header": [ "userName", "givenName", "sn", "mail", "description", "accountStatus", "country" ], "reconId": "2e2cf41a-c4b8-4dda-9d92-6e0af65a15fe-6528", "filename": "example-users.csv", "resourcePath": "managed/realm-name_user", "total": 1000, "success": 1000, "failure": 0, "created": 1000, "updated": 0, "unchanged": 0, "begin": "2020-04-17T16:31:02.955Z", "end": "2020-04-17T16:31:09.861Z", "cancelled": false, "importDeleted": false, "tempRecords": 0, "purgedTempRecords": true, "purgedErrorRecords": false, "authId": "openidm-admin", "authzComponent": "internal/user" }, { "_rev": "00000000d4392fc8" } ], ... }
Query Imports To a Specific Object Type
Use a query filter to restrict your query to imports to a specific managed object type. The following example queries uploads to the managed user object:
curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request GET \ 'https://tenant-name.forgeblocks.com/openidm/csv/metadata/?_queryFilter=/resourcePath+eq+"managed/realm-name_user"' { "result": [ { "_id": "82d9a643-8b03-4cec-86fc-3e09c4c2f01c", "_rev": "000000009b3ff60b", "header": [ "userName", "givenName", "sn", "mail", "description", "accountStatus", "country" ], "reconId": "417dae3b-c939-4191-acbf-6eb1b9e802af-53335", "filename": "example-users.csv", "resourcePath": "managed/realm-name_user", "total": 1001, "success": 1000, "failure": 1, "created": 0, "updated": 0, "unchanged": 1000, "begin": "2020-04-20T13:12:03.028Z", "end": "2020-04-20T13:12:05.222Z", "cancelled": false, "importDeleted": false, "tempRecords": 0, "purgedTempRecords": true, "purgedErrorRecords": false, "authId": "openidm-admin", "authzComponent": "internal/user" } ], ... }
Handle Failed Import Records
The previous example showed the statistics that are returned when you query bulk imports. One of these fields is "failure": 0,
. If the import was unsuccessful for any records, this failure
field will have a positive value. You can then download the failed records, examine the failures and correct them in the CSV file, then run the import again.
To download failed records, send a GET request to the endpoint export/csvImportFailures/importUUID
:
curl \ --header "Authorization: Bearer *token*" \ --request GET \ --header "Accept-API-Version: resource=1.0" \ "https://tenant-name.forgeblocks.com/export/csvImportFailures/82d9a643-8b03-4cec-86fc-3e09c4c2f01c" userName, givenName, sn, mail, ..., _importError emacheke, Edward, Macheke, emacheke, ..., "{code=403, reason=Forbidden, message=Policy validation failed, detail={result=false, failedPolicyRequirements=[{policyRequirements=[ {policyRequirement=VALID_EMAIL_ADDRESS_FORMAT}], property=mail}]}}"
The output indicates the failed record or records, and the reason for the failure, in the _importError
field. In this example, the import failed because of a policy validation error—the email address is not the correct format.
Identity Cloud does not scan for possible CSV injection attacks on uploaded files. Do not edit the downloaded CSV file with Microsoft Excel, as this can expose your data to CSV injection. |
Cancel an Import in Progress
Cancel an import that is in progress by sending a POST request to the openidm/csv/metadata/importUUID
endpoint, with the cancel
action. You might want to cancel an import if the import is taking too long, or if you have noticed problems with the import data, for example:
curl \ --header "Authorization: Bearer *token*" \ --header "Accept-API-Version: resource=1.0" \ --request POST \ "https://tenant-name.forgeblocks.com/openidm/csv/metadata/92971c92-67bb-4ae7-b41b-96d249b0b2aa/?_action=cancel" { "status": "OK" }
HTTP Request Timeout
By default, the timeout for the bulk import servlets is 30 seconds (or 30000
milliseconds). This parameter is set in your resolver/boot.properties
file, as follows:
openidm.servlet.timeoutMillis=30000
If you are importing a very large number of records, you might need to increase the HTTP request timeout to prevent requests timing out.
In test environments, you can set this parameter to 0
to disable the request timeout. You should not disable the timeout in a production environment because no timeout can lead to DDoS attacks where thousands of slow HTTP connections are made.
For a list of all REST endpoints related to bulk import, see Bulk import.
Appendix A: Data models and objects reference
You can customize a variety of objects that can be addressed via a URL or URI. Identity Cloud 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.
Object Type | Intended Use | Special Functionality |
---|---|---|
Managed objects |
Serve as targets and sources for synchronization, and to build virtual identities. |
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 can be configured 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 purely through the underlying data store or repository API. |
Persistence and API access |
System objects |
Representation of target resource objects, such as accounts. |
|
Audit objects |
Houses audit data in the repository. |
|
Links |
Defines a relation between two objects. |
|
Managed objects
Managed objects and their properties are defined in the Identity Cloud 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 Identity Cloud. In Identity Cloud, 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. Identity Cloud does not expose any transactional semantics in the managed object access API.
For information on conditional header access through the REST API, see 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.
- 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. 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
andnewObject
variables are in-scope for the trigger. TheoldObject
represents a complete object, as retrieved from the data store. The trigger can elect to changenewObject
properties. If, as a result of the trigger, the values of theoldObject
andnewObject
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
-
Called when a managed object is changed, and the change triggers an implicit synchronization operation. The implicit synchronization operation is triggered by calling the sync service, which attempts to go through all the configured managed-system mappings. The sync service returns either a response or an error. For both the response and the error, the script that is referenced by the
onSync
hook is called.You can use this hook to inject business logic when the sync service either fails or succeeds to synchronize all applicable mappings. For an example of how the
onSync
hook is used to revert partial successful synchronization operations, see Synchronization Failure Compensation.
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 just prior to when an object is stored in the data store. Typically used to transform an object just 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 ifexecuteOnRetrieve
is set totrue
in the query request parameters. IfexecuteOnRetrieve
is not passed, or if it isfalse
, 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
-
-
Retrieve the raw object from the data store
-
The
executeOnRetrieve
boolean is used to check whether property values should be recalculated. The sequence continues if the boolean is set totrue
. -
Call object
onRetrieve
trigger -
Per-property within the object, call property
onRetrieve
trigger
-
- Object Storage Sequence
-
-
Per-property within the object:
-
Call property
onValidate
trigger -
Call object
onValidate
trigger
-
-
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.
{
"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 Object 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
}
}
- 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, see 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, therequest
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 anewObject
property. The script can change thenewObject
. 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 anewObject
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.
The
schema
property includes the following additional elements:- icon
-
string, optional
The name of the Font Awesome icon to display for this object in the UI. Only applies to standalone Identity Cloud.
- mat-icon
-
string, optional
The name of the Material Design Icon to display for this object in the UI. Only applies to Identity Cloud as part of the ForgeRock Identity Platform.
- id
-
urn, optional
The URN of the managed object, for example,
urn:jsonschema:org:forgerock:openidm:managed:api:Role
. - order
-
list of properties, optional
The order in which properties of this managed object are displayed in the UI.
- properties
-
list of property configuration objects, optional
A list of property specifications. For more information, see Property Configuration Properties.
- $schema
-
url, optional
Link to the JSON schema specification.
- title
-
string, optional
The title of this managed object in the UI.
- 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,
}
- 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 totrue
foruserName
andpostalAddress
. - 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 Identity Cloud 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
can include the following sub-properties:- id
-
urn, optional
The URN of the property, for example,
urn:jsonschema:org:forgerock:openidm:managed:api:Role:members: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", ... } }
- resourceCollection
-
property configuration object, optional
The collection of resources (objects) on which this relationship is based (for example,
managed/realm-name_user
objects). - reversePropertyName
-
string, optional
For
relationship
type properties, specifies the corresponding property name in the case of a reverse relationship. For example, aroles
property might have areversePropertyName
ofmembers
. - reverseRelationship
-
boolean, true or false.
For
relationship
type properties, specifies whether the relationship exists in both directions. - title
-
string, optional
The title of array items, as displayed in the UI, for example
Role Members Items
. - type
-
string, optional
The array type, for example
relationship
. - 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
andpropertyName
. The property that was retrieved is provided in the root scope as thepropertyName
variable; its value is provided as theproperty
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
andpropertyName
. The property that was retrieved is provided in the root scope as thepropertyName
variable; its value is provided as theproperty
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
Identity Cloud supports
"text/javascript"
. - source, file
-
string, required (only one, source or file is required)
Specifies the source code of the script to be executed (if the keyword is "source"), or a pointer to the file that contains the script (if the keyword is "file").
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 Identity Cloud cryptography service keystore used to encrypt the property.
Accessing Managed Objects Through the REST API
Identity Cloud exposes all managed object functionality through the REST API unless you configure a policy to prevent such access. In addition to the common REST functionality of create, read, update, delete, patch, and query, the REST API also supports patch by query. For more information, see the REST API reference.
System objects
System objects are 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.
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.