Using the REST API in IDM/OpenIDM

This book provides information on using the REST API in IDM/OpenIDM and includes known issues (including solutions).


How do I create a new connector configuration via REST in IDM (All versions) and OpenIDM 4.x?

The purpose of this article is to provide information on creating a new connector configuration (provisioner file) via REST in IDM/OpenIDM. This article demonstrates creating an LDAP connector configuration, but you can use the same principles to create any connector configuration via the REST API.

Creating a connector configuration

To create an LDAP connector configuration:

  1. Output all the configuration details using the following curl command:
    $ curl -X GET -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -H "Content-Type: application/json" http://localhost:8080/openidm/config
    
    This command returns a full list of the different configuration IDs, with each one representing a subsystem or component in your IDM/OpenIDM instance. The following details are relevant for creating the LDAP connector:
    {
          "_id": "provisioner.openicf/ldap",
          "pid": "provisioner.openicf.7132376d-a10d-4ffd-8b34-633f6d44e985",
          "factoryPid": "provisioner.openicf"
    }
    
    
  2. Output details for the standard LDAP connector configuration using the following curl command with the _id value identified in step 1:
    $ curl -X GET -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -H "Content-Type: application/json" http://localhost:8080/openidm/config/provisioner.openicf/ldap
    
    This command returns the entire JSON configuration object for the LDAP connector:
    {
      "_id": "provisioner.openicf/ldap",
      "name": "ldap",
      "connectorRef": {
        "bundleName": "org.forgerock.openicf.connectors.ldap-connector",
        "bundleVersion": "[1.4.0.0,2.0.0.0)",
        "connectorName": "org.identityconnectors.ldap.LdapConnector"
      },
      "configurationProperties": {
        "host": "localhost",
        "port": 1389,
        "ssl": false,
        "principal": "cn=Directory Manager",
        "credentials": {
          "$crypto": {
            "value": {
              "iv": "l0X7XU5U5cICjOOoab7c+g==",
              "data": "56txTbcXYQDwPgL5R140Fg==",
              "cipher": "AES/CBC/PKCS5Padding",
              "key": "openidm-sym-default"
            },
            "type": "x-simple-encryption"
          }
        },
        "baseContexts": [
          "dc=example,dc=com"
        ],
        "baseContextsToSynchronize": [
          "dc=example,dc=com"
        ],
        "accountSearchFilter": null,
    [...]
    }
    
  3. Create a new LDAP connector configuration using the output returned in step 2 as a template. You will need to change at least the "_id", "name" and "credentials" plus customize any other details required for your new connector. You should enter the credentials as clear text. For example, to create a new connector configuration with an _id of ldapNew:
    $ curl -X PUT -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -H "Content-Type: application/json" -d '{ 
        "_id": "provisioner.openicf/ldapNew",
        "name": "ldapNew",
        "connectorRef": {
          "bundleName": "org.forgerock.openicf.connectors.ldap-connector",
          "bundleVersion": "[1.4.0.0,2.0.0.0)",
          "connectorName": "org.identityconnectors.ldap.LdapConnector"
        },
        "configurationProperties": {
          "host": "localhost",
          "port": 1389,
          "ssl": false,
          "principal": "cn=Directory Manager",
          "credentials": "Passw0rd",
          "baseContexts": [
            "dc=example,dc=com"
          ],
          "baseContextsToSynchronize": [
            "dc=example,dc=com"
          ],
          "accountSearchFilter": null,
    [...]
     }' http://localhost:8080/openidm/config/provisioner.openicf/ldapNew
    
    This command creates the connector configuration and the corresponding provisioner.openicf-ldapNew.json file in the /path/to/idm/conf directory.

See Also

How do I find the available parameters for inclusion in the provisioner configuration file for a connector in IDM (All versions) and OpenIDM 3.1.x, 4.x?

How do I configure the LDAP connector in IDM/OpenIDM (All versions) for LDAP failover?

How do I configure pooled connections for a connector in IDM/OpenIDM (All versions)?

Integrator's Guide › Connecting to External Resources › Configuring Connectors

Related Training

N/A

Related Issue Tracker IDs

N/A


How do I monitor LiveSync activity using REST in IDM/OpenIDM (All versions)?

The purpose of this article is to provide information on monitoring LiveSync activity in IDM/OpenIDM using the REST API. You can use this information to help you troubleshoot failed synchronization jobs.

Monitoring LiveSync activity

The following example demonstrates returning details for the last two LiveSync schedules and then following up on a specific schedule that failed. You will need to adjust these queries to fit your environment, but they should help you to monitor and resolve your own LiveSync schedule issues.

Note

Using the syncToken endpoint is not a reliable indicator of the health of a job because a failed LiveSync will not update the syncToken. 

Example

Return details of the last two schedule syncs using the following query, where you will need to update userId to match the LiveSync schedule:

$ curl -X GET -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" "http://localhost:8080/openidm/audit/access?_queryFilter=userId+sw+\"Scheduled\"&_fields=timestamp,transactionId,userId,response,request&_sortKeys=-timestamp&_pageSize=2"

Example response (where both LiveSync schedules failed):

"result": [
    {
      "_id": "d33e369d-7b82-4f4f-9a70-30d196aacddd-24438",
      "timestamp": "2017-11-14T00:15:45.500Z",
      "transactionId": "d33e369d-7b82-4f4f-9a70-30d196aacddd-24420",
      "userId": "Scheduled d4528b10-cb4f-4b2f-8c13-8deff9677d1b-Fri Nov 10 15:24:30 CDT 2017",
      "response": {
        "status": "FAILED",
        "statusCode": null,
        "elapsedTime": "75475",
        "elapsedTimeUnits": "MILLISECONDS"
      },
      "request": {
        "protocol": "CREST",
        "operation": "ScheduledTask",
        "detail": {
          "taskName": "scheduler-service-group.d4528b10-cb4f-4b2f-8c13-8deff9677d1b"
        }
      }
    },
    {
      "_id": "d33e369d-7b82-4f4f-9a70-30d196aacddd-24382",
      "timestamp": "2017-11-14T00:15:21.500Z",
      "transactionId": "d33e369d-7b82-4f4f-9a70-30d196aacddd-24379",
      "userId": "Scheduled d4528b10-cb4f-4b2f-8c13-8deff9677d1b-Fri Nov 10 15:19:00 CDT 2017",
      "response": {
        "status": "FAILED",
        "statusCode": null,
        "elapsedTime": "75517",
        "elapsedTimeUnits": "MILLISECONDS"
      },
      "request": {
        "protocol": "CREST",
        "operation": "ScheduledTask",
        "detail": {
          "taskName": "scheduler-service-group.d4528b10-cb4f-4b2f-8c13-8deff9677d1b"
        }
      }
    }
  ],
  "resultCount": 2,
  "pagedResultsCookie": "2",
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": -1
}

You can then find out more about a failed sync in the audit log using the details returned from the above call. For example, you could use one of the following calls with the corresponding transactionId, depending on what type of events you are interested in:

  • Access events:
    $ curl -X GET -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" "http://localhost:8080/openidm/audit/access/d33e369d-7b82-4f4f-9a70-30d196aacddd-24420"
    
    This call will indicate the status of the job (either a SUCCESS or FAILED) and report the latest timestamp. 
  • Activity events:
    $ curl -X GET -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" "http://localhost:8080/openidm/audit/activity?_queryFilter=userId+sw+\"Scheduled\"&_status+eq+\"FAILED\"&_transactionId+eq+\"d33e369d-7b82-4f4f-9a70-30d196aacddd-24420\"&_sortKeys=-timestamp"
    
    This call will query the activity logs to see if any failures were reported there.

See Also

How do I read and set the LiveSync syncToken using REST in IDM/OpenIDM (All versions)?

How do I query individual reconciliation synchronization failures using REST in IDM/OpenIDM (All versions)?

Integrator's Guide › Querying Audit Logs Over REST

Integrator's Guide ›Triggering LiveSync Over REST

Related Training

N/A

Related Issue Tracker IDs

N/A


How do I read and set the LiveSync syncToken using REST in IDM/OpenIDM (All versions)?

The purpose of this article is to provide information on reading and setting the LiveSync syncToken using the REST API in IDM/OpenIDM.

Reading and setting the syncToken

You only need to set the syncToken on one instance in the cluster as the syncToken is shared by all instances in a cluster:

  1. Query the _id of the sync data using the following REST call:
    $ curl -X GET -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -H "Content-Type: application/json" http://localhost:8080/openidm/repo/synchronisation/pooledSyncStage?_queryId=query-all-ids
    Example response:
    {
      "result": [
        {
          "_id": "SYSTEMLDAPACCOUNT"
        }
      ],
      "resultCount": 1,
      "pagedResultsCookie": null,
      "totalPagedResultsPolicy": "NONE",
      "totalPagedResults": -1,
      "remainingPagedResults": -1
    }
    
    
  2. Retrieve the last syncToken value using the following REST call, where SYSTEMLDAPACCOUNT is the _id value returned in step 1:
    $ curl -X GET -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -H "Content-Type: application/json" http://localhost:8080/openidm/repo/synchronisation/pooledSyncStage/SYSTEMLDAPACCOUNT
    Example response:
    {
      "_id": "SYSTEMLDAPACCOUNT",
      "_rev": "100",
      "connectorData": {
        "syncToken": 15000,
        "nativeType": "integer"
      }
    }
    
  3. Update the syncToken to the required value (15000 in this example) using the following REST call, where the other connectorData details are the ones returned in step 2 and _rev is set to null to update any revision since it will change every few seconds for small LiveSync intervals:
    $ curl -X PUT -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -H "Content-Type: application/json" -d '{ "connectorData": {  "syncToken": 15000, "nativeType": "integer" }, "_id": "SYSTEMLDAPACCOUNT", "_rev": "null" }' http://localhost:8080/openidm/repo/synchronisation/pooledSyncStage/SYSTEMLDAPACCOUNT
Note

See IDM/OpenIDM (All versions) LiveSync syncToken is out of sync with the DS/OpenDJ changelog number for information on resetting the syncToken to zero instead of to a specific value.

See Also

Best practice for LiveSync in IDM/OpenIDM (All versions) with multiple DS/OpenDJ instances

IDM/OpenIDM (All versions) LiveSync syncToken is out of sync with the DS/OpenDJ changelog number

Related Training

N/A

Related Issue Tracker IDs

N/A


How do I query individual reconciliation synchronization failures using REST in IDM/OpenIDM (All versions)?

The purpose of this article is to provide information on querying individual recon sync failures using REST in IDM/OpenIDM. This can be useful when troubleshooting why a reconciliation synchronization has failed.

Querying individual reconciliation synchronization failures

You can use the following REST request to query the details of individual synchronizations that have failed:

$ curl --cacert self-signed.crt -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -X GET 'https://localhost:8443/openidm/audit/recon' -G --data-urlencode '_queryFilter=status+eq+\"FAILURE\"'

Example response (with data removed to only show response summary with resultCount):

{
  "result": [
    {
        ...
    }
  ],
  "resultCount": 6,
  "pagedResultsCookie": null,
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": -1
}

Specific reconciliation IDs

If you want to query failed synchronization operations for a specific reconciliation, you can include the actual reconciliation ID. For example, you can use the following REST request:

$ curl --cacert self-signed.crt -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -X GET 'https://localhost:8443/openidm/audit/recon' -G --data-urlencode '_queryFilter=status+eq+\"FAILURE\"&_reconId+eq+\"208154c0-c97b-41d3-bebb-4cf22112c110-138\"'

Example response (which shows a resultCount of 1):

{
  "result": [
    {
      "_id": "208154c0-c97b-41d3-bebb-4cf22112c110-176",
      "_rev": "1",
      "status": "FAILURE",
      "reconId": "208154c0-c97b-41d3-bebb-4cf22112c110-138",
      "transactionId": "208154c0-c97b-41d3-bebb-4cf22112c110-138",
      "timestamp": "2016-08-17T12:50:54.447Z",
      "eventName": "recon",
      "userId": "openidm-admin",
      "action": "CREATE",
      "exception": "org.forgerock.openidm.sync.impl.SynchronizationException: Create rejected as Object with same ID already exists. Cannot index record managed_user{displayName:Morley Waghorne-2,description:null,givenName:Morley,mail:WaghornM@ns-mail3.com,telephoneNumber:+1 818 885-8439,sn:Waghorne,userName:WaghornM,ldapGroups:[0],accountStatus:active,effectiveRoles:[0],effectiveAssignments:[0],_openidm_id:68a9bac8-2994-4f1d-b388-100fc59e5d12}: found duplicated key 'WaghornM' in index 'managed_user!userName!Idx' previously assigned to the record #12:8\n\tat org.forgerock.openidm.sync.impl.ObjectMapping.createTargetObject(ObjectMapping.java:568)\n\tat org.forgerock.openidm.sync.impl.ObjectMapping.access$1400(ObjectMapping.java:69)\n\tat org.forgerock.openidm.sync.impl.ObjectMapping$SyncOperation.performAction(ObjectMapping.java:1776)\n\tat org.forgerock.openidm.sync.impl.ObjectMapping$SourceSyncOperation.sync(ObjectMapping.java:2164)\n\tat org.forgerock.openidm.sync.impl.ObjectMapping$2.recon(ObjectMapping.java:1174)\n\tat org.forgerock.openidm.sync.impl.ObjectMapping$ReconTask.call(ObjectMapping.java:1302)\n\tat org.forgerock.openidm.sync.impl.ObjectMapping$ReconTask.call(ObjectMapping.java:1275)\n\tat java.util.concurrent.FutureTask.run(FutureTask.java:262)\n\tat java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)\n\tat java.util.concurrent.FutureTask.run(FutureTask.java:262)\n\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)\n\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)\n\tat java.lang.Thread.run(Thread.java:745)\nCaused by: org.forgerock.json.resource.PreconditionFailedException: Create rejected as Object with same ID already exists. Cannot index record managed_user{displayName:Morley Waghorne-2,description:null,givenName:Morley,mail:WaghornM@ns-mail3.com,telephoneNumber:+1 818 885-8439,sn:Waghorne,userName:WaghornM,ldapGroups:[0],accountStatus:active,effectiveRoles:[0],effectiveAssignments:[0],_openidm_id:68a9bac8-2994-4f1d-b388-100fc59e5d12}: found duplicated key 'WaghornM' in index 'managed_user!userName!Idx' previously assigned to the record #12:8\n\tat org.forgerock.openidm.repo.orientdb.impl.OrientDBRepoService.create(OrientDBRepoService.java:295)\n\tat org.forgerock.openidm.repo.orientdb.impl.OrientDBRepoService.handleCreate(OrientDBRepoService.java:180)\n\tat org.forgerock.json.resource.Router.handleCreate(Router.java:255)\n\tat org.forgerock.json.resource.FilterChain$Cursor.handleCreate(FilterChain.java:69)\n\tat org.forgerock.json.resource.Filters$ConditionalFilter.filterCreate(Filters.java:62)\n\tat org.forgerock.json.resource.FilterChain$Cursor.handleCreate(FilterChain.java:67)\n\tat org.forgerock.json.resource.Filters$ConditionalFilter.filterCreate(Filters.java:62)\n\tat org.forgerock.json.resource.FilterChain$Cursor.handleCreate(FilterChain.java:67)\n\tat org.forgerock.json.resource.Filters$ConditionalFilter.filterCreate(Filters.java:62)\n\tat org.forgerock.json.resource.FilterChain$Cursor.handleCreate(FilterChain.java:67)\n\tat org.forgerock.openidm.audit.filter.AuditFilter.filterCreate(AuditFilter.java:110)\n\tat org.forgerock.json.resource.Filters$ConditionalFilter.filterCreate(Filters.java:60)\n\tat org.forgerock.json.resource.FilterChain$Cursor.handleCreate(FilterChain.java:67)\n\tat org.forgerock.openidm.servlet.internal.ServletConnectionFactory$5.filterCreate(ServletConnectionFactory.java:499)\n\tat org.forgerock.json.resource.FilterChain$Cursor.handleCreate(FilterChain.java:67)\n\tat org.forgerock.openidm.maintenance.impl.PassthroughFilter.filterCreate(PassthroughFilter.java:48)\n\tat org.forgerock.openidm.maintenance.impl.MaintenanceService.filterCreate(MaintenanceService.java:229)\n\tat org.forgerock.json.resource.Filters$ConditionalFilter.filterCreate(Filters.java:60)\n\tat org.forgerock.json.resource.FilterChain$Cursor.handleCreate(FilterChain.java:67)\n\tat org.forgerock.json.resource.FilterChain.handleCreate(FilterChain.java:213)\n\tat org.forgerock.json.resource.InternalConnection.createAsync(InternalConnection.java:44)\n\tat org.forgerock.json.resource.AbstractAsynchronousConnection.create(AbstractAsynchronousConnection.java:44)\n\tat org.forgerock.json.resource.AbstractConnectionWrapper.create(AbstractConnectionWrapper.java:96)\n\tat org.forgerock.openidm.servlet.internal.ServletConnectionFactory$1$1.create(ServletConnectionFactory.java:177)\n\tat org.forgerock.json.resource.AbstractConnectionWrapper.create(AbstractConnectionWrapper.java:96)\n\tat org.forgerock.openidm.managed.ManagedObjectSet.createInstance(ManagedObjectSet.java:650)\n\tat org.forgerock.json.resource.InterfaceCollectionHandler.handleCreate(InterfaceCollectionHandler.java:40)\n\tat org.forgerock.json.resource.Router.handleCreate(Router.java:255)\n\tat org.forgerock.openidm.managed.ManagedObjectService$ManagedObjectSetRequestHandler.handleCreate(ManagedObjectService.java:180)\n\tat org.forgerock.json.resource.Router.handleCreate(Router.java:255)\n\tat org.forgerock.openidm.managed.ManagedObjectService.handleCreate(ManagedObjectService.java:283)\n\tat org.forgerock.json.resource.Router.handleCreate(Router.java:255)\n\tat org.forgerock.json.resource.FilterChain$Cursor.handleCreate(FilterChain.java:69)\n\tat org.forgerock.json.resource.Filters$ConditionalFilter.filterCreate(Filters.java:62)\n\tat org.forgerock.json.resource.FilterChain$Cursor.handleCreate(FilterChain.java:67)\n\tat org.forgerock.openidm.servlet.internal.ScriptedFilter$2.apply(ScriptedFilter.java:96)\n\tat org.forgerock.openidm.servlet.internal.ScriptedFilter$2.apply(ScriptedFilter.java:93)\n\tat org.forgerock.util.promise.Promises$CompletedPromise.thenAsync(Promises.java:221)\n\tat org.forgerock.util.promise.Promises$CompletedPromise.thenAsync(Promises.java:205)\n\tat org.forgerock.openidm.servlet.internal.ScriptedFilter.filterResourceResponseRequest(ScriptedFilter.java:167)\n\tat org.forgerock.openidm.servlet.internal.ScriptedFilter.filterCreate(ScriptedFilter.java:92)\n\tat org.forgerock.json.resource.Filters$ConditionalFilter.filterCreate(Filters.java:60)\n\tat org.forgerock.json.resource.FilterChain$Cursor.handleCreate(FilterChain.java:67)\n\tat org.forgerock.json.resource.Filters$ConditionalFilter.filterCreate(Filters.java:62)\n\tat org.forgerock.json.resource.FilterChain$Cursor.handleCreate(FilterChain.java:67)\n\tat org.forgerock.openidm.audit.filter.AuditFilter.filterCreate(AuditFilter.java:110)\n\tat org.forgerock.json.resource.Filters$ConditionalFilter.filterCreate(Filters.java:60)\n\tat org.forgerock.json.resource.FilterChain$Cursor.handleCreate(FilterChain.java:67)\n\tat org.forgerock.openidm.servlet.internal.ServletConnectionFactory$5.filterCreate(ServletConnectionFactory.java:499)\n\tat org.forgerock.json.resource.FilterChain$Cursor.handleCreate(FilterChain.java:67)\n\tat org.forgerock.openidm.maintenance.impl.PassthroughFilter.filterCreate(PassthroughFilter.java:48)\n\tat org.forgerock.openidm.maintenance.impl.MaintenanceService.filterCreate(MaintenanceService.java:229)\n\tat org.forgerock.json.resource.Filters$ConditionalFilter.filterCreate(Filters.java:60)\n\tat org.forgerock.json.resource.FilterChain$Cursor.handleCreate(FilterChain.java:67)\n\tat org.forgerock.json.resource.FilterChain.handleCreate(FilterChain.java:213)\n\tat org.forgerock.json.resource.InternalConnection.createAsync(InternalConnection.java:44)\n\tat org.forgerock.json.resource.AbstractAsynchronousConnection.create(AbstractAsynchronousConnection.java:44)\n\tat org.forgerock.json.resource.AbstractConnectionWrapper.create(AbstractConnectionWrapper.java:96)\n\tat org.forgerock.openidm.servlet.internal.ServletConnectionFactory$1$1.create(ServletConnectionFactory.java:177)\n\tat org.forgerock.json.resource.AbstractConnectionWrapper.create(AbstractConnectionWrapper.java:96)\n\tat org.forgerock.openidm.sync.impl.ObjectMapping.createTargetObject(ObjectMapping.java:561)\n\t... 12 more\nCaused by: com.orientechnologies.orient.core.storage.ORecordDuplicatedException: Cannot index record managed_user{displayName:Morley Waghorne-2,description:null,givenName:Morley,mail:WaghornM@ns-mail3.com,telephoneNumber:+1 818 885-8439,sn:Waghorne,userName:WaghornM,ldapGroups:[0],accountStatus:active,effectiveRoles:[0],effectiveAssignments:[0],_openidm_id:68a9bac8-2994-4f1d-b388-100fc59e5d12}: found duplicated key 'WaghornM' in index 'managed_user!userName!Idx' previously assigned to the record #12:8 RID=#12:8\n\tat com.orientechnologies.orient.core.index.OIndexTxAwareOneValue.checkEntry(OIndexTxAwareOneValue.java:52)\n\tat com.orientechnologies.orient.core.index.OClassIndexManager.checkIndexedPropertiesOnCreation(OClassIndexManager.java:517)\n\tat com.orientechnologies.orient.core.index.OClassIndexManager.checkIndexes(OClassIndexManager.java:495)\n\tat com.orientechnologies.orient.core.index.OClassIndexManager.onRecordBeforeCreate(OClassIndexManager.java:61)\n\tat com.orientechnologies.orient.core.hook.ODocumentHookAbstract.onTrigger(ODocumentHookAbstract.java:237)\n\tat com.orientechnologies.orient.core.db.record.ODatabaseRecordAbstract.callbackHooks(ODatabaseRecordAbstract.java:1466)\n\tat com.orientechnologies.orient.core.db.record.ODatabaseRecordAbstract.executeSaveRecord(ODatabaseRecordAbstract.java:1103)\n\tat com.orientechnologies.orient.core.tx.OTransactionNoTx.saveRecord(OTransactionNoTx.java:84)\n\tat com.orientechnologies.orient.core.db.record.ODatabaseRecordTx.save(ODatabaseRecordTx.java:322)\n\tat com.orientechnologies.orient.core.db.record.ODatabaseRecordTx.save(ODatabaseRecordTx.java:40)\n\tat com.orientechnologies.orient.core.record.ORecordAbstract.save(ORecordAbstract.java:335)\n\tat com.orientechnologies.orient.core.record.impl.ODocument.save(ODocument.java:1439)\n\tat com.orientechnologies.orient.core.record.impl.ODocument.save(ODocument.java:1428)\n\tat com.orientechnologies.orient.core.record.impl.ODocument.save(ODocument.java:1417)\n\tat org.forgerock.openidm.repo.orientdb.impl.OrientDBRepoService.create(OrientDBRepoService.java:287)\n\t... 72 more\n",
      "linkQualifier": "default",
      "mapping": "systemLdapAccounts_managedUser",
      "message": "Create rejected as Object with same ID already exists. Cannot index record managed_user{displayName:Morley Waghorne-2,description:null,givenName:Morley,mail:WaghornM@ns-mail3.com,telephoneNumber:+1 818 885-8439,sn:Waghorne,userName:WaghornM,ldapGroups:[0],accountStatus:active,effectiveRoles:[0],effectiveAssignments:[0],_openidm_id:68a9bac8-2994-4f1d-b388-100fc59e5d12}: found duplicated key 'WaghornM' in index 'managed_user!userName!Idx' previously assigned to the record #12:8. Root cause: Cannot index record managed_user{displayName:Morley Waghorne-2,description:null,givenName:Morley,mail:WaghornM@ns-mail3.com,telephoneNumber:+1 818 885-8439,sn:Waghorne,userName:WaghornM,ldapGroups:[0],accountStatus:active,effectiveRoles:[0],effectiveAssignments:[0],_openidm_id:68a9bac8-2994-4f1d-b388-100fc59e5d12}: found duplicated key 'WaghornM' in index 'managed_user!userName!Idx' previously assigned to the record #12:8",
      "messageDetail": {
        "code": 412,
        "reason": "Precondition Failed",
        "message": "Create rejected as Object with same ID already exists. Cannot index record managed_user{displayName:Morley Waghorne-2,description:null,givenName:Morley,mail:WaghornM@ns-mail3.com,telephoneNumber:+1 818 885-8439,sn:Waghorne,userName:WaghornM,ldapGroups:[0],accountStatus:active,effectiveRoles:[0],effectiveAssignments:[0],_openidm_id:68a9bac8-2994-4f1d-b388-100fc59e5d12}: found duplicated key 'WaghornM' in index 'managed_user!userName!Idx' previously assigned to the record #12:8"
      },
      "situation": "ABSENT",
      "sourceObjectId": "system/ldap/account/cn=Morley Waghorne-2,ou=People,dc=example,dc=com",
      "targetObjectId": "managed/user/null",
      "reconciling": "source",
      "ambiguousTargetObjectIds": "",
      "entryType": "entry"
    }
  ],
  "resultCount": 1,
  "pagedResultsCookie": null,
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": -1
} 

See Also

Policy validation failed error when running reconciliation or using a workflow to set or update attributes to null in IDM (All versions) and OpenIDM 4.5

How do I identify reconciliation performance issues in IDM/OpenIDM (All versions)?

Integrator's Guide › REST API Reference › Accessing Log Entries Over REST

Integrator's Guide › Triggering LiveSync Over REST

Related Training

N/A

Related Issue Tracker IDs

N/A


How do I create a queryFilter for an audit field in IDM/OpenIDM (All versions)?

The purpose of this article is to provide information on writing a queryFilter for an audit field record in IDM/OpenIDM.

Creating a queryFilter

You can create a queryFilter for an audit field record to return activity for a specific object. If you look at the type of audit entries you want to query, you should be able to create a queryFilter accordingly. See Integrator's Guide › Accessing Data Objects › Constructing Queries for further information on creating queryFilter queries.

Example

You can use a curl command such as the following, where the double quotes have been escaped using backslashes:

$ curl -X GET -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -H "Content-Type: application/json" http://localhost:8080/idm/audit/activity?_queryFilter=/after+co+'\"name\":\"Employee\"'"

If you use a REST client such as Postman, you do not need to escape the double quotes, for example:

GET http://localhost:8080/idm/audit/activity?_queryFilter=/after+co+'"name":"Employee"'

These commands will give a response such as the following:

{
      "result": [
      {
            "_id": "ddacdf46-d2bf-45c3-ab62-ea55fe4afa38-59",
            "timestamp": "2016-03-17T15:32:01.292Z",
            "eventName": "activity",
            "transactionId": "ddacdf46-d2bf-45c3-ab62-ea55fe4afa38-52",
            "userId": "openidm-admin",
            "trackingIds": null,
            "runAs": "openidm-admin",
            "objectId": "managed/role/Employee",
            "operation": "CREATE",
            "before": null,
            "after": "{\"name\":\"Employee\",\"description\":\"Role assigned to workers on the payroll.\",\"_id\":\"Employee\",\"_rev\":\"0\"}",
            "changedFields": [],
            "revision": "0",
            "passwordChanged": "false",
            "message": "create",
            "status": "SUCCESS"
          },
      ],
      "resultCount": 1,
      "pagedResultsCookie": null,
      "totalPagedResultsPolicy": "NONE",
      "totalPagedResults": -1,
      "remainingPagedResults": -1
 }

See Also

FAQ: REST API in IDM/OpenIDM

Using the REST API in IDM/OpenIDM

Integrator's Guide › Querying Audit Logs Over REST

Integrator's Guide › Logging Audit Information

Integrator's Guide › Accessing Data Objects › Constructing Queries

Related Training

N/A

Related Issue Tracker IDs

N/A


How do I search managed user objects for attributes stored in arrays in IDM/OpenIDM (All versions)?

The purpose of this article is to provide information on searching managed user objects for attributes that are stored in arrays in IDM/OpenIDM. Attributes stored in arrays are not searchable by default.

Overview

Predefined queries for generic mappings were updated in IDM 6 for improved relationship performance as noted in the Release Notes › Important Changes to Existing Functionality (Changes to predefined queries).

This article provides examples to demonstrate making the attributes stored within the regions array searchable, where the attribute values are North, East, South and West. By doing this, you can then search for users who belong to a specific region. The examples are version specific because of the predefined query changes in IDM 6:

Searching managed user objects for attributes stored in arrays (IDM 6 and later)

To allow searches for attributes stored in arrays:

  1. Edit the repo.jdbc.json file (located in the /path/to/idm/conf directory) and add a new query for your array:
    • Copy the for-username query:
      "queries" : {
              "genericTables" : {
                  [...]
                  "for-userName" : "SELECT obj.objectid, obj.rev, obj.fullobject FROM ${_dbSchema}.${_mainTable} obj INNER JOIN ${_dbSchema}.${_propTable} prop ON obj.id = prop.${_mainTable}_id INNER JOIN ${_dbSchema}.objecttypes objtype ON objtype.id = obj.objecttypes_id WHERE prop.propkey='/userName' AND prop.propvalue = ${uid} AND objtype.objecttype = ${_resource}",
                  [...]
                  ]
      
    • Paste this in and update it to refer to your regions array, for example:
      "queries" : {
              "genericTables" : {
                  [...]
                  "for-userName" : "SELECT obj.objectid, obj.rev, obj.fullobject FROM ${_dbSchema}.${_mainTable} obj INNER JOIN ${_dbSchema}.${_propTable} prop ON obj.id = prop.${_mainTable}_id INNER JOIN ${_dbSchema}.objecttypes objtype ON objtype.id = obj.objecttypes_id WHERE prop.propkey LIKE '/regions%' AND prop.propvalue = ${region} AND objtype.objecttype = ${_resource}",
                  [...]
                  ]
      
  2. Update the repo.jdbc.json file to add /regions as a searchable field under properties in the managed/user section:
                "managed/user" : {
                    "mainTable" : "managedobjects",
                    "propertiesTable" : "managedobjectproperties",
                    "searchableDefault" : false,
                    "properties" : {
                        "/userName" : {
                            "searchable" : true
                        },
                        [...]
                        "/regions" : {
                            "searchable" : true
                        },
                        [...]
                    } 
    
Note

You can set searchableDefault to true in the repo.jdbc.json file instead of setting the searchable property for individual attributes; however, this has an impact on performance and it is recommended that you only set the searchable property for the attributes that should be searchable.

  1. Restart the IDM instance.
  2. Run reconciliation or update a managed user with a value in the regions array to force the object to be re-written to the repository with the new searchable properties; this will cause the managedobjectproperties table to be updated.

Searching managed user objects

You can now perform a query on the attributes stored in the regions array using a REST call such as:

$ curl -X GET -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -H "Content-Type: application/json" http://localhost:8443/openidm/managed/user?_queryId=by-regions&region=West

Searching managed user objects for attributes stored in arrays (pre-IDM 6)

To allow searches for attributes stored in arrays:

  1. Edit the repo.jdbc.json file (located in the /path/to/idm/conf directory) and add a new query for your array:
    • Copy the for-username query:
      "queries" : {
              "genericTables" : {
                  [...]
                  "for-userName" : "SELECT fullobject FROM ${_dbSchema}.${_mainTable} obj INNER JOIN ${_dbSchema}.${_propTable} prop ON obj.id = prop.${_mainTable}_id INNER JOIN ${_dbSchema}.objecttypes objtype ON objtype.id = obj.objecttypes_id WHERE prop.propkey='/userName' AND prop.propvalue = ${uid} AND objtype.objecttype = ${_resource}",
                  [...]
                  ]
      
    • Paste this in and update it to refer to your regions array, for example:
      "queries" : {
              "genericTables" : {
                  [...]
                  "by-regions" : "SELECT fullobject FROM ${_dbSchema}.${_mainTable} obj INNER JOIN ${_dbSchema}.${_propTable} prop ON obj.id = prop.${_mainTable}_id INNER JOIN ${_dbSchema}.objecttypes objtype ON objtype.id = obj.objecttypes_id WHERE prop.propkey LIKE '/regions%' AND prop.propvalue = ${region} AND objtype.objecttype = ${_resource}",
                  [...]
                  ]
      
  2. Update the repo.jdbc.json file to add /regions as a searchable field under properties in the managed/user section:
                "managed/user" : {
                    "mainTable" : "managedobjects",
                    "propertiesTable" : "managedobjectproperties",
                    "searchableDefault" : false,
                    "properties" : {
                        "/userName" : {
                            "searchable" : true
                        },
                        [...]
                        "/regions" : {
                            "searchable" : true
                        },
                        [...]
                    } 
    
    
Note

You can set searchableDefault to true in the repo.jdbc.json file instead of setting the searchable property for individual attributes; however, this has an impact on performance and it is recommended that you only set the searchable property for the attributes that should be searchable.

  1. Restart the IDM/OpenIDM instance.
  2. Run reconciliation or update a managed user with a value in the regions array to force the object to be re-written to the repository with the new searchable properties; this will cause the managedobjectproperties table to be updated.

Searching managed user objects

You can now perform a query on the attributes stored in the regions array using a REST call such as:

$ curl -X GET -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -H "Content-Type: application/json" http://localhost:8443/openidm/managed/user?_queryId=by-regions&region=West

See Also

How do I maintain relationships for a managed user in IDM/OpenIDM (All versions) using REST Patch operations?

Using the REST API in IDM/OpenIDM

Integrator's Guide › Managing the Repository › Understanding the Database Table Configuration

Related Training

N/A

Related Issue Tracker IDs

OPENIDM-3155 (Enhance queryFilter "eq" operator to find items in an array)


How do I restrict the managed/user attributes that are returned via REST in IDM (All versions) and OpenIDM 4.x?

The purpose of this article is to provide information on restricting the managed/user attributes that are returned from a REST query based on the user making the request in IDM/OpenIDM. This means you can control the information contained in the response according to who the user is or what role they have.

Restricting the managed/user attributes returned via REST

You can restrict which managed/user attributes are returned by adding a router filter to the router.json file (located in the /path/to/idm/conf directory). You can do this based on either the role associated with a user or a specific user ID.

The following examples show a simple restriction, which prevents a single field being returned in the query response. You can, however, add as much conditional logic as you want to restrict fields and include multiple restricted fields providing it is valid JavaScript®. If you intend to include multiple constraints, you should consider including them in a file and just reference the file in the router.json file instead.

Role

The following example demonstrates what should be added to the router.json file to remove the description field from the response for users without the openidm-authorized role: 

        {
            "pattern" : "managed/user/.*",
            "onResponse" : {
                "type" : "text/javascript",
                "source" : "if (context.security.authorizationId.roles.indexOf(\"openidm-authorized\") === -1) { delete response.description; }"
            }
        },

This filter means that users with the openidm-authorized role will see the description field in their query response. Users who do not have this role will not see this attribute as it will be deleted.

User ID

The following example demonstrates what should be added to the router.json file to remove the description field from the response for the user jdoe:

        {
            "pattern" : "managed/user/.*",
            "onResponse" : {
                "type" : "text/javascript",
                "source" : "if (context.security.authenticationId === \"jdoe\") { delete response.description; }"
            }
        },

This filter means all other users will see the description field in the query response, but jdoe will not since it will be deleted from the response. 

Including a file

The following example demonstrates what should be added to the router.json file to reference a file:

        {
            "pattern" : "managed/user/.*",
            "onResponse" : {
                "type" : "text/javascript",
                "file" : "script/restrictAttributes.js"
            }
        },

Where the conditional logic to restrict fields is included in the restrictAttributes.js file.

See Also

How do I search managed user objects for attributes stored in arrays in IDM/OpenIDM (All versions)?

FAQ: Scripts in IDM/OpenIDM

FAQ: REST API in IDM/OpenIDM

Using the REST API in IDM/OpenIDM

Integrator's Guide › Router Service Reference

Integrator's Guide › Scripting Reference › Script Triggers Defined in router.json

Related Training

N/A

Related Issue Tracker IDs

OPENIDM-2314 (Script launched from router.json by onResponse hook is unable to update response data)


How do I maintain relationships for a managed user in IDM/OpenIDM (All versions) using REST Patch operations?

The purpose of this article is to provide information on maintaining relationships for a managed user in IDM/OpenIDM using REST Patch operations (add, replace and remove). This applies to all any-to-many relationships such as roles or members. In OpenIDM 4.0, it is necessary to use the Delete operation to remove relationships instead of Patch.

Adding relationships

You can add relationships to a managed user using the Patch operation as follows, depending on which version of IDM/OpenIDM you are using:

IDM / OpenIDM 4.x

If you want to add a relationship to the user's existing list of relationships, you can use a curl command such as the following (this example updates the members field):

$ curl -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -H "Content-Type: application/json" -X PATCH -d '[
    {
       "operation": "add",
       "field": "/members/-",
       "value": {"_ref" : "managed/user/14786a13-33c3-42d4-aadd-675b072339ee"}
    }
 ]' "http://localhost:8080/openidm/managed/role/employee"

If you want to replace the user's existing list of relationships with a new value, you would use a curl command such as the following (this example updates the roles field):

$ curl -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -H "Content-Type: application/json" -X PATCH -d '[
    {
       "operation": "replace",
       "field": "/roles",
       "value": [ {"_ref" : "managed/role/employee"} ]
    }
 ]' "http://localhost:8080/openidm/managed/user/jdoe"

The key differences between these curl commands are:

  • for appending, the field value is "/field/-" and the the array brackets [ ] are not needed for the value since the special hyphen construct is being used.
  • for replacing, the field value is "/field" and the array brackets [ ] are needed.

OpenIDM 3.x

If you want to add a relationship to the user's existing list of relationships, you can use a curl command such as the following (this example updates the roles field):

$ curl -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -H "Content-Type: application/json" -X PATCH -d '[
    {
       "operation": "add",
       "field": "/roles/-",
       "value": "managed/role/employee"
    }
 ]' "http://localhost:8080/openidm/managed/user/jdoe"

If you want to replace the user's existing list of relationships with a new value, you just need to remove the - from the field value, for example:

       "field": "/roles/",

Removing relationships

You can remove a relationship using the Patch operation as follows, depending on which version of IDM/OpenIDM you are using (these examples update the roles field):

IDM / OpenIDM 4.5

The following example removes the relationship from the array of relationships; you must include the entire relationship object in the value:

$ curl -H "Content-type: application/json" -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -X PATCH -d '[
    {
      "operation" : "remove",
      "field" : "/roles",
      "value" :     {
       "_ref": "managed/role/6bf4701a-7579-43c4-8bb4-7fd6cac552a1",
       "_refProperties": {
         "temporalConstraints": [],
         "_grantType": "",
         "_id": "14786a13-33c3-42d4-aadd-675b072339ee",
         "_rev": "1"
       }
     }
    }
  ]' "http://localhost:8080/openidm/managed/user/jdoe"

You can also use the Delete operation in IDM / OpenIDM 4.5 (with the addition of dynamic role grants and temporal constraints) as noted in Integrator's Guide › Managing Users, Groups, Roles and Relationships › Deleting a User's Roles.

OpenIDM 4.0

In OpenIDM 4.0, you need to use the Delete operation rather than Patch and include the reference ID (the ID of the relationship). The following example removes the employee role from user jdoe, where the relationship ID is: 14786a13-33c3-42d4-aadd-675b072339ee:

$ curl -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -X DELETE "http://localhost:8080/openidm/managed/user/jdoe/roles/14786a13-33c3-42d4-aadd-675b072339ee"
{
  "_ref": "managed/role/employee",
  "_refProperties": {
    "_id": "14786a13-33c3-42d4-aadd-675b072339ee",
    "_rev": "6"
  }
}

OpenIDM 3.x

The following example removes the employee role from user jdoe, whose _id is 2e78fd22-a7cb-4585-9570-5f649e8abd25:

$ curl --cacert self-signed.crt -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -H "Content-Type: application/json" -H "If-Match: *" -X PATCH -d '[
    {
        "operation": "remove",
        "field": "roles",
        "value": "managed/role/employee"

    }
]' "https://localhost:8443/openidm/managed/user/2e78fd22-a7cb-4585-9570-5f649e8abd25"

See Also

IDM 5 Integrator's Guide › Managing Users, Groups, Roles and Relationships

Integrator's Guide › REST API Reference › Managing Users Over REST

OpenIDM 4 Integrator's Guide › Managing Users, Groups, Roles and Relationships

Related Training

N/A

Related Issue Tracker IDs

OPENIDM-5446 (Remove a Managed Assignment from a Role does not get reflected on the target system)

OPENIDM-5460 (Clarify/correct section on removing a role from a user using REST)

OPENIDM-5573 (With /roles/-, the value should not be a list)


How do I remove elements of a string array using the REST Patch operation in IDM (All versions) and OpenIDM 4.x?

The purpose of this article is to provide information on removing elements of a string array using the REST Patch operation in IDM/OpenIDM. Alternatives using REST Delete operations are also given.

Removing elements of a string array

It is not possible to remove elements of a string array by relationship map. However, you can use one of the following approaches to remove elements instead:

Patch operations

For the following example managed user object:

{
    "_id": "f3796bd2-1ec5-4220-bb69-8be34a83de4c",
    "_rev": "10",
    "userName": "jdoe",
    "givenName": "Joe",
    "sn": "Doe",
    "mail": "jdoe@example.com",
    "accountStatus": "active",
    "groups": [
        "employee",
        "contractor"
    ],
    "authzRoles" : [
      {
         "_ref" : "repo/internal/role/openidm-admin"
      },
      {
         "_ref" : "repo/internal/role/openidm-authorized"
      }
   ]
}
  • You can remove an element by value; for example to remove employee from the groups array:
    $ curl -X PATCH -H 'Content-type:application/json' -k -u openidm-admin:openidm-admin -d '[{"operation":"remove","field":"/groups","value":"employee"}]' https://localhost:8443/openidm/managed/user/f3796bd2-1ec5-4220-bb69-8be34a83de4c
  • You can remove an element by the array index of the element; for example to remove the first value from the authzRoles array ("_ref" : "repo/internal/role/openidm-admin"):
    $ curl -X PATCH -H 'Content-type:application/json' -k -u openidm-admin:openidm-admin -d '[{"operation":"remove","field":"/authzRoles/0"}]' https://localhost:8443/openidm/managed/user/f3796bd2-1ec5-4220-bb69-8be34a83de4c
    

Delete operations

  • You can remove an element by the ID of the relationship, for example:
    $ curl -X DELETE -H 'Content-type:application/json' -k -u openidm-admin:openidm-admin https://localhost:8443/openidm/managed/user/f3796bd2-1ec5-4220-bb69-8be34a83de4c/authzRoles/eedb8c82-6041-4493-b877-266931ff4c76
    
  • You can remove an element by removing the managed user from the role by specifying the relationship reference (f81f6bec-8712-4fe6-a7f8-a767d57a2016 in the following example):
    $ curl -X DELETE -H 'Content-type:application/json' -k -u openidm-admin:openidm-admin https://localhost:8443/openidm/managed/role/059b3554-807d-454a-9b11-c3a7085c6c4c/members/f81f6bec-8712-4fe6-a7f8-a767d57a2016
Note

If you are attempting to remove elements from a managed object property, you must ensure the string array is correctly defined in the managed.json file (this is located in the /path/to/idm/conf directory). 

See Also

How do I maintain relationships for a managed user in IDM/OpenIDM (All versions) using REST Patch operations?

FAQ: REST API in IDM/OpenIDM

Using the REST API in IDM/OpenIDM

Integrator's Guide › Working With Managed Objects

Related Training

N/A

Related Issue Tracker IDs

OPENIDM-5736 (Can not remove an element of a relationship map by value)


How does the OIDC authorization flow work when IDM (All versions) is integrated with AM?

The purpose of this article is to provide information on the OIDC authorization flow used when IDM is integrated with AM. This flow is used when you want to protect an IDM endpoint (custom or standard) with AM and are using the OAUTH_CLIENT module (IDM 5.5 and later) or the OPENID_CONNECT module (IDM 5).

Overview

You must integrate IDM with AM as detailed in the documentation: Samples Guide › Integrating IDM With the ForgeRock Identity Platform if you want to use AM for authentication.

Once integrated, follow the authorization flow to obtain an OIDC token (instead of the AM session cookie) for access; the same concepts apply for standard and custom IDM endpoints. This article describes the OIDC authorization flow used to obtain the OIDC token that can then be passed to IDM in order to access the endpoint.

OIDC authorization flow

The following example demonstrates the OIDC authorization flow where the following example URLs are used:

  • IDM URL: idm.example.net:8081
  • AM URL: host1.example.com:8080

Example

  1. Send a request to IDM:
    $ curl -X POST -H 'Content-Type: application/json' -H 'X-OpenIDM-Username: anonymous' -H 'X-OpenIDM-Password: anonymous' -H 'X-OpenIDM-NoSession: true' -d '{
       "provider":"OPENAM",
       "landingPage":"http://idm.example.net:8081/#login/&oauthReturn=true&provider=OPENAM&gotoURL=%23"
    }' 'http://idm.example.net:8081/openidm/identityProviders?_action=getAuthRedirect'
    Example response; this includes a long token value which you should save for step 4:
    {"redirect":"http://host1.example.com:8080/openam/oauth2/authorize?nonce=74881rqrqjtw4cq7exjhzb9tjeo4vbc&response_type=code&client_id=openidm&redirect_uri=http://idm.example.net:8081/oauthReturn/&scope=openid&state=99iu3pclpz8ub9buogfp4geznl0ax5c","token":"ey...<long token>...cnF0"}
    
  2. Send the following request to authenticate to AM (note the AM username and password shown in bold):
    $ curl -X POST -H "Content-Type: application/json" -H "X-OpenAM-Username: demo" -H "X-OpenAM-Password: changeit" -H "Accept-API-Version: resource=2.0, protocol=1.0" 'http://host1.example.com:8080/openam/json/realms/root/authenticate'
    Example response:
    {"tokenId":"aXuK02gnIwq_2rJacbNqob_QWC8.*AAJTSQACMDEAAlNLABxZeU5DZGhPTm8yVlBBVEx5eW9DZWpIVzh6R0k9AAJTMQAA*","successUrl":"/openam/console","realm":"/"}
    
  3. Send the following request to AM to obtain an authorization token, ensuring you replace the nonce and state values with the ones returned in step 1, and the iPlanetDirectoryPro cookie (default AM/OpenAM session cookie name) with the token returned in step 2:
    $ curl -v -H 'Cookie: iPlanetDirectoryPro=aXuK02gnIwq_2rJacbNqob...JTMQAA*' 'http://host1.example.com:8080/openam/oauth2/authorize?nonce=74881rqrqjtw4cq7exjhzb9tjeo4vbc&response_type=code&client_id=openidm&redirect_uri=http%3A%2F%2Fidm.example.net%3A8081%2FoauthReturn%2F&scope=openid&state=99iu3pclpz8ub9buogfp4geznl0ax5c'
    Example response (note the Location header):
    < HTTP/1.1 302 Found 
    < X-Frame-Options: SAMEORIGIN 
    < Pragma: no-cache 
    < Cache-Control: no-store 
    < Date: Mon, 15 Jan 2018 16:00:25 GMT 
    < Accept-Ranges: bytes 
    < Location: http://idm.example.net:8081/oauthReturn/?code=3d69820b-452a-49a9-bf55-22c4c3c588ac&scope=openid&iss=http%3A%2F%2Fhost1.example.com%3A8080%2Fopenam%2Foauth2&state=99iu3pclpz8ub9buogfp4geznl0ax5c&client_id=openidm 
    < Server: Restlet-Framework/2.3.4 
    < Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept 
    < Content-Length: 0
    
  4. Send the following request to IDM, ensuring you set the X-OpenIDM-DataStoreToken header to the long token value returned in step 1, replace the code value with the one returned in step 3 and replace the state value with the one returned in step 1:
    $ curl -H 'Content-Type: application/json' -H 'X-OpenIDM-Username: anonymous' -H 'X-OpenIDM-Password: anonymous' -H 'X-OpenIDM-NoSession: true' -H 'X-OpenIDM-DataStoreToken: ey...<long token>...cnF0' -d '{
       "code":["3d69820b-452a-49a9-bf55-22c4c3c588ac"],
       "scope":["openid"],
       "iss":["http://host1.example.com:8080/openam/oauth2"],
       "state":["99iu3pclpz8ub9buogfp4geznl0ax5c"],
       "client_id":["openidm"]
    }' 'http://idm.example.net:8081/openidm/identityProviders?_action=handlePostAuth'
    Example response:
    {"landingPage":"http://idm.example.net:8081/#login/&oauthReturn=true&provider=OPENAM&gotoURL=%23","data":null,"token":"eyJ...<BIG JWT>...2hk"}
    
  5. Send the following request to IDM, ensuring you set the X-OpenIDM-DataStoreToken header to the JWT value returned in step 4:
    $ curl -H 'Content-Type: application/json' -H 'X-OpenIDM-OAuth-Login: true' -H 'X-OpenIDM-DataStoreToken:eyJ...<BIG JWT...2hk' -H 'Referer: http://idm.example.net:8081/' 'http://idm.example.net:8081/openidm/managed/user/b4acc4e1-365d-4684-85e1-09c27e26725b'
    Successful response:
    {"_id":"b4acc4e1-365d-4684-85e1-09c27e26725b","_rev":"00000000b775e5e0","displayName":"demo","givenName":"demo","mail":"demo@example.com","telephoneNumber":"12345","sn":"demo","userName":"demo","kbaInfo":[],"accountStatus":"active","lastChanged":{"date":"2017-12-18T12:44:58.269Z"},"effectiveRoles":[],"effectiveAssignments":[]}
    
    

See Also

How do I invoke the OpenIDM 3.1 and 4.x REST API when OpenIDM is protected by OpenAM?

Integrator's Guide › Supported Authentication Modules

Related Training

N/A

Related Issue Tracker IDs

OPENIDM-10455 (query and non-read operations not authorised for openidm-admin role when OAuth)

OPENIDM-10454 (Provide an endpoint to retrieve DataStoreToken in an OIDC integration)


How do I invoke the OpenIDM 3.1 and 4.x REST API when OpenIDM is protected by OpenAM?

The purpose of this article is to provide information on invoking the REST API when OpenIDM is protected by OpenAM using the OPENAM_SESSION authentication module. You can still use this authentication module in IDM 5.x in certain circumstances (in which case the advice in this article applies), but typically you should use the OAUTH_CLIENT module (IDM 5.5) or the OPENID_CONNECT module (IDM 5) instead. The OPENAM_SESSION authentication module is deprecated as of IDM 5.5.

Overview

In general, when OpenIDM is protected by OpenAM, an OpenIDM user should authenticate with credentials stored in the OpenAM's identity repository. The OpenAM servlet filter will intercept the authentication request and redirect the request to the OpenAM server. If the user's credentials match those in the OpenAM's repository, OpenAM will redirect the user back to OpenIDM.

Invoking the REST API via a browser

When a user is authenticated to OpenIDM via OpenAM, the user does not need to re-authenticate during a session when invoking the REST API providing the following is true:

  • The same browser is used to authenticate the user to OpenAM and make REST calls to OpenIDM.
  • The session is still valid.

In this scenario, OpenAM creates and maintains the session, and passes the browser cookie (with the authenticated user's credentials) to OpenIDM.

Invoking the REST API via curl

When using curl to invoke the REST API, you must explicitly pass the authenticated user's credentials as follows:

  1. Create policy rules in OpenAM to provide authenticated users with access to the OpenIDM REST endpoints in addition to the openidmui or selfservice endpoints required (depending on which version of OpenIDM you are using). For example:
    • OpenIDM 4.x:
      http://host1.example.com:8080/openidm/*
      http://host1.example.com:8080/openidm/*?*
      http://host1.example.com:8080/openidm
      http://host1.example.com:8080/selfservice/*
      http://host1.example.com:8080/selfservice/*?*
      http://host1.example.com:8080/selfservice
    • OpenIDM 3.1:
      http://host1.example.com:8080/openidm/*
      http://host1.example.com:8080/openidm/*?*
      http://host1.example.com:8080/openidm
      http://host1.example.com:8080/openidmui/*
      http://host1.example.com:8080/openidmui/*?*
      http://host1.example.com:8080/openidmui
  2. Restart both OpenAM and OpenIDM.
  3. Authenticate to OpenAM, for example:
    $ curl -X POST -H "X-OpenAM-Username: openidm-admin" -H "X-OpenAM-Password: openidm-admin" -H "Content-Type: application/json" http://host1.example.com:8080/openam/json/authenticate
    Example response:
    { "tokenId": "AQIC5wM2LY4SfcxUm6wdixPGaSrucHNIH7haV14vmdkrRsU.*AAJTSQACMDE.*", "successUrl": "/openam/console", "realm": "/" }
    
  4. Pass the authenticated user's token in the iPlanetDirectoryPro header (default OpenAM session cookie name), along with the header "X-Requested-With: XMLHttpRequest", when performing operations that require authentication. For example:
    $ curl -b "iPlanetDirectoryPro=AQIC5wM2LY4SfcxUm6wdixPGaSrucHNIH7haV14vmdkrRsU.*AAJTSQACMDE.*" -H "X-Requested-With: XMLHttpRequest" "http://host1.example.com:8080/openidm/managed/user?_queryId=query-all-ids"

See Also

How does the OIDC authorization flow work when IDM (All versions) is integrated with AM?

How do I correctly configure the OPENAM_SESSION authentication module in OpenIDM 4.5?

How does a user change their own password in IDM (All versions) and OpenIDM 4.x using the REST API?

How does a user change their own password in OpenIDM 3.x using the REST API?

OpenAM Developer's Guide › Developing Client Applications › Authentication & Logout

Related Training

N/A

Related Issue Tracker IDs

N/A


How do I initiate the password reset functionality in IDM (All versions) and OpenIDM 4.x via the REST API?

The purpose of this article is to provide information on initiating the password reset functionality in IDM/OpenIDM via the REST API. This article also includes the REST calls needed to reset the password if you do not want to use the UI to reset the password.

Initiating the password reset functionality

To initiate the password reset functionality via the REST API, you can send a POST request to the selfservice/reset endpoint and provide a queryFilter as input to locate the managed user within the repository. The parameters required in the body of the request are specific to your setup.

You can determine what parameters are required using your browser's developer tools:

  1. Access the IDM/OpenIDM Self-Service login page using your browser.
  2. Launch the Developer tools for your browser.
  3. Select the Network tab to trace communications between the browser and server.
  4. Walk through the Password Reset functionality in the browser; the Network trace will show exactly which request the UI is sending to the server, what HTTP Headers are being supplied and the content of the request body.

Refer to Integrator's Guide › Accessing Data Objects › Constructing Queries for further information on how the queryFilter should be constructed in your curl command.

Curl commands for the following examples are provided below:

  • Example 1 - Initiating the password reset process via REST. This relies on the user receiving an email and then resetting their password via the UI.
  • Example 2 - Performing the entire password reset process via REST.

Example 1 - Initiating the password reset process via REST

The following example demonstrates initiating a password reset where the Password Reset functionality has been configured to send an email to the user for verification:

  1. Use a curl command such as the following; this example is looking for a managed user who has the username jdoe:
    $ curl -X POST -H "Content-Type: application/json" -H "X-OpenIDM-Username: anonymous" -H "X-OpenIDM-Password: anonymous" -H "Accept-Language:en-US,en;q=0.8" -d '{"input":{"queryFilter":"userName eq \"jdoe\""}}' "https://idm.example.com:8443/openidm/selfservice/reset?_action=submitRequirements"
    Example response; an email will be sent to jdoe for verification:
    {
      "type": "emailValidation",
      "tag": "validateCode",
      "requirements": {
        "$schema": "http://json-schema.org/draft-04/schema#",
        "description": "Verify emailed code",
        "type": "object",
        "required": [
          "code"
        ],
        "properties": {
          "code": {
            "description": "Enter code emailed",
            "type": "string"
          }
        }
      },
      "token": "eyAidHlwIjogIkpXRSIsICJhbGciOiAiSFMyNTYiIH0....U0djycrxM5WFGEc"
    }
    

Example 2 - Performing the entire password reset process via REST

The following example demonstrates performing the entire password reset process via REST:

  1. Use a curl command such as the following to obtain the reset token; this example is looking for a managed user who has the username jdoe:
    $ curl -X POST -H "Content-Type: application/json" -H "X-OpenIDM-Username: anonymous" -H "X-OpenIDM-Password: anonymous" -H "Accept-Language:en-US,en;q=0.8" -d '{"input":{"queryFilter":"userName eq \"jdoe\""}}' "https://idm.example.com:8443/openidm/selfservice/reset?_action=submitRequirements"
    Example response:
    {
      "type": "kbaSecurityAnswerVerificationStage",
      "tag": "initial",
      "requirements": {
        "$schema": "http://json-schema.org/draft-04/schema#",
        "description": "Answer security questions",
        "type": "object",
        "required": [
          "answer1"
        ],
        "properties": {
          "answer1": {
            "systemQuestion": {
              "en": "What's your favorite color?"
            },
            "type": "string"
          }
        }
      },
      "token": "eyAidHlwIjogIkpXRSIsICJhbGciOiAiSFMyNTYiIH0....U0djycrxM5WFGEc"
    }
    
  2. Use a curl command such as the following to submit your answers to the security questions detailed in the above response along with the returned token:
    $ curl -X POST -H "Content-Type: application/json" -H "X-OpenIDM-Username: anonymous" -H "X-OpenIDM-Password: anonymous" -H "Accept-Language:en-US,en;q=0.8" -d '{"token":"eyAidHlwIjogIkpXRSIsICJhbGciOiAiSFMyNTYiIH0....U0djycrxM5WFGEc","input":{"answer1":"Blue"}}' "https://idm.example.com:8443/openidm/selfservice/reset?_action=submitRequirements"
    Example response:
    {
      "type": "resetStage",
      "tag": "initial",
      "requirements": {
          "$schema": "http://json-schema.org/draft-04/schema#",
          "description": "Reset password",
          "type": "object",
          "required": [
               "password"
          ],
          "properties": {
              "password": {
                  "description": "Password",
                  "type": "string"
              }
          }
      },
       "token": "eyAidHlwIjogIkpXRSIsICJhbGciOiAiSFMyNTYiIH0....U0djycrxM5WFGEc"
    }
    
  3. Use a curl command such as the following to provide your new password; this uses the token returned in step 1:
    $ curl -X POST -H "Content-Type: application/json" -H "X-OpenIDM-Username: anonymous" -H "X-OpenIDM-Password: anonymous" -H "Accept-Language:en-US,en;q=0.8" -d '{"token":"eyAidHlwIjogIkpXRSIsICJhbGciOiAiSFMyNTYiIH0....U0djycrxM5WFGEc","input":{"password":"newPassw0rd"}}' "https://idm.example.com:8443/openidm/selfservice/reset?_action=submitRequirements"
    Example response:
    {
        "type": "resetStage",
        "tag": "end",
        "status": {
            "success": true
        },
        "additions": {}
    }
    
Note

If email validation has been configured in this scenario, you will need to execute an additional REST call between steps 1 and 2 to submit the code from the validation email. This call will use the same format as the examples in steps 2 and 3, where the input value is in the format: {"code":"02a5c58a-5f20-45e1-9cf9-cad0d0b78cba"}.

See Also

Integrator's Guide › Web-Based User Interfaces › Customizing User Self-Service Screens

Related Training

N/A

Related Issue Tracker IDs

OPENIDM-7108 (Password Reset Token issued by one process cannot be validated by a different process)


How does a user change their own password in IDM (All versions) and OpenIDM 4.x using the REST API?

The purpose of this article is to provide information on how a user can change their own password in IDM/OpenIDM using the REST API. The method varies slightly if IDM/OpenIDM is protected by AM/OpenAM as the user must first authenticate before they can change their password.

Changing a user's own password

A user can either use a POST or PATCH request to change their own password:

POST

$ curl -X POST -H "Content-Type: application/json" -H "X-OpenIDM-Username: jdoe" -H "X-OpenIDM-Password: OldPassword" -H "X-OpenIDM-Reauth-Password:OldPassword" -H "X-HTTP-Method-Override: PATCH" -d '[{"operation":"replace","field":"password","value":"NewPassw0rd"}]' "http://localhost:8080/openidm/managed/user/jdoe"

PATCH

$ curl -X PATCH-H "Content-Type: application/json" -H "X-OpenIDM-Username: jdoe" -H "X-OpenIDM-Password: OldPassword" -H "X-OpenIDM-Reauth-Password:OldPassword" -d '[{"operation":"replace","field":"password","value":"NewPassw0rd"}]' "http://localhost:8080/openidm/managed/user/jdoe"

Changing a user's own password when IDM/OpenIDM is protected by AM/OpenAM

When a user changes their own password where IDM/OpenIDM is protected by AM/OpenAM, they must explicitly pass their authenticated credentials as follows:​

  1. Authenticate to AM/OpenAM. The URL to authenticate changes depending on which version you are using; you must use the actual AM/OpenAM server URL (not lb). For example: 
    • AM 5 and later:
      $ curl -X POST -H "X-OpenAM-Username: openidm-admin" -H "X-OpenAM-Password: openidm-admin" -H "Content-Type: application/json" http://host1.example.com:8080/openam/json/realms/root/authenticate
    • Pre-AM 5:
      $ curl -X POST -H "X-OpenAM-Username: openidm-admin" -H "X-OpenAM-Password: openidm-admin" -H "Content-Type: application/json" http://host1.example.com:8080/openam/json/authenticate
    This will return a tokenID, such as AQIC5wM2LY4SfcxUm6wdixPGaSrucHNIH7haV14vmdkrRsU.*AAJTSQACMDE.*
  2. Change your password, where the cookie header is set to iPlanetDirectoryPro (default AM/OpenAM session cookie name) and the value of the token returned when you authenticated. You must also include the header "X-Requested-With: XMLHttpRequest". You can either use a POST or PATCH request:
    • POST:
      $ curl -b "iPlanetDirectoryPro=AQIC5wM2LY4SfcxUm6wdixPGaSrucHNIH7haV14vmdkrRsU.*AAJTSQACMDE.*" -H "X-Requested-With: XMLHttpRequest" -H "Content-Type: application/json" -H "X-OpenIDM-Reauth-Password:OldPassword" -X POST -H "X-HTTP-Method-Override: PATCH" -d '[{"operation":"replace","field":"password","value":"NewPassw0rd"}]' "http://localhost:8080/openidm/managed/user/jdoe"
      
    • PATCH:
      $ curl -b "iPlanetDirectoryPro=AQIC5wM2LY4SfcxUm6wdixPGaSrucHNIH7haV14vmdkrRsU.*AAJTSQACMDE.*" -H "X-Requested-With: XMLHttpRequest" -H "Content-Type: application/json" -H "X-OpenIDM-Reauth-Password:OldPassword" -X PATCH -d '[{"operation":"replace","field":"password","value":"NewPassw0rd"}]' "http://localhost:8080/openidm/managed/user/jdoe"
      

See Also

How do I invoke the OpenIDM 3.1 and 4.x REST API when OpenIDM is protected by OpenAM?

How does a user change their own password in OpenIDM 3.x using the REST API?

Related Training

N/A

Related Issue Tracker IDs

N/A


How does a user change their own password in OpenIDM 3.x using the REST API?

The purpose of this article is to provide information on how a user can change their own password in OpenIDM 3.x using the REST API. The method varies slightly if OpenIDM is protected by OpenAM as the user must first authenticate before they can change their password.

Changing a user's own password

The following command can be used by a user to change their own password:

$ curl -H "Content-Type: application/json" -H "X-OpenIDM-Username: jdoe" -H "X-OpenIDM-Password: OldPassword" -H "X-OpenIDM-Reauth-Password:OldPassword" -X POST -d '[{"operation":"replace","field":"password","value":"NewPassw0rd"}]' "http://localhost:8080/openidm/managed/user/jdoe?_action=patch"

Changing a user's own password when OpenIDM is protected by OpenAM

When a user changes their own password where OpenIDM is protected by OpenAM, they must explicitly pass their authenticated credentials as follows:​

  1. Use curl to authenticate to OpenAM as described in OpenAM Developer's Guide › Developing Client Applications › Authentication & Logout. For example:
    $ curl -X POST -H "X-OpenAM-Username: jdoe" -H "X-OpenAM-Password: OldPassword" -H "Content-Type: application/json" http://openam.example.com:8080/openam/json/authenticate
    This will return a tokenID, such as AQIC5wM2LY4SfcxUm6wdixPGaSrucHNIH7haV14vmdkrRsU.*AAJTSQACMDE.*
  2. Change your password, including the tokenID as the cookie value and the header "X-Requested-With: XMLHttpRequest":
    $ curl -b "iPlanetDirectoryPro=AQIC5wM2LY4SfcxUm6wdixPGaSrucHNIH7haV14vmdkrRsU.*AAJTSQACMDE.*" -H "X-Requested-With: XMLHttpRequest" -H "Content-Type: application/json" -H "X-OpenIDM-Reauth-Password:OldPassword" -X POST -d '[{"operation":"replace","field":"password","value":"NewPassw0rd"}]' "http://localhost:8080/openidm/managed/user/jdoe?_action=patch"
    
Note

Some command line parameters, such as iPlanetDirectoryPro, are case-sensitive.

See Also

How do I invoke the OpenIDM 3.1 and 4.x REST API when OpenIDM is protected by OpenAM?

How does a user change their own password in IDM (All versions) and OpenIDM 4.x using the REST API?

OpenAM Developer's Guide › Developing Client Applications › Authentication & Logout

Related Training

N/A

Related Issue Tracker IDs

N/A


How do I construct a curl command to successfully send external email via the REST API in IDM/OpenIDM (All versions)?

The purpose of this article is to provide information on constructing a curl command to successfully send external email via the REST API in IDM/OpenIDM.

Sending external email

The basic format of the curl command for sending external email via the REST API is:

$ curl -H "Content-Type: application/json" -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -X POST 
-d '{"from":"sender@example.com", "to":"recipient@example.com", "subject":"Test Email", "body":"Test body text"}' "https://localhost:8080/openidm/external/email?_action=send"
Note

Due to the use of the POST --data option (-d), spaces are permitted in the subject and body parameters without the need for url encoding.

See Also

Integrator's Guide › Sending Email

Related Training

ForgeRock Identity Management Core Concepts (IDM-400)

Related Issue Tracker IDs

N/A


FAQ: REST API in IDM/OpenIDM

The purpose of this FAQ is to provide answers to commonly asked questions regarding the REST API in IDM/OpenIDM.

Frequently asked questions

Q. Can I do a negation query with the REST API?

A. Yes, you can using the boolean operator ! (NOT). Examples of queries that can be performed via REST (with the equivalent LDAP filter for comparison) are shown in Developer's Guide › Querying Resource Collections.

Q. How do I define the Content-Type header when using an external REST call?

A. IDM/OpenIDM sets the Content-Type header to application/json in external REST calls even if you specify a different header value. If you need this header to be anything other than application/json, you must use the contentType parameter in your external REST call.

For example, to specify your Content-Type as application/x-www-form-urlencoded in your external REST call:

$ curl -H "Content-Type: application/json" -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: password" -X POST -d '{ 
   "url": "https://host1.example.com:18080/openam/oauth2/access_token", 
   "method": "POST", 
   "detectResultFormat": false, 
   "body": "grant_type=client_credentials", 
   "authenticate" : {"type": "basic", "user" : "Test", "password" : "password"}, 
   "contentType" : "application/x-www-form-urlencoded"
}' "http://localhost:8080/openidm/external/rest?_action=call"

See 500-Internal server error when calling external REST endpoint from workflow in IDM/OpenIDM (All versions) for further information on this issue.

Q. How do I remove elements of a string array from a managed object by relationship map?

A. It is not possible to remove elements of a string array by relationship map. See How do I remove elements of a string array using the REST Patch operation in IDM (All versions) and OpenIDM 4.x? for further information on removing elements of a string array.

Q. Why does my search on a new attribute not return all the expected results?

A. When you add an attribute, you must make it searchable to ensure the expected results are returned. You can make it searchable as follows:

  1. Update the repo.jdbc.json file (located in the /path/to/idm/conf directory) to add /newAttribute as a searchable field:
    "properties" : {
                        [..]
                        "/newAttribute" : {
                            "searchable" : true
                        },
                        [..]
                    } 
    
    
  2. Restart the IDM/OpenIDM instance.
  3. Run reconciliation or update a managed user with a value in the newAttribute attribute to force the object to be re-written to the repository with the new searchable properties; this will cause the managedobjectproperties table to be updated.
Note

You can set searchableDefault to true in the repo.jdbc.json file instead of setting the searchable property for individual attributes; however, this has an impact on performance and it is recommended that you only set the searchable property for the attributes that need to be searchable.

Q. Why can't I search managed user objects for attributes stored in arrays?

A. Attributes stored in arrays are not searchable by default. You can make attributes stored in arrays searchable as detailed in How do I search managed user objects for attributes stored in arrays in IDM/OpenIDM (All versions)? 

Q. How do I ensure virtual attributes are returned when I query users in managed.json?

A. You can query a user object by specifying the user ID; this will return all attributes (including virtual), for example:

$ curl -X GET -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -H "Content-Type: application/json" http://localhost:8080/openidm/managed/user/44a86e3c-f509-48b6-91a7-0bfc4ea53b7d 

However, if you do a query using a queryFilter, virtual attributes are excluded from the result.

Q. How can I delete a user regardless of its revision, for example, there is a mismatch of revisions?

A. If there is a mismatch of revisions, you will see a response similar to:

{"error":412,"reason":"Precondition Required","message":"Delete rejected as current Object revision 8 is different than expected by caller 7, the object has changed since retrieval."}

To ensure the user is deleted, you can execute the REST call with the "If-Match: *" header, for example:

$ curl -X DELETE -H "If-Match: *" -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" http://localhost:8080/openidm/managed/user/jdoe

Q. Can I force a user to change their password in DS/OpenDJ via the IDM/OpenIDM REST API?

A. Yes you can. You can set the pwdReset attribute (set-password-is-reset) to true in the system/OpenDJ/account object. For example, you could use a REST call such as:

$ curl -X PUT -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -H "Content-Type: application/json" -d '{"pwdReset": "true"}' http://localhost:8080/​openidm/system/openDJ/account/316cb3e8-446e-4328-b4d7-2e55b863977b

The user will be forced to change their password when they next log in.

Note

pwdReset is an operational attribute; you should ensure an appropriate ACI exists for the account used by IDM/OpenIDM to bind to DS/OpenDJ.

If you are using OpenIDM 4.x or IDM, see How do I initiate the password reset functionality in IDM (All versions) and OpenIDM 4.x via the REST API? for a way of doing this within IDM/OpenIDM regardless of where your passwords are stored.

Q. Can I lock and unlock a user's account in DS/OpenDJ via the IDM/OpenIDM REST API?

A. Yes you can by setting the ds-pwp-account-disabled attribute to true (to lock the account) and false (to unlock the account) in the system/OpenDJ/account object.

You can use a REST call such as the following to lock a user's account:

$ curl -X PUT -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -H "Content-Type: application/json" -d '{"ds-pwp-account-disabled": "true"}' http://localhost:8080/​/openidm/system/openDJ/account/uid=jdoe,ou=people,dc=example,dc=com

Optionally, you can PATCH this change to the IDM/OpenIDM managed user and rely on your sync to update the DS/OpenDJ target.

Note

ds-pwp-account-disabled is an operational attribute; you should ensure an appropriate ACI exists for the account used by IDM/OpenIDM to bind to DS/OpenDJ.

Q. How can I find the available managed objectTypes via REST?

A. You can query the openidm/config/managed endpoint which reads managed.json, for example:

$ curl -X GET -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -H "Content-Type: application/json" http://localhost:8080/openidm/config/managed

And look for all the name attributes within the objects structure to identify all the available objectTypes.

Q. How do I delete a schedule via REST?

A. You can delete a schedule as follows depending on your version:

IDM 5 and later

  1. Query the _id of the schedule you want to delete using the following REST call:
    $ curl -X GET -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -H "Content-Type: application/json" http://localhost:8080/openidm/scheduler/job?_queryId=query-all-ids
    Example response:
    { 
      "result": [ 
        { 
          "_id": "910d2bc5-a04b-66f6-aa74-eb365e47b6d3" 
        } 
      ], 
      "resultCount": 1, 
      "pagedResultsCookie": null, 
      "totalPagedResultsPolicy": "NONE", 
      "totalPagedResults": -1, 
      "remainingPagedResults": -1 
    }
    
  2. Delete the schedule using the following REST call, where 910d2bc5-a04b-66f6-aa74-eb365e47b6d3 is the _id value returned in step 1:
    $ curl -X DELETE -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" "http://localhost:8080/openidm/scheduler/job/910d2bc5-a04b-66f6-aa74-eb365e47b6d3"

Pre-IDM 5

  1. Query the _id of the schedule you want to delete using the following REST call:
    $ curl -X GET -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -H "Content-Type: application/json" http://localhost:8080/openidm/scheduler?_queryId=query-all-ids
    Example response:
    { 
      "result": [ 
        { 
          "_id": "910d2bc5-a04b-66f6-aa74-eb365e47b6d3" 
        } 
      ], 
      "resultCount": 1, 
      "pagedResultsCookie": null, 
      "totalPagedResultsPolicy": "NONE", 
      "totalPagedResults": -1, 
      "remainingPagedResults": -1 
    }
    
  2. Delete the schedule using the following REST call, where 910d2bc5-a04b-66f6-aa74-eb365e47b6d3 is the _id value returned in step 1:
    $ curl -X DELETE -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" "http://localhost:8080/openidm/scheduler/910d2bc5-a04b-66f6-aa74-eb365e47b6d3"

See Also

Using the REST API in IDM/OpenIDM

Integrator's Guide › Configuring the Server Over REST

Integrator's Guide › Accessing External REST Services

Integrator's Guide › REST API Reference

Related Training

ForgeRock Identity Management Core Concepts (IDM-400)


Known issues in OpenIDM


500-Internal server error when calling external REST endpoint from workflow in IDM/OpenIDM (All versions)

The purpose of this article is to provide assistance if your call to an external REST endpoint from a workflow in IDM/OpenIDM fails with a 500-Internal server error, where the associated Content-Type is 'application/x-www-form-urlencoded'.

Symptoms

The REST call fails with the following error:

500-Internal server error

When the IDM/OpenIDM logging is set to FINEST, you can see that the action is invoked with the correct Content-Type; for example, your logs will show something similar to:

Oct 10, 2014 5:02:36 PM org.forgerock.openidm.external.rest.RestService actionInstance
FINE: Action invoked on call with { "content": { "authenticate": { "type": "basic", "user": "admin", "password": "Passw0rd" }, "headers": { "Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json" }, "body": "grant_type=client_credentials", "method": "POST", "url": "https://host1.example.com:8080/openam/oauth2/access_token" }, "additionalParameters": {  }, "action": "call", "method": "action", "resourceName": "", "fields": [  ] }
Oct 10, 2014 5:02:36 PM org.forgerock.openidm.external.rest.RestService setAttributes
INFO: Adding header Content-Type: application/x-www-form-urlencoded

Later in the log where an attempt is made to execute the request, you can see that the Content-Type has changed to 'application/json': 

FINE: Attempt 1 to execute request
Oct 10, 2014 5:02:36 PM org.apache.http.impl.conn.DefaultClientConnection sendRequestHeader
FINE: Sending request: POST /openam/oauth2/access_token HTTP/1.1
Oct 10, 2014 5:02:36 PM org.apache.http.impl.conn.Wire wire
FINE: >> "POST /openam/oauth2/access_token HTTP/1.1[\r][\n]"
Oct 10, 2014 5:02:36 PM org.apache.http.impl.conn.Wire wire
FINE: >> "Date: Fri, Oct 10, 2014 17:02:36 GMT[\r][\n]"
Oct 10, 2014 5:02:36 PM org.apache.http.impl.conn.Wire wire
FINE: >> "Content-Type: application/json; charset=UTF-8[\r][\n]"

Recent Changes

N/A

Causes

When IDM/OpenIDM makes an external REST call, messages are passed through a client proxy, which may alter the header containing the Content-Type and change it to 'application/json'. Since the Content-Type is no longer correct, the external REST call fails.

Solution

This issue can be resolved by changing the curl command to use the contentType parameter instead of setting the Content-Type via the headers parameter. For example, replace the following parameter in your curl command:

"headers": { "Content-Type": "application/x-www-form-urlencoded" } 

with:

"contentType" : "application/x-www-form-urlencoded" }

See Also

Integrator's Guide › Extending Functionality By Using Scripts › Creating Custom Endpoints to Launch Scripts

Integrator's Guide › Integrating Business Processes and Workflows › Managing Workflows Over the REST Interface

Related Training

ForgeRock Identity Management Core Concepts (IDM-400)

Related Issue Tracker IDs

N/A


Error when deleting an object from DS/OpenDJ using the REST API in IDM/OpenIDM (All versions)

The purpose of this article is to provide assistance if you receive an error or a 404 response when attempting to delete an object, such as a user, from DS/OpenDJ using the REST API in IDM/OpenIDM. This information also applies when you are connecting to other external LDAP servers.

Symptoms

With a curl command such as:

$ curl -H "Content-Type: application/json" -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -X DELETE "http://localhost:8080/openidm/system/ldap/account/uniqueidentifier=jdoe,ou=People,dc=example,dc=com"

where the entry DN does exist but is actually (with ou value all in lower case):

uniqueidentifier=jdoe,ou=people,dc=example,dc=com

The response is:

<"code":404,"reason":"Not Found","message":"">

Recent Changes

Installed or upgraded IDM/OpenIDM.

Causes

IDM/OpenIDM is case sensitive by default, whereas DS/OpenDJ (and other LDAP servers) are not; therefore, the REST API in IDM/OpenIDM can only delete an object if the case of the uniqueidentifier in the REST call exactly matches the entry DN in DS/OpenDJ.

Solution

This issue can be resolved in one of two ways:

  • Standardize the data in DS/OpenDJ so that all entry DNs use the same case.
  • Enable the CaseInsensitiveFilter to make REST calls case insensitive.

You can enable the CaseInsensitiveFilter by including the following in your LDAP provisioner config file (for example, provisioner.openicf-ldap.json), which is located in the /path/to/idm/conf directory:

 "resultsHandlerConfig" :
       {
          "enableNormalizingResultsHandler" : true,
          "enableFilteredResultsHandler" : true,
          "enableCaseInsensitiveFilter": true,
          "enableAttributesToGetSearchResultsHandler" : true
       },

See Also

IDM/OpenIDM (All versions) connector returns null search result

Integrator's Guide › REST API Reference

Integrator's Guide › Synchronizing Data Between Resources › Configuring Case Sensitivity For Data Stores

Related Training

N/A

Related Issue Tracker IDs

N/A


Command line interface and REST commands timeout in OpenIDM 4.0 when communicating over SSL

The purpose of this article is to provide assistance if you experience issues where command line interface (cli.sh) and REST commands timeout in OpenIDM 4.0 when communicating over SSL. When the timeout occurs, CPU usage is high (~100%).

Symptoms

Running a cli.sh command or a REST command that communicates over SSL intermittently times out / hangs. On the server, you will notice that the OpenIDM Java® process is consuming ~100% CPU when the timeout occurs.

Example commands that will cause an issue are:

  • REST:
    $ curl -k -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" -X GET "https://localhost:8443/openidm/managed/user/?_queryId=query-all-ids"
  • cli.sh:
    $ cli.sh configexport --user openidm-admin:openidm-admin --port 8443 --url https://localhost:8443/openidm/ /tmp/config-export

Running the same commands with http instead of https succeeds.

If you locate the thread that is consuming the CPU as described in How do I find which thread is consuming CPU in a Java process in IDM/OpenIDM (All versions)?,  you will see that the thread corresponds to a Restlet JVM thread similar to the following:

"Restlet-2001136342" daemon prio=10 tid=0x00007faa28018000 nid=0xd1c runnable [0x00007faa1c84e000]
   java.lang.Thread.State: RUNNABLE

Recent Changes

N/A

Causes

An infinite loop occurs in the Restlet code when attempting the SSL handshake, which is caused by Restlet Issue #805. An affected version of Restlet (2.1.2) is bundled with OpenIDM.

Solution

This issue can be resolved by upgrading to OpenIDM 4.5 or later; you can download this from BackStage.

See Also

N/A

Related Training

N/A

Related Issue Tracker IDs

OPENIDM-5438 (Infinite loop within Restlet 2.1.2 library when using ExternalRest over SSL)


Copyright and TrademarksCopyright © 2018 ForgeRock, all rights reserved.

This content has been optimized for printing.

Loading...