PingOne Advanced Identity Cloud

Authentication

Authentication is the process of verifying who is requesting access to a resource. The user or application making the request presents credentials, making it possible to prove that the requester is who they claim to be. The goal is to authorize access to specific IDM resources, depending on the confirmed identity of the user or application making the request.

Authentication and roles

When a user authenticates, the user is given a set of default internal roles. These roles determine what IDM resources the user can access. IDM includes a number of default internal roles, on the openidm/internal/roles endpoint. You can configure additional internal roles to customize how you restrict access to the server.

The following internal roles are defined by default:

openidm-admin

IDM administrator role, excluded from the reauthorization required policy definition by default.

openidm-authorized

Default role for any user who authenticates with a username and password.

openidm-cert

Default role for any user who authenticates with mutual SSL authentication.

This role applies only to mutual authentication. The shared secret (certificate) must be adequately protected. The openidm-cert role is excluded from the reauthorization required policy definition by default.

openidm-reg

Assigned to users who access IDM with the default anonymous account.

The openidm-reg role is excluded from the reauthorization required policy definition by default.

openidm-tasks-manager

Role for users who can be assigned to workflow tasks.

platform-provisioning

Role for platform provisioning access. If you are not planning to run AM and IDM together as a platform, you can safely remove this role.

When a user authenticates, IDM calculates that user’s roles as follows:

  • Each authentication module includes a defaultUserRoles property. Depending on how the user authenticates, IDM assigns the roles listed in that module’s defaultUserRoles property to the user on authentication. The defaultUserRoles property is specified as an array. For most authentication modules, the user obtains the openidm-authorized role on authentication. For example:

    {
        "name" : "MANAGED_USER",
        "properties" : {
            ...
            "defaultUserRoles" : [
                "internal/role/openidm-authorized"
            ]
        },
        ...
    }
  • The userRoles property in an authentication module maps to an attribute (or list of attributes) in a user entry that contains that user’s authorization roles. This attribute is usually authzRoles, unless you have changed how user roles are stored.

    Any internal roles that are conditionally applied are also calculated and included in the user’s authzRoles property at this point.

  • If the authentication module includes a groupRoleMapping, groupMembership, or groupComparison property, IDM can assign additional roles to the user, depending on the user’s group membership on an external system. For more information, refer to Use Groups to Control Access to IDM.

    The roles calculated in sequence are cumulative. Roles with temporal restrictions are not included in that list if the current time is outside of the time assigned to the role.

Dynamic role calculation

By default, IDM calculates a user’s roles only on authentication. You can configure IDM to recalculate a user’s roles dynamically, with each request, instead of only when the user reauthenticates. To enable this feature, set enableDynamicRoles to true in the JWT_SESSION session module in authentication.json:

To enable dynamic role calculation using the IDM admin UI, click Configure > Authentication > Session > Enable Dynamic Roles.

Roles, authentication, and the Security Context

The Security Context (context.security), consists of a principal (defined by the authenticationId property) and an access control element (defined by the authorization property).

If authentication is successful, the authentication framework sets the principal. IDM stores that principal as the authenticationId.

The authorization property includes an id, an array of roles, and a component, that specifies the resource against which authorization is validated.

Authentication through OAuth 2.0 and subject mappings

Ping Identity IDM uses AM bearer tokens for authentication. Accordingly, all authentication is delegated to AM. With AM bearer tokens, all Advanced Identity Cloud endpoints that require authentication are accessed using an authorization header that contains the bearer token. Endpoints that allow anonymous access can be accessed without a token.

This page details the backend process of how AM does this, which includes subject mappings.

An rsFilter is an authentication method used to delegate authentication from IDM to AM. In Advanced Identity Cloud, the rsFilter is predefined in the authentication configuration.

The rsFilter configuration includes the following properties:

scopes

Any scopes that are required to be present in the access token. This will vary depending on your configuration. For more information about scopes, refer to OAuth 2.0 scopes in the AM OAuth 2.0 Guide.

cache

Sets the timeout (maxTimeout), in seconds, after which the token is removed from the cache.

augmentSecurityContext

Specifies a script that is executed only after a successful authentication request. The script helps to populate the expected security context. For more information, refer to The augmentSecurityContext trigger.

subjectMapping

An array of mappings that maps the AM realms (in Advanced Identity Cloud /alpha and /bravo) to IDM managed object types. For example:

"subjectMapping" : [
    {
        "queryOnResource" : "managed/realm-name_user",
        "propertyMapping" : {
            "sub" : "_id"
        },
        "userRoles" : "authzRoles/*",
        "additionalUserFields" : [
            "adminOfOrg",
            "ownerOfOrg"
        ],
        "defaultRoles" : [
            "internal/role/openidm-authorized"
        ]
    }
],
  • queryOnResource: The IDM resource to check for the authenticating user; for example, managed/realm-name_user.

    The queryOnResource property supports dynamic handlebars template that lets a single subject mapping match multiple realms, if the managed objects are named prescriptively, and based on the realm name.

    For example:

    "queryOnResource" : "managed/realm-name_user"

    This example configuration lets an access token with the realm alpha map to an IDM managed/alpha_user, and an access token with the realm bravo map to an IDM managed/bravo_user. The configuration is useful if your AM and IDM deployments use a consistent realm and managed object naming.

    • realm: The AM realm to which this subject mapping applies. A value of / specifies the top-level realm. If this property is absent, the mapping can apply to any realm, which is useful if the queryOnResource uses a dynamic handlebars template.

      You cannot have more than one mapping for the same realm, and you cannot have more than one mapping that has no realm in the configuration.
    • propertyMapping: Maps fields in the AM access token to properties in IDM. This mapping is used to construct the query filter that locates the authenticating user. The default configuration maps the subject (sub) in the access token to the _id in IDM.

    • userRoles: Determines the field to consult for locating the authorization roles; usually authzRoles, unless you have changed how user roles are stored. This field must be a relationship field. IDM uses the _refId from the array elements to populate the user roles in the security context.

    • additionalUserFields: Determines the field to consult for locating the authorization roles; usually authzRoles, unless you have changed how user roles are stored. This field must be a relationship field. IDM uses the _refId from the array elements to populate the user roles in the security context.

    • defaultRoles: The default roles that should be applied to a user who authenticates using the rsFilter.

{
    "subject" : "RCS-OAuth-clientId",
    "localUser" : "internal/user/idm-provisioning"
}

The subject must reflect the OAuth2 client in AM that has been set up for the remote connector server. The localUser can be any existing user. Do not assign that user any roles to ensure that the connector server bearer token cannot be used for any other purpose.

staticUserMapping

Maps AM users to a matching IDM user. Can contain multiple user mappings, each with three properties: subject, localUser, and roles.

  • subject of the access token (the AM user). If you have specified a resourceTypeMapping, the static user mapping includes the full new subject string to match service accounts or static subject mappings, for example:

    "subject" : "amadmin"
  • localUser is the IDM user you want to associate with the AM user identified in subject. For example, if subject is set to amadmin, you might set the corresponding localUser to internal/user/openidm-admin.

  • roles the default IDM roles that this mapped user will have after they authenticate.

    The idm-provisioning subject is a service account used by AM to provision users in IDM. You must include this subject in your staticUserMapping. For example:
    {
        "subject": "(age!idm-provisioning)",
        "localUser": "internal/user/idm-provisioning",
        "roles" : [
            "internal/role/platform-provisioning"
        ]
    }

Only one mapping is selected and used during the authentication process. If there is a realm attribute in the access token, that realm is used to select an appropriate mapping. If no mapping is defined for the access token’s realm, or if the realm is not provided in the access token, the authentication uses a mapping that does not define a realm.

In most situations if you have a remote connector server that is authenticating against AM, you must add a subject mapping specifically for the connector server.

In this case you must add a staticUserMapping.

Test authentication

To test authentication, create your own OAuth 2.0 client with the proper grant types. For more information, refer to Create custom OAuth 2.0 applications with application management.

  1. Obtain a bearer token from AM.

    For example, the bearer token would look like:

    Authorization: Bearer z4uKDWiv4wnxKY7OjeG04PujG8E

    For more information on how get a bearer token, refer to Authenticate to REST API with an access token.

  2. Authenticate to IDM using that bearer token:

    curl \
    --request GET \
    --header "Content-Type: application/json" \
    --header "Authorization: Bearer z4uKDWiv4wnxKY7OjeG04PujG8E" \
    'https://<tenant-env-fqdn>/openidm/info/login'
    {
      "_id": "login",
      "authenticationId": "testClientID",
      "authorization": {
        "id": "testClientID",
        "roles": [
          "internal/role/platform-provisioning"
        ],
        "component": "internal/user"
      }
    }

Authorization and roles

IDM provides role-based authorization that restricts direct HTTP access to REST interface URLs. This access control applies to direct HTTP calls only. Access for internal calls (for example, calls from scripts) is not affected by this mechanism.

When a user authenticates, the user is given a set of default roles, as described in Authentication and Roles. The authorization configuration grants access rights to users, based on these roles acquired during authentication.

You can use internal and managed roles to restrict access, with the following caveats:

  • Internal roles are not meant to be provisioned or synchronized with external systems.

  • Internal roles cannot be given assignments.

  • Event scripts (such as onCreate) cannot be attached to internal roles.

  • The internal role schema is not configurable.

Authorization roles are referenced in a user’s authzRoles property by default, and are assigned when the user authenticates.

By default, managed users are assigned the openidm-authorized role when they authenticate. The following request shows the authorization roles for user psmith when that user logs in to the server:

curl \
--header "X-OpenIDM-Username: psmith" \
--header "X-OpenIDM-Password: Passw0rd" \
--header "Accept-API-Version: resource=1.0" \
--cacert ca-cert.pem \
--request GET \
"https://<tenant-env-fqdn>/openidm/info/login"
{
  "_id": "login",
  "authenticationId": "psmith",
  "authorization": {
    "userRolesProperty": "authzRoles",
    "component": "managed/realm-name_user",
    "authLogin": false,
    "authenticationIdProperty": "username",
    "roles": [
      "internal/role/openidm-authorized"
    ],
    "ipAddress": "0:0:0:0:0:0:0:1",
    "authenticationId": "psmith",
    "protectedAttributeList": [
      "password"
    ],
    "id": "psmith",
    "moduleId": "MANAGED_USER",
    "queryId": "credential-query"
  }
}

The authorization implementation is configured in two files:

  • openidm/bin/defaults/script/router-authz.js

  • project-dir/conf/access.json

IDM calls the router-authz.js script for each request. router-authz.js references your project’s access configuration file (access.json) to determine the allowed HTTP requests. If access is denied, according to the configuration defined in access.json, the router-authz.js script throws an exception, and IDM denies the request.

In addition, the router.json file also defines onResponse relationshipFilter filters. This provides additional filtering to ensure that the user has the appropriate access to see the data of the related object. You can change this behavior by extending or updating /bin/defaults/script/relationshipFilter.js, or by removing the onResponse script if you don’t want additional filtering on relationships. For more information about relationships, refer to Relationships between objects.

You can configure delegated administration to bypass this access control.

The router authorization script

The router authorization script (router-authz.js contains a number of functions that enforce access rules. For example, the following function controls whether users with a certain role can start a specified process:

function isAllowedToStartProcess() {
    var processDefinitionId = request.content._processDefinitionId;
    var key = request.content._key;
    return isProcessOnUsersList(function (process) {
        return (process._id === processDefinitionId) || (process.key === key);
    });
}

You can extend the default authorization mechanism by defining additional functions in router-authz.js and by creating new access control rules in access.json.

Some authorization-related functions in router-authz.js should not be altered, because they affect the security of the server. Such functions are indicated in the comments in that file.

Configure access control in access.json

The access.json configuration includes a set of rules that govern access to specific endpoints. These rules are tested in the order in which they appear in the file. You can define more than one rule for the same endpoint. If one rule passes, the request is allowed. If all the rules fail, the request is denied.

The following rule (from a default access.json file) shows the access configuration structure:

{
    "pattern"   : "system/*",
    "roles"     : "internal/role/openidm-admin",
    "methods"   : "action",
    "actions"   : "test,testConfig,createconfiguration,liveSync,authenticate"
}

This rule specifies that users with the openidm-admin role can perform the listed actions on all system endpoints.

The parameters in each access rule are as follows:

pattern

The REST endpoint for which access is being controlled. "*" specifies access to all endpoints in that path. For example, "managed/realm-name_user/*" specifies access to all managed user objects.

roles

A comma-separated list of the roles to which this access configuration applies.

The roles referenced here align with the object’s security context (security.authorization.roles). The authzRoles relationship property of a managed user produces this security context value during authentication.

methods

A comma-separated list of the methods that can be performed with this access. Methods can include create, read, update, delete, patch, action, query. A value of "*" indicates that all methods are allowed. A value of "" indicates that no methods are allowed.

actions

A comma-separated list of the allowed actions. The possible actions depend on the resource (URL) that is being exposed. Note that the actions in the default access.json file do not list all the supported actions on each resource.

A value of "*" indicates that all actions exposed for that resource are allowed. A value of "" indicates that no actions are allowed.

customAuthz

An optional parameter that lets you define a custom function for additional authorization checks. Custom functions are defined in router-authz.js .

excludePatterns

An optional parameter that lets you specify endpoints to which access should not be granted.

Change the access configuration over REST

You can manage the access configuration at the endpoint openidm/config/access. To change an access rule, first get the current access configuration, amend it to change the access rule, then submit the updated configuration in a PUT request. This example restricts access to the info endpoint to users who have authenticated:

Get the current access configuration
curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0"  \
--request GET \
"https://<tenant-env-fqdn>/openidm/config/access"
{
  "_id": "access",
  "configs": [
    {
      "pattern": "info/*",
      "roles": "*",
      "methods": "read",
      "actions": "*"
    },
    {
      "pattern": "authentication",
      "roles": "*",
      "methods": "read,action",
      "actions": "login,logout"
    },
    {
      "pattern": "identityProviders",
      "roles": "*",
      "methods": "action",
      "actions": "getAuthRedirect,handlePostAuth,getLogoutUrl"
    },
    {
      "pattern": "identityProviders",
      "roles": "internal/role/openidm-authorized",
      "methods": "action",
      "actions": "normalizeProfile"
    },
    {
      "pattern": "identityProviders",
      "roles": "internal/role/openidm-authorized",
      "methods": "read",
      "actions": "*"
    },
    {
      "pattern": "config/ui/themeconfig",
      "roles": "*",
      "methods": "read",
      "actions": "*"
    },
    {
      "pattern": "info/uiconfig",
      "roles": "*",
      "methods": "read",
      "actions": "*"
    },
    {
      "pattern": "config/selfservice/kbaConfig",
      "roles": "*",
      "methods": "read",
      "actions": "*",
      "customAuthz": "checkIfAnyFeatureEnabled(['registration', 'passwordReset'])"
    },
    {
      "pattern": "config/ui/dashboard",
      "roles": "internal/role/openidm-authorized",
      "methods": "read",
      "actions": "*"
    },
    {
      "pattern": "info/features",
      "roles": "*",
      "methods": "query",
      "actions": "*"
    },
    {
      "pattern": "privilege",
      "roles": "*",
      "methods": "action",
      "actions": "listPrivileges"
    },
    {
      "pattern": "privilege/*",
      "roles": "*",
      "methods": "read",
      "actions": "*"
    },
    {
      "pattern": "selfservice/registration",
      "roles": "*",
      "methods": "read,action",
      "actions": "submitRequirements",
      "customAuthz": "checkIfAnyFeatureEnabled('registration')"
    },
    {
      "pattern": "selfservice/socialUserClaim",
      "roles": "*",
      "methods": "read,action",
      "actions": "submitRequirements",
      "customAuthz": "checkIfAnyFeatureEnabled('registration')"
    },
    {
      "pattern": "selfservice/reset",
      "roles": "*",
      "methods": "read,action",
      "actions": "submitRequirements",
      "customAuthz": "checkIfAnyFeatureEnabled('passwordReset')"
    },
    {
      "pattern": "selfservice/username",
      "roles": "*",
      "methods": "read,action",
      "actions": "submitRequirements",
      "customAuthz": "checkIfAnyFeatureEnabled('retrieveUsername')"
    },
    {
      "pattern": "selfservice/profile",
      "roles": "*",
      "methods": "read,action",
      "actions": "submitRequirements"
    },
    {
      "pattern": "selfservice/termsAndConditions",
      "roles": "*",
      "methods": "read,action",
      "actions": "submitRequirements"
    },
    {
      "pattern": "selfservice/kbaUpdate",
      "roles": "*",
      "methods": "read,action",
      "actions": "submitRequirements"
    },
    {
      "pattern": "policy/*",
      "roles": "*",
      "methods": "action",
      "actions": "validateObject",
      "customAuthz": "context.current.name === 'selfservice'"
    },
    {
      "pattern": "policy/selfservice/registration",
      "roles": "*",
      "methods": "action,read",
      "actions": "validateObject",
      "customAuthz": "checkIfAnyFeatureEnabled('registration')"
    },
    {
      "pattern": "policy/selfservice/reset",
      "roles": "*",
      "methods": "action,read",
      "actions": "validateObject",
      "customAuthz": "checkIfAnyFeatureEnabled('passwordReset')"
    },
    {
      "pattern": "selfservice/kba",
      "roles": "internal/role/openidm-authorized",
      "methods": "read",
      "actions": "*",
      "customAuthz": "checkIfAnyFeatureEnabled('kba')"
    },
    {
      "pattern": "managed/realm-name_user",
      "roles": "internal/role/openidm-reg",
      "methods": "create",
      "actions": "*",
      "customAuthz": "checkIfAnyFeatureEnabled('registration') && isSelfServiceRequest() && onlyEditableManagedObjectProperties('user', [])"
    },
    {
      "pattern": "managed/realm-name_user",
      "roles": "*",
      "methods": "query",
      "actions": "*",
      "customAuthz": "checkIfAnyFeatureEnabled(['registration', 'retrieveUsername', 'passwordReset']) && isSelfServiceRequest()"
    },
    {
      "pattern": "managed/realm-name_user/*",
      "roles": "*",
      "methods": "read",
      "actions": "*",
      "customAuthz": "checkIfAnyFeatureEnabled(['retrieveUsername', 'passwordReset']) && isSelfServiceRequest()"
    },
    {
      "pattern": "managed/realm-name_user/*",
      "roles": "*",
      "methods": "patch,action",
      "actions": "patch",
      "customAuthz": "(checkIfAnyFeatureEnabled(['registration', 'passwordReset']) || checkIfProgressiveProfileIsEnabled()) && isSelfServiceRequest() && onlyEditableManagedObjectProperties('user', [])"
    },
    {
      "pattern": "external/email",
      "roles": "*",
      "methods": "action",
      "actions": "send",
      "customAuthz": "checkIfAnyFeatureEnabled(['registration', 'retrieveUsername', 'passwordReset']) && isSelfServiceRequest()"
    },
    {
      "pattern": "schema/*",
      "roles": "internal/role/openidm-authorized",
      "methods": "read",
      "actions": "*"
    },
    {
      "pattern": "consent",
      "roles": "internal/role/openidm-authorized",
      "methods": "action,query",
      "actions": "*"
    },
    {
      "pattern": "*",
      "roles": "internal/role/openidm-admin",
      "methods": "*",
      "actions": "*",
      "excludePatterns": "repo,repo/*"
    },
    {
      "pattern": "system/*",
      "roles": "internal/role/openidm-admin",
      "methods": "create,read,update,delete,patch,query",
      "actions": ""
    },
    {
      "pattern": "system/*",
      "roles": "internal/role/openidm-admin",
      "methods": "script",
      "actions": "*"
    },
    {
      "pattern": "system/*",
      "roles": "internal/role/openidm-admin",
      "methods": "action",
      "actions": "test,testConfig,createconfiguration,liveSync,authenticate"
    },
    {
      "pattern": "repo",
      "roles": "internal/role/openidm-admin",
      "methods": "*",
      "actions": "*",
      "customAuthz": "disallowCommandAction()"
    },
    {
      "pattern": "repo/*",
      "roles": "internal/role/openidm-admin",
      "methods": "*",
      "actions": "*",
      "customAuthz": "disallowCommandAction()"
    },
    {
      "pattern": "repo/link",
      "roles": "internal/role/openidm-admin",
      "methods": "action",
      "actions": "command",
      "customAuthz": "request.additionalParameters.commandId === 'delete-mapping-links'"
    },
    {
      "pattern": "managed/*",
      "roles": "internal/role/platform-provisioning",
      "methods": "create,read,query,patch"
    },
    {
      "pattern": "internal/role/*",
      "roles": "internal/role/platform-provisioning",
      "methods": "read,query"
    },
    {
      "pattern": "profile/*",
      "roles": "internal/role/platform-provisioning",
      "methods": "create,read,action,update",
      "actions": "*"
    },
    {
      "pattern": "policy/*",
      "roles": "internal/role/platform-provisioning",
      "methods": "read,action",
      "actions": "*"
    },
    {
      "pattern": "schema/*",
      "roles": "internal/role/platform-provisioning",
      "methods": "read"
    },
    {
      "pattern": "consent",
      "roles": "internal/role/platform-provisioning",
      "methods": "action,query",
      "actions": "*"
    },
    {
      "pattern": "selfservice/kba",
      "roles": "internal/role/platform-provisioning",
      "methods": "read"
    },
    {
      "pattern": "selfservice/terms",
      "roles": "internal/role/platform-provisioning",
      "methods": "read"
    },
    {
      "pattern": "identityProviders",
      "roles": "internal/role/platform-provisioning",
      "methods": "read"
    },
    {
      "pattern": "external/email",
      "roles": "internal/role/platform-provisioning",
      "methods": "action",
      "actions": "sendTemplate"
    },
    {
      "pattern": "policy/*",
      "roles": "internal/role/openidm-authorized",
      "methods": "read,action",
      "actions": "*"
    },
    {
      "pattern": "config/ui/*",
      "roles": "internal/role/openidm-authorized",
      "methods": "read",
      "actions": "*"
    },
    {
      "pattern": "authentication",
      "roles": "internal/role/openidm-authorized",
      "methods": "action",
      "actions": "reauthenticate"
    },
    {
      "pattern": "*",
      "roles": "internal/role/openidm-authorized",
      "methods": "read,action,delete",
      "actions": "bind,unbind",
      "customAuthz": "ownDataOnly()"
    },
    {
      "pattern": "*",
      "roles": "internal/role/openidm-authorized",
      "methods": "update,patch,action",
      "actions": "patch",
      "customAuthz": "ownDataOnly() && onlyEditableManagedObjectProperties('user', []) && reauthIfProtectedAttributeChange()"
    },
    {
      "pattern": "selfservice/user/*",
      "roles": "internal/role/openidm-authorized",
      "methods": "patch,action",
      "actions": "patch",
      "customAuthz": "(request.resourcePath === 'selfservice/user/' + context.security.authorization.id) && onlyEditableManagedObjectProperties('user', [])"
    },
    {
      "pattern": "endpoint/getprocessesforuser",
      "roles": "internal/role/openidm-authorized",
      "methods": "read",
      "actions": "*"
    },
    {
      "pattern": "endpoint/gettasksview",
      "roles": "internal/role/openidm-authorized",
      "methods": "query",
      "actions": "*"
    },
    {
      "pattern": "workflow/taskinstance/*",
      "roles": "internal/role/openidm-authorized",
      "methods": "action",
      "actions": "complete",
      "customAuthz": "isMyTask()"
    },
    {
      "pattern": "workflow/taskinstance/*",
      "roles": "internal/role/openidm-authorized",
      "methods": "read,update",
      "actions": "*",
      "customAuthz": "canUpdateTask()"
    },
    {
      "pattern": "workflow/processinstance",
      "roles": "internal/role/openidm-authorized",
      "methods": "create",
      "actions": "*",
      "customAuthz": "isAllowedToStartProcess()"
    },
    {
      "pattern": "workflow/processdefinition/*",
      "roles": "internal/role/openidm-authorized",
      "methods": "*",
      "actions": "read",
      "customAuthz": "isOneOfMyWorkflows()"
    },
    {
      "pattern": "managed/realm-name_user",
      "roles": "internal/role/openidm-cert",
      "methods": "patch,action",
      "actions": "patch",
      "customAuthz": "isQueryOneOf({'managed/realm-name_user': ['for-userName']}) && restrictPatchToFields(['password'])"
    },
    {
      "pattern": "internal/usermeta/*",
      "roles": "internal/role/openidm-authorized",
      "methods": "read",
      "actions": "*",
      "customAuthz": "ownRelationship()"
    },
    {
      "pattern": "internal/notification/*",
      "roles": "internal/role/openidm-authorized",
      "methods": "read,delete",
      "actions": "*",
      "customAuthz": "ownRelationship()"
    },
    {
      "pattern": "managed/realm-name_user/*",
      "roles": "internal/role/openidm-authorized",
      "methods": "read,query",
      "actions": "*",
      "customAuthz": "ownRelationshipCollection(['idps','_meta','_notifications'])"
    },
    {
      "pattern": "notification",
      "roles": "internal/role/openidm-authorized",
      "methods": "action",
      "actions": "deleteNotificationsForTarget",
      "customAuthz": "request.additionalParameters.target === (context.security.authorization.component + '/' + context.security.authorization.id)"
    },
    {
      "pattern": "managed/*",
      "roles": "internal/role/openidm-authorized",
      "methods": "read",
      "actions": "*",
      "customAuthz": "ownIDP()"
    }
  ]
}
Replace the Access Configuration
curl \
--header "Authorization: Bearer <token>" \
--header "Content-type: application/json" \
--header "Accept-API-Version: resource=1.0"  \
--request PUT \
--data '{
  "_id": "access",
  "configs": complete-configuration} ]
}' \
"https://<tenant-env-fqdn>/openidm/config/access"
{
  "_id": "access",
  "configs": complete-configuration} ]
}

Grant internal authorization roles manually

Apart from the default roles that users get when they authenticate, you can grant internal authorization roles manually, over REST or using the IDM admin UI. This mechanism works in the same way as the granting of managed roles. For information about granting managed roles, refer to Grant Roles to a User. To grant an internal role manually through the IDM admin UI:

  1. From the navigation bar, click Manage > User, and click a user.

  2. From the Authorization Roles tab, click Add Authorization Roles.

  3. Select Internal Role as the Type, click in the Authorization Roles field to select from the list of defined Internal Roles, and click Add.

To manually grant an internal role over REST, add a reference to the internal role to the user’s authzRoles property. The following command adds the openidm-admin role to user bjensen (with ID 9dce06d4-2fc1-4830-a92b-bd35c2f6bcbb):

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--cacert ca-cert.pem \
--request PATCH \
--data '[
  {
    "operation": "add",
    "field": "/authzRoles/-",
    "value": {"_ref" : "internal/role/openidm-admin"}
  }
]' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/9dce06d4-2fc1-4830-a92b-bd35c2f6bcbb"
{
  "_id": "9dce06d4-2fc1-4830-a92b-bd35c2f6bcbb",
  "_rev": "0000000050c62938",
  "mail": "bjensen@example.com",
  "givenName": "Barbara",
  "sn": "Jensen",
  "description": "Created By CSV",
  "userName": "bjensen",
  "telephoneNumber": "1234567",
  "accountStatus": "active",
  "effectiveRoles": [],
  "effectiveAssignments": []
}

You can also grant internal roles dynamically using conditional role grants.

Because internal roles are not managed objects, you cannot manipulate them in the same way as managed roles. Therefore, you cannot add a user to an internal role, as you would to a managed role.

To add users directly to an internal role, add the users as values of the role’s authzMembers property. For example:

curl \
--header "Authorization: Bearer <token>" \
--header "Content-Type: application/json" \
--cacert ca-cert.pem \
--request POST \
--data '{"_ref":"managed/realm-name_user/bjensen"}' \
"https://<tenant-env-fqdn>/openidm/internal/role/3042798d-37fd-49aa-bae3-52598d2c8dc4/authzMembers?_action=create"

Delegated administration

Delegated administration lets you give fine-grained administrative access to specific users, based on a privilege mechanism.

Delegated administration is only available to Alpha realm users. For detailed information, refer to Alpha and Bravo realms → Delegated administration.

How privileges restrict administrative access

Privileges enable you to grant fine-grained administrative access to specific endpoints and objects. For example, you could allow help desk or support users to update the information of other user accounts, but not delete user accounts or change system configuration.

You can use privileges to delegate specific administrative capabilities to non-administrative users, without exposing the IDM admin UI to those users. If a user has been granted a privilege that lets them see a list of users and user information, for example, they can access this list directly through the End User UI.

A delegated administrator does not have access to the same REST API methods as a regular administrator. IDM does not allow REST API methods such as POST or DELETE to delegated administrators. To add or remove relationships, use the PATCH method. For examples, refer to Managed roles.

For more information on managing privileges using REST, refer to Privileges.

Determine access privileges

IDM determines what access a user has as follows:

  1. IDM checks the onRequest script specified in router.json . By default, this script calls router-authz.js .

  2. If access requirements are not satisfied, IDM then checks for any privileges associated with the user’s roles.

onResponse and onFailure scripts are supported when using privileges. onFailure scripts are called only if both the onRequest script and the privilege filter fail. onRequest, onResponse, and onFailure scripts are not required for the privilege mechanism.

Create privileges

Privileges are assigned to internal roles. A privilege specifies the following information:

  • The service path to which users with that internal role have access.

  • The methods and actions allowed on that service path.

  • The specific attributes of the objects at that service path, to which access is allowed.

You can use a query filter within a privilege so that the privilege applies to only a subset of managed objects.

The privileges property is an array, and can contain multiple privileges. Each privilege can contain:

accessFlags

A list of attributes within a managed object that you wish to give access to. Each attribute has two fields:

attribute

The name of the property you are granting access to.

readOnly (boolean)

Determines what level of access is allowed.

Attributes marked as "readOnly": true can be viewed but not edited. Attributes marked as "readOnly": false can be both viewed and edited. Attributes that are not listed in the accessFlags array cannot be viewed or edited.

  • Privileges are not automatically aware of changes to the managed object schema. If new properties are added, removed, or made mandatory, you must update any existing privileges to account for these changes. When a new property is added, it has a default permission level of NONE in existing privileges, including when the privilege is set to access all attributes.

  • IDM applies policy validation when creating or updating a privilege, to ensure that all required properties are writable when the CREATE permission is assigned. This validation does not run when schema changes are made,so you must verify that any existing privileges adhere to defined policies.

actions

A list of the specific actions allowed if the ACTION permission has been specified. Allowed actions must be explicitly listed.

description (optional)

A description of the privilege.

filter (optional)

This property lets you apply a static or dynamic query filter to the privilege, which can be used to limit the scope of what the privilege allows the user to access.

Example 1. Static Filter Example

To allow a delegated administrator to access information only about users for the stateProvince Washington, include a static filter such as:

filter : "stateProvince eq \"Washington\""
Example 2. Dynamic Filter Example

Dynamic filters insert values from the authenticated resource. To allow a delegated administrator to access information only about users in their own stateProvince, include a dynamic filter by wrapping the parameter in curly braces:

filter : "stateProvince eq \"{{stateProvince}}\""

Users with query filter privileges cannot edit the properties specified in the filter in ways that would cause the privilege to lose access to the object. For example, if a user with either of the preceding example privileges attempted to edit another user’s stateProvince field to anything not matching the query filter, the request would return a 403 Forbidden error.

Privilege filters are another layer of filter in addition to any other query filters you create. This means any output must satisfy all filters to be included.

name

The name of the privilege being created.

path

The path to the service you want to allow members of this privilege to access. For example, managed/realm-name_user.

permissions

A list of permissions this privilege allows for the given path. The following permissions are available:

VIEW

Allows reading and querying the path, such as viewing and querying managed users.

CREATE

Allows creation at the path, such as creating new managed users.

UPDATE

Allows updating or patching existing information, such as editing managed user details.

DELETE

Allows deletion, such as deleting users from managed/realm-name_user.

ACTION

Allows users to perform actions at the given path, such as custom scripted actions.

Actions that require additional filtering on the results of the action are not currently supported.

Add privileges using the Advanced Identity Cloud admin UI

Add privileges using REST

The following example creates a new support role with privileges that let members view, create, and update information about users, but not delete users:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--cacert ca-cert.pem \
--request PUT \
--data '{
  "name": "support",
  "description": "Support Role",
  "privileges": [ {
    "name": "support",
    "description": "Support access to user information.",
    "path": "managed/realm-name_user",
    "permissions": [
      "VIEW", "UPDATE", "CREATE"
    ],
    "actions": [],
    "filter": null,
    "accessFlags": [
      {
        "attribute" : "userName",
        "readOnly" : false
      },
      {
        "attribute" : "mail",
        "readOnly" : false
      },
      {
        "attribute" : "givenName",
        "readOnly" : false
      },
      {
        "attribute" : "sn",
        "readOnly" : false
      },
      {
        "attribute" : "accountStatus",
        "readOnly" : true
      }
    ]
  } ]
}' \
"https://<tenant-env-fqdn>/openidm/internal/role/support"
{
  "_id": "support",
  "_rev": "00000000bfbac2ed",
  "name": "support",
  "description": "Support Role",
  "temporalConstraints": [],
  "condition": null,
  "privileges": [
    {
      "name": "support",
      "description": "Support access to user information.",
      "path": "managed/realm-name_user",
      "permissions": [
        "VIEW",
        "UPDATE",
        "CREATE"
      ],
      "actions": [],
      "filter": null,
      "accessFlags": [
        {
          "attribute": "userName",
          "readOnly": false
        },
        {
          "attribute": "mail",
          "readOnly": false
        },
        {
          "attribute": "givenName",
          "readOnly": false
        },
        {
          "attribute": "sn",
          "readOnly": false
        },
        {
          "attribute": "accountStatus",
          "readOnly": true
        }
      ]
    }
  ]
}

Policies related to privileges

When creating privileges, IDM runs policies found in policy.json and policy.js, including the five policies used for validating privileges:

valid-accessFlags-object

Verifies that accessFlag objects are correctly formatted. Only two fields are permitted in an accessFlag object: readOnly, which must be a boolean; and attribute, which must be a string.

valid-array-items

Verifies that each item in an array contains the properties specified in policy.json, and that each of those properties satisfies any specific policies applied to it. By default, this is used to verify that each privilege contains name, path, accessFlags, actions, and permissions properties, and that the filter property is valid if included.

valid-permissions

Verifies that the permissions set on the privilege are all valid and can be achieved with the accessFlags that have been set. It checks:

  • CREATE permissions must have write access to all properties required to create a new object.

  • CREATE and UPDATE permissions must have write access to at least one property.

  • ACTION permissions must include a list of allowed actions, with at least one action included.

  • If any attributes have write access, then the privilege must also have either CREATE or UPDATE permission.

  • All permissions listed must be valid types of permission: VIEW, CREATE, UPDATE, ACTION, or DELETE. Also, no permissions are repeated.

valid-privilege-path

Verifies that the path specified in the privilege is a valid object with a schema for IDM to reference. Only objects with a schema (such as managed/realm-name_user) can have privileges applied to them.

valid-query-filter

Verifies the query filter used to filter privileges is valid.

Get privileges on a resource

To determine which privileges a user has on a service, you can query the privilege endpoint for a given resource path or object based on the user you are currently logged in as. For example, if a user is a member of the support role mentioned in the previous example, checking the user’s privileges for the managed/realm-name_user resource would look like this:

curl \
--header "Authorization: Bearer <token>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--cacert ca-cert.pem \
--request GET \
"https://<tenant-env-fqdn>/openidm/privilege/managed/realm-name_user"
{
  "VIEW": {
    "allowed": true,
    "properties": [
      "userName",
      "givenName",
      "sn",
      "mail",
      "accountStatus"
    ]
  },
  "CREATE": {
    "allowed": true,
    "properties": [
      "userName",
      "givenName",
      "sn",
      "mail"
    ]
  },
  "UPDATE": {
    "allowed": true,
    "properties": [
      "userName",
      "givenName",
      "sn",
      "mail"
    ]
  },
  "DELETE": {
    "allowed": false
  },
  "ACTION": {
    "allowed": false,
    "actions": []
  }
}

In the above example, accountStatus is listed as a property for VIEW, but not for CREATE or UPDATE, because the privilege sets this property to be read only. Since both CREATE and UPDATE need the ability to write to a property, setting readOnly to false applies to both permissions. If you need more granular control, split these permissions into two privileges.

In addition to checking privileges for a resource, it is also possible to check privileges for specific objects within a resource, such as managed/realm-name_user/scarter.

Create a delegated administrator

You can use the IDM REST API to create an internal/role with privileges that have object, array, and relationship type attribute access. You can then use that role as a delegated administrator to perform operations on those attributes.

If you want to experiment with delegated administrators in Postman, download and import this Postman collection.

Use the following example to create a delegated administrator:

Step 1. Create a Managed Role

To ensure a role object exists when roles are requested, you must create a managed role.

curl \
--header "Authorization: Bearer <token>" \
--header "Content-Type: application/json" \
--header "If-None-Match: *" \
--request PUT \
--data '{
  "name": "testManagedRole",
  "description": "a managed role for test"
}' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_role/testManagedRole"
{
  "_id": "testManagedRole",
  "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-181",
  "name": "testManagedRole",
  "description": "a managed role for test"
}
Step 2. Create a Manager User
curl \
--header "Authorization: Bearer <token>" \
--header "Content-Type: application/json" \
--request POST \
--data '{
  "userName": "psmith",
  "sn": "Smith",
  "givenName": "Patricia",
  "mail": "psmith@example.com",
  "telephoneNumber": "082082082",
  "password": "Passw0rd"
}' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/?_action=create"
{
  "_id": "9cae97b7-3bf3-4107-96d5-39ad153629db",
  "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1223",
  "userName": "psmith",
  "sn": "Smith",
  "givenName": "Patricia",
  "mail": "psmith@example.com",
  "telephoneNumber": "082082082",
  "accountStatus": "active",
  "effectiveRoles": [],
  "memberOfOrgIDs": [],
  "effectiveAssignments": []
}
Step 3. Create Additional Users

In this step, you’ll create two users with the following attributes:

  • preferences

  • manager

  • roles

curl \
--header "Authorization: Bearer <token>" \
--header "Content-Type: application/json" \
--request POST \
--data '{
  "userName": "scarter",
  "sn": "Carter",
  "givenName": "Steven",
  "mail": "scarter@example.com",
  "telephoneNumber": "082082082",
  "password": "Passw0rd",
  "preferences": {
    "updates": true,
    "marketing": false
  },
  "manager": {"_ref": "managed/realm-name_user/9cae97b7-3bf3-4107-96d5-39ad153629db"},
  "roles": [{"_ref": "managed/realm-name_role/testManagedRole"}]
}' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/?_action=create"
{
  "_id": "917bc052-ef39-4add-ae05-0a278e2de9c0",
  "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1238",
  "userName": "scarter",
  "sn": "Carter",
  "givenName": "Steven",
  "mail": "scarter@example.com",
  "telephoneNumber": "082082082",
  "preferences": {
    "updates": true,
    "marketing": false
  },
  "accountStatus": "active",
  "effectiveRoles": [
    {
      "_refResourceCollection": "managed/realm-name_role",
      "_refResourceId": "testManagedRole",
      "_ref": "managed/realm-name_role/testManagedRole"
    }
  ],
  "memberOfOrgIDs": [],
  "effectiveAssignments": []
}
curl \
--header "Authorization: Bearer <token>" \
--header "Content-Type: application/json" \
--request POST \
--data '{
  "userName": "jdoe",
  "sn": "Doe",
  "givenName": "John",
  "mail": "jdoe@example.com",
  "telephoneNumber": "082082082",
  "password": "Passw0rd",
  "preferences": {
    "updates": true,
    "marketing": false
  },
  "manager": {"_ref": "managed/realm-name_user/9cae97b7-3bf3-4107-96d5-39ad153629db"},
  "roles": [{"_ref": "managed/realm-name_role/testManagedRole"}]
}' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/?_action=create"
{
  "_id": "aca0042c-9f4c-4ad5-8cf7-aca0adeb3470",
  "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1267",
  "userName": "jdoe",
  "sn": "Doe",
  "givenName": "John",
  "mail": "jdoe@example.com",
  "telephoneNumber": "082082082",
  "preferences": {
    "updates": true,
    "marketing": false
  },
  "accountStatus": "active",
  "effectiveRoles": [
    {
      "_refResourceCollection": "managed/realm-name_role",
      "_refResourceId": "testManagedRole",
      "_ref": "managed/realm-name_role/testManagedRole"
    }
  ],
  "memberOfOrgIDs": [],
  "effectiveAssignments": []
}
Step 4. Create Another User

You will delegate an internal/role with privileges to this user in the next step:

curl \
--header "Authorization: Bearer <token>" \
--header "Content-Type: application/json" \
--request POST \
--data '{
  "userName": "bjensen",
  "sn": "Jensen",
  "givenName": "Barbara",
  "mail": "bjensen@example.com",
  "telephoneNumber": "082082082",
  "password": "Passw0rd"
}' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/?_action=create"
{
  "_id": "2d726b2a-3324-44b3-ba40-91b154d4f51e",
  "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1291",
  "userName": "bjensen",
  "sn": "Jensen",
  "givenName": "Barbara",
  "mail": "bjensen@example.com",
  "telephoneNumber": "082082082",
  "accountStatus": "active",
  "effectiveRoles": [],
  "memberOfOrgIDs": [],
  "effectiveAssignments": []
}
Step 5. Create an internal/role

This role will have the following privileges:

  • A managed/realm-name_user privilege with accessFlags attributes that are of types: “String” , “boolean” , and “number” ; but also for:

    • An object type that is not a relationship (preferences).

    • An object type that is a relationship (manager).

    • Array types that are relationships (roles, authzRoles, reports).

  • A managed/realm-name_role privilege for viewing details of the “roles” property of a managed user.

  • An internal/role privilege for viewing the details of the “authzRoles” property of a managed user.

You can populate the privilege filter field to apply a finer level of permissions for what a delegated administrator can see or do with certain objects. The filter field is omitted in this example to allow all.

For properties that are not relationships, such as preferences, you can’t specify finer-grained permissions. For example, you can’t set permissions on preferences/marketing.

curl \
--header "Authorization: Bearer <token>" \
--header "Content-Type: application/json" \
--header "If-None-Match: *" \
--request PUT \
--data '{
  "name": "internal_role_with_object_array_and_relationship_privileges",
  "description": "an internal role that has privileges for object & array types and relationships",
  "privileges": [
    {
      "name": "managed_user_privilege",
      "path": "managed/realm-name_user",
      "permissions": [
        "VIEW",
        "CREATE",
        "UPDATE",
        "DELETE"
      ],
      "actions": [],
      "accessFlags": [
        {
          "attribute": "userName",
          "readOnly": false
        },
        {
          "attribute": "password",
          "readOnly": false
        },
        {
          "attribute": "givenName",
          "readOnly": false
        },
        {
          "attribute": "sn",
          "readOnly": false
        },
        {
          "attribute": "mail",
          "readOnly": false
        },
        {
          "attribute": "description",
          "readOnly": false
        },
        {
          "attribute": "accountStatus",
          "readOnly": false
        },
        {
          "attribute": "telephoneNumber",
          "readOnly": false
        },
        {
          "attribute": "postalAddress",
          "readOnly": false
        },
        {
          "attribute": "city",
          "readOnly": false
        },
        {
          "attribute": "postalCode",
          "readOnly": false
        },
        {
          "attribute": "country",
          "readOnly": false
        },
        {
          "attribute": "stateProvince",
          "readOnly": false
        },
        {
          "attribute": "preferences",
          "readOnly": false
        },
        {
          "attribute": "roles",
          "readOnly": false
        },
        {
          "attribute": "manager",
          "readOnly": false
        },
        {
          "attribute": "authzRoles",
          "readOnly": false
        },
        {
          "attribute": "reports",
          "readOnly": false
        }
      ]
    },
    {
      "name": "managed_role_privilege",
      "path": "managed/realm-name_role",
      "permissions": [
        "VIEW"
      ],
      "actions": [],
      "accessFlags": [
        {
          "attribute": "name",
          "readOnly": true
        },
        {
          "attribute": "description",
          "readOnly": true
        }
      ]
    },
    {
      "name": "internal_role_privilege",
      "path": "internal/role",
      "permissions": [
        "VIEW"
      ],
      "actions": [],
      "accessFlags": [
        {
          "attribute": "name",
          "readOnly": true
        },
        {
          "attribute": "description",
          "readOnly": true
        },
        {
          "attribute": "authzMembers",
          "readOnly": true
        }
      ]
    }
  ]
}' \
"https://<tenant-env-fqdn>/openidm/internal/role/testInternalRole"
{
  "_id": "testInternalRole",
  "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-300",
  "name": "internal_role_with_object_array_and_relationship_privileges",
  "description": "an internal role that has privileges for object & array types and relationships",
  "temporalConstraints": [],
  "condition": null,
  "privileges": [
    {
      "name": "managed_user_privilege",
      "path": "managed/realm-name_user",
      "permissions": [
        "VIEW",
        "CREATE",
        "UPDATE",
        "DELETE"
      ],
      "actions": [],
      "accessFlags": [
        {
          "attribute": "userName",
          "readOnly": false
        },
        {
          "attribute": "password",
          "readOnly": false
        },
        {
          "attribute": "givenName",
          "readOnly": false
        },
        {
          "attribute": "sn",
          "readOnly": false
        },
        {
          "attribute": "mail",
          "readOnly": false
        },
        {
          "attribute": "description",
          "readOnly": false
        },
        {
          "attribute": "accountStatus",
          "readOnly": false
        },
        {
          "attribute": "telephoneNumber",
          "readOnly": false
        },
        {
          "attribute": "postalAddress",
          "readOnly": false
        },
        {
          "attribute": "city",
          "readOnly": false
        },
        {
          "attribute": "postalCode",
          "readOnly": false
        },
        {
          "attribute": "country",
          "readOnly": false
        },
        {
          "attribute": "stateProvince",
          "readOnly": false
        },
        {
          "attribute": "preferences",
          "readOnly": false
        },
        {
          "attribute": "roles",
          "readOnly": false
        },
        {
          "attribute": "manager",
          "readOnly": false
        },
        {
          "attribute": "authzRoles",
          "readOnly": false
        },
        {
          "attribute": "reports",
          "readOnly": false
        }
      ]
    },
    {
      "name": "managed_role_privilege",
      "path": "managed/realm-name_role",
      "permissions": [
        "VIEW"
      ],
      "actions": [],
      "accessFlags": [
        {
          "attribute": "name",
          "readOnly": true
        },
        {
          "attribute": "description",
          "readOnly": true
        }
      ]
    },
    {
      "name": "internal_role_privilege",
      "path": "internal/role",
      "permissions": [
        "VIEW"
      ],
      "actions": [],
      "accessFlags": [
        {
          "attribute": "name",
          "readOnly": true
        },
        {
          "attribute": "description",
          "readOnly": true
        },
        {
          "attribute": "authzMembers",
          "readOnly": true
        }
      ]
    }
  ]
}
Step 6. Create the Relationship Between User and internal/role

In this step, assign the internal/role from step 5 to the user created in step 4 by creating a relationship:

curl \
--header "Authorization: Bearer <token>" \
--header "Content-Type: application/json" \
--request POST \
--data '{
  "_ref": "managed/realm-name_user/2d726b2a-3324-44b3-ba40-91b154d4f51e",
  "_refProperties": {}
}' \
"https://<tenant-env-fqdn>/openidm/internal/role/testInternalRole/authzMembers?_action=create"
{
  "_id": "2e21f423-f934-4ed7-b6fd-9883b69d52d8",
  "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1304",
  "_ref": "managed/realm-name_user/2d726b2a-3324-44b3-ba40-91b154d4f51e",
  "_refResourceCollection": "managed/realm-name_user",
  "_refResourceId": "2d726b2a-3324-44b3-ba40-91b154d4f51e",
  "_refProperties": {
    "_id": "2e21f423-f934-4ed7-b6fd-9883b69d52d8",
    "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1304"
  }
}
Step 7. Perform Operations as a Delegated Administrator

You can now perform operations as a delegated administrator, such as:

Query All Users

The query results display all users' properties that are allowed by the privileges:

curl \
--header "X-OpenIDM-Username: bjensen" \
--header "X-OpenIDM-Password: Passw0rd" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user?_queryFilter=true&_pageSize=100&_fields=*,*_ref/*"
{
  "result": [
    {
      "_id": "9cae97b7-3bf3-4107-96d5-39ad153629db",
      "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1223",
      "userName": "psmith",
      "sn": "Smith",
      "givenName": "Patricia",
      "mail": "psmith@example.com",
      "telephoneNumber": "082082082",
      "accountStatus": "active",
      "reports": [
        {
          "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1267",
          "_id": "aca0042c-9f4c-4ad5-8cf7-aca0adeb3470",
          "userName": "jdoe",
          "sn": "Doe",
          "givenName": "John",
          "mail": "jdoe@example.com",
          "telephoneNumber": "082082082",
          "preferences": {
            "updates": true,
            "marketing": false
          },
          "accountStatus": "active",
          "_ref": "managed/realm-name_user/aca0042c-9f4c-4ad5-8cf7-aca0adeb3470",
          "_refResourceCollection": "managed/realm-name_user",
          "_refResourceId": "aca0042c-9f4c-4ad5-8cf7-aca0adeb3470",
          "_refProperties": {
            "_id": "e01a922b-a60d-46c2-b6bc-2b821c1580b4",
            "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1262"
          }
        },
        {
          "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1238",
          "_id": "917bc052-ef39-4add-ae05-0a278e2de9c0",
          "userName": "scarter",
          "sn": "Carter",
          "givenName": "Steven",
          "mail": "scarter@example.com",
          "telephoneNumber": "082082082",
          "preferences": {
            "updates": true,
            "marketing": false
          },
          "accountStatus": "active",
          "_ref": "managed/realm-name_user/917bc052-ef39-4add-ae05-0a278e2de9c0",
          "_refResourceCollection": "managed/realm-name_user",
          "_refResourceId": "917bc052-ef39-4add-ae05-0a278e2de9c0",
          "_refProperties": {
            "_id": "5bc2c633-8ae1-4ea2-adf6-8aa7ce5f8e70",
            "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1233"
          }
        }
      ],
      "manager": null,
      "roles": [],
      "authzRoles": []
    },
    {
      "_id": "917bc052-ef39-4add-ae05-0a278e2de9c0",
      "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1238",
      "userName": "scarter",
      "sn": "Carter",
      "givenName": "Steven",
      "mail": "scarter@example.com",
      "telephoneNumber": "082082082",
      "preferences": {
        "updates": true,
        "marketing": false
      },
      "accountStatus": "active",
      "reports": [],
      "manager": {
        "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1223",
        "_id": "9cae97b7-3bf3-4107-96d5-39ad153629db",
        "userName": "psmith",
        "sn": "Smith",
        "givenName": "Patricia",
        "mail": "psmith@example.com",
        "telephoneNumber": "082082082",
        "accountStatus": "active",
        "_ref": "managed/realm-name_user/9cae97b7-3bf3-4107-96d5-39ad153629db",
        "_refResourceCollection": "managed/realm-name_user",
        "_refResourceId": "9cae97b7-3bf3-4107-96d5-39ad153629db",
        "_refProperties": {
          "_id": "5bc2c633-8ae1-4ea2-adf6-8aa7ce5f8e70",
          "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1233"
        }
      },
      "roles": [
        {
          "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-181",
          "_id": "testManagedRole",
          "name": "testManagedRole",
          "description": "a managed role for test",
          "_ref": "managed/realm-name_role/testManagedRole",
          "_refResourceCollection": "managed/realm-name_role",
          "_refResourceId": "testManagedRole",
          "_refProperties": {
            "_id": "a33e2de0-83ff-481c-b8a7-8ffbc02d135c",
            "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1235"
          }
        }
      ],
      "authzRoles": []
    },
    {
      "_id": "aca0042c-9f4c-4ad5-8cf7-aca0adeb3470",
      "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1267",
      "userName": "jdoe",
      "sn": "Doe",
      "givenName": "John",
      "mail": "jdoe@example.com",
      "telephoneNumber": "082082082",
      "preferences": {
        "updates": true,
        "marketing": false
      },
      "accountStatus": "active",
      "reports": [],
      "manager": {
        "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1223",
        "_id": "9cae97b7-3bf3-4107-96d5-39ad153629db",
        "userName": "psmith",
        "sn": "Smith",
        "givenName": "Patricia",
        "mail": "psmith@example.com",
        "telephoneNumber": "082082082",
        "accountStatus": "active",
        "_ref": "managed/realm-name_user/9cae97b7-3bf3-4107-96d5-39ad153629db",
        "_refResourceCollection": "managed/realm-name_user",
        "_refResourceId": "9cae97b7-3bf3-4107-96d5-39ad153629db",
        "_refProperties": {
          "_id": "e01a922b-a60d-46c2-b6bc-2b821c1580b4",
          "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1262"
        }
      },
      "roles": [
        {
          "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-181",
          "_id": "testManagedRole",
          "name": "testManagedRole",
          "description": "a managed role for test",
          "_ref": "managed/realm-name_role/testManagedRole",
          "_refResourceCollection": "managed/realm-name_role",
          "_refResourceId": "testManagedRole",
          "_refProperties": {
            "_id": "1528ab24-3ec3-4113-ac3f-26cc71a2d678",
            "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1264"
          }
        }
      ],
      "authzRoles": []
    },
    {
      "_id": "2d726b2a-3324-44b3-ba40-91b154d4f51e",
      "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1305",
      "userName": "bjensen",
      "sn": "Jensen",
      "givenName": "Barbara",
      "mail": "bjensen@example.com",
      "telephoneNumber": "082082082",
      "accountStatus": "active",
      "reports": [],
      "manager": null,
      "roles": [],
      "authzRoles": [
        {
          "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-300",
          "_id": "testInternalRole",
          "name": "internal_role_with_object_array_and_relationship_privileges",
          "description": "an internal role that has privileges for object & array types and relationships",
          "_ref": "internal/role/testInternalRole",
          "_refResourceCollection": "internal/role",
          "_refResourceId": "testInternalRole",
          "_refProperties": {
            "_id": "2e21f423-f934-4ed7-b6fd-9883b69d52d8",
            "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1304"
          }
        }
      ]
    }
  ],
  "resultCount": 4,
  "pagedResultsCookie": null,
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": -1
}
Read a Specified User’s Preferences Object
curl \
--header "X-OpenIDM-Username: bjensen" \
--header "X-OpenIDM-Password: Passw0rd" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/aca0042c-9f4c-4ad5-8cf7-aca0adeb3470?_fields=preferences"
{
  "_id": "aca0042c-9f4c-4ad5-8cf7-aca0adeb3470",
  "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1267",
  "preferences": {
    "updates": true,
    "marketing": false
  }
}
Query a Specified User’s Roles
curl \
--header "X-OpenIDM-Username: bjensen" \
--header "X-OpenIDM-Password: Passw0rd" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/917bc052-ef39-4add-ae05-0a278e2de9c0/roles?_queryFilter=true&_fields=*"
{
  "result": [
    {
      "_id": "a33e2de0-83ff-481c-b8a7-8ffbc02d135c",
      "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1235",
      "name": "testManagedRole",
      "description": "a managed role for test",
      "_refResourceCollection": "managed/realm-name_role",
      "_refResourceId": "testManagedRole",
      "_refResourceRev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-181",
      "_ref": "managed/realm-name_role/testManagedRole",
      "_refProperties": {
        "_id": "a33e2de0-83ff-481c-b8a7-8ffbc02d135c",
        "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1235"
      }
    }
  ],
  "resultCount": 1,
  "pagedResultsCookie": null,
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": -1
}
Read a Specified User’s Manager
curl \
--header "X-OpenIDM-Username: bjensen" \
--header "X-OpenIDM-Password: Passw0rd" \
--request GET \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/917bc052-ef39-4add-ae05-0a278e2de9c0/manager?_fields=*"
{
  "_id": "5bc2c633-8ae1-4ea2-adf6-8aa7ce5f8e70",
  "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1233",
  "userName": "psmith",
  "sn": "Smith",
  "givenName": "Patricia",
  "mail": "psmith@example.com",
  "telephoneNumber": "082082082",
  "accountStatus": "active",
  "_refResourceCollection": "managed/realm-name_user",
  "_refResourceId": "9cae97b7-3bf3-4107-96d5-39ad153629db",
  "_refResourceRev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1223",
  "_ref": "managed/realm-name_user/9cae97b7-3bf3-4107-96d5-39ad153629db",
  "_refProperties": {
    "_id": "5bc2c633-8ae1-4ea2-adf6-8aa7ce5f8e70",
    "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1233"
  }
}
Update a Specified User’s Reports
curl \
--header "X-OpenIDM-Username: bjensen" \
--header "X-OpenIDM-Password: Passw0rd" \
--header "Content-Type: application/json" \
--request PATCH \
--data '[ {
   "operation" : "replace",
   "field" : "reports",
   "value" : [{"_ref" : "managed/realm-name_user/917bc052-ef39-4add-ae05-0a278e2de9c0"}]
} ]' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/9cae97b7-3bf3-4107-96d5-39ad153629db"
{
  "_id": "9cae97b7-3bf3-4107-96d5-39ad153629db",
  "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1223",
  "userName": "psmith",
  "sn": "Smith",
  "givenName": "Patricia",
  "mail": "psmith@example.com",
  "telephoneNumber": "082082082",
  "accountStatus": "active"
}
Assign a Specified User’s Manager
curl \
--header "X-OpenIDM-Username: bjensen" \
--header "X-OpenIDM-Password: Passw0rd" \
--header "Content-Type: application/json" \
--request PATCH \
--data '[
  {
    "operation": "add",
    "field": "manager",
    "value": {"_ref" : "managed/realm-name_user/9cae97b7-3bf3-4107-96d5-39ad153629db"}
  }
]' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/aca0042c-9f4c-4ad5-8cf7-aca0adeb3470"
{
  "_id": "aca0042c-9f4c-4ad5-8cf7-aca0adeb3470",
  "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1517",
  "userName": "jdoe",
  "sn": "Doe",
  "givenName": "John",
  "mail": "jdoe@example.com",
  "telephoneNumber": "082082082",
  "preferences": {
    "updates": true,
    "marketing": false
  },
  "accountStatus": "active"
}
Remove a Specified User’s Manager
curl \
--header "X-OpenIDM-Username: bjensen" \
--header "X-OpenIDM-Password: Passw0rd" \
--header "Content-Type: application/json" \
--request PATCH \
--data '[
  {
     "operation": "remove",
     "field": "manager"
  }
]' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/aca0042c-9f4c-4ad5-8cf7-aca0adeb3470"
{
  "_id": "aca0042c-9f4c-4ad5-8cf7-aca0adeb3470",
  "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1545",
  "userName": "jdoe",
  "sn": "Doe",
  "givenName": "John",
  "mail": "jdoe@example.com",
  "telephoneNumber": "082082082",
  "preferences": {
    "updates": true,
    "marketing": false
  },
  "accountStatus": "active"
}
Update a Specified User’s Manager
curl \
--header "X-OpenIDM-Username: bjensen" \
--header "X-OpenIDM-Password: Passw0rd" \
--header "Content-Type: application/json" \
--request PATCH \
--data '[
  {
    "operation": "replace",
    "field": "manager",
    "value": {"_ref" : "managed/realm-name_user/aca0042c-9f4c-4ad5-8cf7-aca0adeb3470"}
  }
]' \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/917bc052-ef39-4add-ae05-0a278e2de9c0"
{
  "_id": "917bc052-ef39-4add-ae05-0a278e2de9c0",
  "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1565",
  "userName": "scarter",
  "sn": "Carter",
  "givenName": "Steven",
  "mail": "scarter@example.com",
  "telephoneNumber": "082082082",
  "preferences": {
    "updates": true,
    "marketing": false
  },
  "accountStatus": "active"
}
Delete a Specified User
curl \
--header "X-OpenIDM-Username: bjensen" \
--header "X-OpenIDM-Password: Passw0rd" \
--header "Content-Type: application/json" \
--request DELETE \
"https://<tenant-env-fqdn>/openidm/managed/realm-name_user/9cae97b7-3bf3-4107-96d5-39ad153629db"
{
  "_id": "9cae97b7-3bf3-4107-96d5-39ad153629db",
  "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-1223",
  "userName": "psmith",
  "sn": "Smith",
  "givenName": "Patricia",
  "mail": "psmith@example.com",
  "telephoneNumber": "082082082",
  "accountStatus": "active"
}
Create a User
  • Using POST:

    curl \
    --header "Content-Type: application/json" \
    --header "X-OpenIDM-Username: bjensen" \
    --header "X-OpenIDM-Password: Passw0rd" \
    --request POST \
    --data '{
      "userName": "psmith",
      "sn": "Smith",
      "givenName": "Patricia",
      "mail": "psmith@example.com",
      "telephoneNumber": "082082082",
      "password": "Passw0rd"
    }' \
    "https://<tenant-env-fqdn>/openidm/managed/realm-name_user"
    {
      "_id": "1a20930b-cf61-4b43-a730-9f73af9147cb",
      "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-571",
      "userName": "psmith",
      "sn": "Smith",
      "givenName": "Patricia",
      "mail": "psmith@example.com",
      "telephoneNumber": "082082082",
      "accountStatus": "active"
    }
  • Using PUT:

    curl \
    --header "Content-Type: application/json" \
    --header "X-OpenIDM-Username: bjensen" \
    --header "X-OpenIDM-Password: Passw0rd" \
    --header "If-None-Match: *" \
    --request PUT \
    --data '{
      "userName": "psmith",
      "sn": "Smith",
      "givenName": "Patricia",
      "mail": "psmith@example.com",
      "telephoneNumber": "082082082",
      "password": "Passw0rd"
    }' \
    "https://<tenant-env-fqdn>/openidm/managed/realm-name_user/psmith"
    {
      "_id": "psmith",
      "_rev": "200bc5d6-7cc1-4648-a854-3137f3d9c103-590",
      "userName": "psmith",
      "sn": "Smith",
      "givenName": "Patricia",
      "mail": "psmith@example.com",
      "telephoneNumber": "082082082",
      "accountStatus": "active"
    }

Delegated administration may not work as expected if _id is something other than a UUID.

For more examples, including working with filters, refer to the Postman collection.

All patches are done with a PATCH request. Delegated administrator operations do not currently support using POST actions for patch requests (POST _action=patch will not work).