This book provides information on administering and configuring IDM/OpenIDM, including frequently asked questions and known issues.

## What versions of DS/OpenDJ are compatible with IDM/OpenIDM?

The purpose of this article is to provide compatibility information between DS/OpenDJ and IDM/OpenIDM versions. This includes connecting to DS/OpenDJ as an external resource (LDAP connector), the embedded DS repositories shipped with later versions of IDM and the supported Java® versions for each combination.

#### External resources compatibility

You can connect to DS/OpenDJ as an external resource using the LDAP connector (the LDAP connector works with any LDAPv3 compliant servers). The following matrix indicates compatibility between IDM/OpenIDM and DS/OpenDJ when using the LDAP connector:

DS 6.x DS 5.x OpenDJ 3.x
IDM 6.x Yes Yes Yes
IDM 5.x Yes Yes Yes
OpenIDM 4.x Yes Yes Yes
##### Note

It is strongly recommended that you always upgrade to the latest maintenance releases for whichever versions of IDM/OpenIDM and DS/OpenDJ you have deployed.

#### Repositories compatibility

Embedded DS

Embedded DS repositories have been shipped with IDM since IDM 5.5; these repositories are for evaluation purposes only and cannot be used in production. The following embedded DS versions are included with IDM:

IDM versions Embedded DS version
IDM 6.5 DS 6.5
IDM 6 DS 6
IDM 5.5 DS 5.5

External DS

IDM 6 introduced a new feature where an external DS instance can now be used as a supported repository in production environments. The following matrix indicates compatibility between IDM and external DS repositories:

DS 6.5 DS 6 DS 5.x OpenDJ 3.x
IDM 6.5 Yes -- -- --
IDM 6 -- Yes -- --
IDM 5.x -- -- -- --
OpenIDM 4.x -- -- -- --
##### Note

It is strongly recommended that you always upgrade to the latest maintenance releases for whichever versions of IDM/OpenIDM and DS/OpenDJ you have deployed.

#### Java Compatability

Java 11

• IDM 6.5 and later.
• DS 6.5 and later.

Java 9

• DS 6 only.

Java 8

• IDM 5 and later; OpenIDM 4.x
• DS 5 and later; OpenDJ 3.x

Java 7

• IDM 5; OpenIDM 4.x
• OpenDJ 3.x. Java 7 can be used in DS 5 but support for it is deprecated.

IDM/OpenIDM

DS/OpenDJ

N/A

N/A

## What versions of AM/OpenAM are compatible with IDM/OpenIDM?

#### Compatibility

The following matrix indicates compatibility between IDM/OpenIDM and AM/OpenAM for integration purposes:

AM 6.5.x AM 6 AM 5.5.x AM 5, 5.1 OpenAM 13.5.x OpenAM 13
IDM 6.5.x Yes -- -- -- -- --
IDM 6 -- Yes -- -- -- --
IDM 5.5.x -- -- Yes -- -- --
IDM 5 -- -- -- Yes -- --
OpenIDM 4.5.x -- -- -- -- Yes --
OpenIDM 4 -- -- -- -- --- Yes
##### Note

It is strongly recommended that you always upgrade to the latest maintenance releases for whichever versions of IDM/OpenIDM and AM/OpenAM you have deployed.

The authentication modules available for integration vary according to product versions as follows:

IDM 6.x IDM 5.5.x IDM 5 OpenIDM 4.x
OAUTH_CLIENT Yes Yes -- --
OPENID_CONNECT -- -- Yes --
OPENAM_SESSION -- Yes * Yes Yes

* The OPENAM_SESSION authentication module is deprecated in IDM 5.5. You should use the OAUTH_CLIENT module instead for integrating IDM with AM.

#### Java Compatability

Java 11

• IDM 6.5 and later.
• AM 6.5 and later.

Java 8

• IDM 5 and later; OpenIDM 4.x
• AM 5 and later; OpenAM 13.x

Java 7

• IDM 5; OpenIDM 4.x
• AM 5 and 5.1.x; OpenAM 13.x

IDM/OpenIDM

AM/OpenAM

N/A

N/A

## What Java versions are ForgeRock products supported on?

#### Oracle® JDK

##### Note

End of Public Updates for Oracle JDK 8

Since January 2019, Oracle no longer posts updates of Java SE 8 to its public download sites for commercial use. If you need continued access to critical bug fixes and security fixes, as well as general maintenance for Java SE 8 or previous versions, you can get long term support through Oracle Java SE Subscription or Oracle Java Desktop Subscription. For more information and details on how to receive longer term support for Oracle JDK 8, please see the Oracle Java SE Support Roadmap.

Platform 5 and later

Platform 6.5 Platform 6 Platform 5.5 Platform 5
Access Management 8, 11 8 8 7, 8
Directory Services 8, 11 8, 9 8 7, 8
Identity Management 8, 11 8 8 7, 8
Identity Gateway 8 8 8 7, 8

Pre-Platform 5

Oracle JDK 8 Oracle JDK 7
OpenAM 13.x Yes Yes
OpenDJ 3.x Yes Yes
OpenIDM 4.x Yes Yes
OpenIG 4.x Yes Yes

Java Agents

Oracle JDK 11 Oracle JDK 8 Oracle JDK 7
Java Agent 5.6 Yes Yes --
Java Agent 5.5 -- Yes --
Java Agent 5 -- Yes --
JEE agents 3.5.x -- Yes Yes

* Web Agents 4 and later do not have any Java dependencies. Earlier versions did require Java in order to run the installer.

#### OpenJDK

Platform 5 and later

Platform 6.5 Platform 6 Platform 5.5 Platform 5
Access Management 8, 11 8 8 8
Directory Services 8, 11 8, 9 8 7, 8
Identity Management 8, 11 8 8 7, 8
Identity Gateway 8, 11 8 8 8

Pre-Platform 5

OpenJDK 8 OpenJDK 7
OpenAM 13.x -- --
OpenDJ 3.x Yes Yes
OpenIDM 4.x Yes Yes
OpenIG 4.x Yes Yes

Java Agents

OpenJDK 11 OpenJDK 8
Java Agent 5.6 Yes Yes
Java Agent 5.5 -- Yes
Java Agent 5 -- Yes
JEE agents 3.5.x -- --

* Web Agents 4 and later do not have any Java dependencies. Earlier versions did require Java in order to run the installer.

#### IBM® SDK (Websphere® only)

##### Note

Only AM/OpenAM and Java Agents have been validated with the IBM SDK.

AM/OpenAM

IBM SDK 8 IBM SDK 7
AM 6.x Yes --
AM 5.5 Yes --
AM 5 -- Yes
OpenAM 13.x -- Yes

Java Agents

IBM SDK 8 IBM SDK 7
Java Agent 5.6 Yes --
Java Agent 5.5 Yes --
Java Agent 5 Yes --
JEE agents 3.5.x Yes Yes

## How do I secure the JWT session cookie used by IDM/OpenIDM (All versions)?

#### Securing the JWT session cookie

You can secure the JWT session cookie by making the cookie httponly and secure as follows:

1. Edit the authentication.json file (located in the /path/to/idm/conf directory) and add the following properties to the JWT Session Module configuration:
                "isHttpOnly" : true,
"isSecure" : true

For example, the configuration for this module would now look similar to this:
        "sessionModule" : {
"name" : "JWT_SESSION",
"properties" : {
"keyAlias" : "openidm-localhost",
"keystoreType" : "&{openidm.keystore.type}",
"keystoreFile" : "&{openidm.keystore.location}",
"maxTokenLifeMinutes" : "120",
"tokenIdleTimeMinutes" : "30",
"sessionOnly" : true,
"isHttpOnly" : true,
"isSecure" : true
}

2. Check the cookie using your browser's developer tool to ensure the HttpOnly and Secure flags are set.

N/A

N/A

## How do I limit the supported secure protocols and cipher suites in IDM/OpenIDM (All versions)?

The purpose of this article is to provide information on disabling specific secure protocols and cipher suites in IDM/OpenIDM. You may need to do this to remove an insecure protocol or address findings from a vulnerability scan.

#### Overview

By default, Jetty® supports a number of protocols and cipher suites. You can see what protocols are currently supported in the Enabled Protocols output of the openidm0.log.n log at server startup, for example:

INFO: Enabled Protocols [SSLv2Hello, TLSv1.1, TLSv1.2] of [SSLv2Hello, SSLv3, TLSv1, TLSv1.1, TLSv1.2]


Enabled protocols appear before "of", in the list of all protocols.

To see what cipher suites are currently supported, set the log level to FINE (change the ".level=INFO" to ".level=FINE" in the logging.properties file). The openidm0.log.n log will show a list of Enabled Ciphers when restarting the server, for example (the log snippet has been truncated due to its size):

FINE: Enabled Ciphers   [TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 ... TLS_EMPTY_RENEGOTIATION_INFO_SCSV] of [TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_RSA_WITH_AES_256_CBC_SHA256 ... TLS_KRB5_WITH_DES_CBC_MD5]

#### Disabling secure protocols

The SSLv3 protocol is disabled by default because it is considered an obsolete and insecure protocol: This POODLE Bites: Exploiting The SSL 3.0 Fallback.

Support for the TLSv1.0 protocol has been removed in IDM 6; see the following PDF: Migrating from SSL and Early TLS from the PCI Security Standards Council for further information. Support for the TLSv1.1 protocol is deprecated in IDM 6 due to a potential vulnerability: see CVE-2011-3389 from the National Vulnerability Database from the US National Institute of Standards and Technology for further information.

You can exclude protocols as follows:

1. Add any protocols you want to exclude to the ExcludeProtocols sections of sslContextFactory and sslContextFactoryMutualAuth in the jetty.xml file (located in the /path/to/idm/conf directory).
2. Restart IDM/OpenIDM to apply these changes.

Example

The following example demonstrates excluding the TLSv1 and TLSv1.1 protocols in addition to the SSLv3 protocol:

    <New id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory">
...
<Set name="ExcludeProtocols">
<Array type="java.lang.String">
<Item>SSLv3</Item>
<Item>TLSv1</Item>
<Item>TLSv1.1</Item>
</Array>
</Set>
...
</New>

<New id="sslContextFactoryMutualAuth" class="org.eclipse.jetty.util.ssl.SslContextFactory">
...
<Set name="ExcludeProtocols">
<Array type="java.lang.String">
<Item>SSLv3</Item>
<Item>TLSv1</Item>
<Item>TLSv1.1</Item>
</Array>
...
</Set>
...
</New>


#### Disabling cipher suites

You can exclude cipher suites as follows:

1. Add any cipher suites you want to exclude to the <Array id="excludedCipherSuites" type="java.lang.String"> section in the jetty.xml file (located in the /path/to/idm/conf directory). There are numerous excluded cipher suites by default.
2. Restart IDM/OpenIDM to apply these changes.

Example

The following example demonstrates excluding the TLS_RSA_WITH_AES_128_CBC_SHA cipher suite:

    <Array id="excludedCipherSuites" type="java.lang.String">

<Item>TLS_RSA_WITH_AES_128_CBC_SHA</Item>

<!-- EXP-RC4-MD5  -->
<Item>SSL_RSA_EXPORT_WITH_RC4_40_MD5</Item>
<Item>SSL_DH_anon_EXPORT_WITH_RC4_40_MD5</Item>
<Item>TLS_KRB5_EXPORT_WITH_RC4_40_MD5</Item>

<!-- EXP-EDH-RSA-DES-CBC-SHA or EXP-DHE-RSA-DES-CBC-SHA  -->
<Item>SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA</Item>
...
</Array>


N/A

N/A

## How do I disable TLS Client-Initiated Renegotiation in IDM/OpenIDM (All versions)?

#### Disabling TLS renegotiation

Java® 8 introduced a new system property jdk.tls.rejectClientInitiatedRenegotiation that controls TLS client-initiated renegotiation.

You can disable client-initiated renegotiation using the OPENIDM_OPTS environment variable:

• On Unix® and Linux® systems:
$cd /path/to/idm/$ export OPENIDM_OPTS="-Djdk.tls.rejectClientInitiatedRenegotiation=true"
$./startup.sh • On Microsoft® Windows® systems: C:\> cd \path\to\idm C:\path\to\idm> set OPENIDM_OPTS=-Djdk.tls.rejectClientInitiatedRenegotiation=true C:\path\to\idm> startup.bat  ##### Note You can also edit the startup.sh or startup.bat files to update the default OPENIDM_OPTS values. #### See Also #### Related Training N/A #### Related Issue Tracker IDs N/A ## How do I hash the password for openidm-admin before the first startup of IDM/OpenIDM (All versions)? The purpose of this article is to provide information on securing the openidm-admin password before starting IDM/OpenIDM for the first time by hashing the password value. Normally IDM/OpenIDM hashes the password on first startup of the instance; this information is only required if you want the password hashed prior to this. This article assumes the configuration and boot.properties are in place even though IDM/OpenIDM is not yet running. #### Hashing the password for openidm-admin You can set the openidm-admin's password to a secure value before the first startup as follows: 1. Execute the ./cli.sh secureHash command within the root of the IDM/OpenIDM installation: $ cd /path/to/idm
$./cli.sh secureHash newPassword 2. Copy the return JSON object that is between the ----- BEGIN HASHED VALUE ---- and ----- END HASHED VALUE ------ lines, for example: -----BEGIN HASHED VALUE----- { "$crypto" : {
"value" : {
"algorithm" : "SHA-256",
},
"type" : "salted-hash"
}
}
------END HASHED VALUE------

3. Run a database query against the openidm-admin object to update the internaluser password, where the JSON object returned above is all on one line with all the spaces removed. For example, your query would look like this if you have a MySQL repository:
update internaluser set pwd='{"$crypto":{"value":{"algorithm":"SHA-256","data":"xMJwQJCIUdhLCPIoQny9vp04coqadSBsC/iin4FsY+KfZJ10OO1C7gmN91tz2aFL"},"type":"salted-hash"}}'where objectid='openidm-admin';  4. Start the IDM/OpenIDM instance. You should be able to log in with your new password. ##### Note You will not be able to log in with your new password if the JSON object included in the update has any spaces or spans multiple lines. Additionally, you will see a warning when you perform this update with a MySQL repository (but not with a PostgreSQL repository); this warning can be ignored. #### See Also #### Related Training N/A #### Related Issue Tracker IDs N/A ## How does IDM/OpenIDM (All versions) use anonymous access? The purpose of this article is to provide information on the access available to the anonymous user in IDM/OpenIDM, and to explain how to limit or remove this access if required. #### Overview The anonymous user renders the login page in IDM/OpenIDM. Additionally, if enabled, anonymous is used to perform user self-registration and password reset. To accomplish these functions, anonymous needs access to the configuration files, including the user interface settings for language, color schemes and logos. The anonymous user has the internal/role/openidm-reg role. In pre-IDM 6.5, you do not need to include the full path; you can just refer to the role name, for example, openidm-reg. By default, this role has limited functionality as defined in the access.js and router-authz.js files (located in the /path/to/idm/script and /path/to/idm/bin/defaults/script directories respectively). These files are explained in more detail in How do I customize authorization rules for http requests in IDM/OpenIDM (All versions)? ##### Note The authentication mechanism for the anonymous user uses the STATIC_USER authentication module to improve performance: Integrator's Guide › Supported Authentication Modules. #### Understanding anonymous access The anonymous user has access rights as determined by the internal/role/openidm-reg role in the access.js file (located in the /path/to/idm/script directory). For example, the internal/role/openidm-reg role is available for self-registration for the managed/user endpoint (http request) by default:  { "pattern" : "managed/user", "roles" : "internal/role/openidm-reg", "methods" : "create", "actions" : "*", "customAuthz" : "checkIfUIIsEnabled('selfRegistration') && isSelfServiceRequest() && onlyEditableManagedObjectProperties('user')" },  Certain endpoints (such as the managed/user one) depend on additional authorization checks such as selfRegistration or passwordReset being enabled. If you want to use the associated functionality, you must ensure these authorization checks are enabled in the ui-configuration.json file. This is described in more detail in Integrator's Guide › Configuring User Self-Service. The internal/role/openidm-reg role is also available to all endpoints that apply to all roles. For example, the config/ui/themeconfig endpoint:  { "pattern" : "config/ui/themeconfig", "roles" : "*", "methods" : "read", "actions" : "*" },  If you don't want to use the user interface (config/ui/themeconfig endpoint) or allow access to the customizable information service (info/* endpoint), you should update the relevant endpoint to implicitly state each individual role they are accessible to in order to remove access for the internal/role/openidm-reg role. For example, if you only use the default roles supplied with IDM/OpenIDM, you would update the roles definition as follows to remove the internal/role/openidm-reg role:  "roles" : "internal/role/openidm-admin,internal/role/openidm-authorized,internal/role/openidm-cert",  #### See Also #### Related Training #### Related Issue Tracker IDs N/A ## How does IDM/OpenIDM (All versions) protect against CSRF attacks? The purpose of this article is to provide information on how IDM/OpenIDM protects against Cross Site Request Forgery (CSRF) attacks. #### CSRF attacks CSRF attacks attempt to make an authenticated user execute malicious functionality unknowingly; this is achieved by including a link or script in a page that accesses a site to which the user is authenticated. It is important to understand that although CSRF attacks can execute functionality, they cannot interact with the response from the targeted server. Therefore, CSRF attacks make changes, such as transferring funds out of a bank account or changing a user's password but cannot steal data. #### Protecting against CSRF attacks IDM/OpenIDM defends against CSRF attacks by requiring a custom HTTP header for update REST requests (POST, PUT and DELETE); the built-in read requests (GET) don't require this custom HTTP header as they don't make changes to the repository and the response from a GET request is unavailable to a CSRF attacker. This is in line with the NSA guidelines. IDM/OpenIDM checks that one of the following custom HTTP headers are present when processing update REST requests: • "X-Requested-With" or "x-requested-with" - these headers are typically used with AJAX requests, such as ones originating from JQuery. These headers protect against CSRF attacks because they cannot be added to an AJAX request cross domain without using Cross-Origin Resource Sharing (CORS). CORS is a W3C specification that allows cross-domain communication to happen in a similar way to same-domain requests, however, your servers must be configured to allow CORS. • "Authorization" or "authorization" - these basic authorization headers are provided for convenience when using Curl commands and authenticate the user. • "X-OpenIDM-Username" or "x-openidm-username" - these custom authorization headers are specific to IDM/OpenIDM and authenticate the user. If a REST endpoint in IDM/OpenIDM receives an update request without one of these custom HTTP headers, it is dropped; thereby preventing any potential CSRF attacks. Custom request headers can only be set by an XHR-type request. They cannot be set by simple GET and POST requests from HTTP forms and embedded resources. ##### Warning If you build any functionality with custom endpoints, you should ensure that all GET requests are also read-only in line with the standard GET requests in IDM/OpenIDM to prevent them being able to make changes. If you choose not to follow this standard, you should ensure you implement your own protections against CSRF attacks. #### See Also #### Related Training N/A #### Related Issue Tracker IDs ## How do I remove access to the browser-based UI in IDM/OpenIDM (All versions)? The purpose of this article is to provide information on removing access to the Admin and/or End User (previously Self-Service) UIs in IDM/OpenIDM. You may want to do this for security reasons. #### Removing access to the browser-based UI You can remove access to the Admin and/or End User UIs using one of the following options: • Disable the UI • Remove the ui directory Disable the UI You can disable the UIs as follows: • Admin: edit the ui.context-admin.json file (located in the /path/to/idm/conf directory) and change enabled to false. For example: { "enabled" : false, "urlContextRoot" : "/admin",  • End User • IDM 6.5 and later: edit the ui.context-enduser.json file (located in the /path/to/idm/conf directory) and change enabled to false. For example: { "enabled" : false, "urlContextRoot" : "/",  • Pre-IDM 6.5: edit the ui.context-selfservice.json file (located in the /path/to/idm/conf directory) and change enabled to false. For example: { "enabled" : false, "urlContextRoot" : "/",  Remove the ui directory The ui directory (located in the /path/to/idm directory) contains an admin directory and either an enduser (IDM 6.5 and later) or selfservice (pre-IDM 6.5) directory. You can simply remove one or both of these directories to remove access to the corresponding UI. #### See Also #### Related Training N/A #### Related Issue Tracker IDs N/A ## Keystores ## How do I change the symmetric key in IDM/OpenIDM (All versions)? The purpose of this article is to provide information on changing the symmetric key in IDM/OpenIDM; this key is used to encrypt values. The approach recommended in this article involves generating a new symmetric key but retaining the old one to ensure existing encrypted data can still be decrypted. #### Overview The default alias for the symmetric key is openidm-sym-default. As of IDM 6.5, an alias can have a dedicated capability and function. This means the default encryption alias is used for multiple purposes as detailed in Integrator's Guide › Configuration Options in secrets.json. You can change the symmetric key as follows: #### Generating a new symmetric key (pre-IDM 6.5) ##### Warning If you replace the symmetric key within an existing environment, you will render IDM/OpenIDM incapable of decrypting any existing encrypted data stored within the repository or the file-based JSON configuration. This affects both configuration and managed objects. If replacing the encryption key in the keystore is desired, this article recommends that you generate a new symmetric key with a new alias but retain the old one. The new key will be used when encrypting data but the old key can still be found under the original alias to decrypt any data encrypted with the older key. 1. Shut down the IDM/OpenIDM instance. 2. Generate a new symmetric key using the keytool command; you must use a different alias name, for example: $ keytool -genseckey -alias idm-sym-new -keyalg AES -keysize 128 -storetype jceks -keystore security/keystore.jceks
3. Update the openidm.config.crypto.alias property in the boot.properties file (located in install-dir/resolver (IDM 6 and later) or /path/to/idm/conf/boot (pre-IDM 6)) to use the new symmetric key you created. For example, change the following:
# key in keystore to handle config encryption
openidm.config.crypto.alias=openidm-sym-default

to the new name (idm-sym-new in this example):
# key in keystore to handle config encryption
openidm.config.crypto.alias=idm-sym-new

4. Update the encryption keys specified in the managed.json file (located in /path/to/idm/conf) to use the new symmetric key you created. For example, change the following:
"password" : {
"type" : "string",
...
"encryption" : {
"key" : "openidm-sym-default"
},

to the new name (idm-sym-new in this example):
"password" : {
"type" : "string",
...
"encryption" : {
"key" : "idm-sym-new"
},

5. Replace the $crypto blocks within the JSON configuration files across all nodes (whether standalone or clustered) with their corresponding plain text values. For example, to update the password field in the datasource.jdbc-default.json file, you would change the password field from:  "password" : { "$crypto" : {
"value" : {
"iv" : "5UWV+SLe/Z9gg/7lZRO+Ng==",
"data" : "7rol/iYruQ4xauop0hq6cQ==",
"key" : "openidm-sym-default"
},
"type" : "x-simple-encryption"
}
},

To:
  "password" : "plain_text_value",

6. Restart all the IDM/OpenIDM instances. The startup process will re-encrypt the plain text values with the new symmetric key.

N/A

N/A

## How do I change the default keystore password in IDM/OpenIDM (All versions)?

The purpose of this article is to provide information on changing the default keystore password in IDM/OpenIDM for improved security. The keystore password is changeit by default and should be changed in production environments. You can also use this procedure to change the truststore password.

#### Changing the default keystore password

The keystore password is changeit by default and should be changed in production environments to improve security. This process is documented in the Integrator's guide.

You should refer to the process relevant to your version of IDM/OpenIDM:

N/A

## How do I configure IDM/OpenIDM (All versions) to use my existing CA signed certificate?

#### Overview

In order to import an existing signed certificate into the IDM/OpenIDM keystore, the following are required:

• CA signed certificate.
• Private key associated with the Certificate Signing Request (CSR) used to request the signed certificate.
• Intermediary and root certificates from the Certificate Authority.
##### Note

All of the above are expected to be in .PEM format. If there are multiple intermediary CA certificates they can be concatenated with the root certificate into a single .PEM file.

You can import an existing signed certificate as follows:

#### Importing an existing CA signed certificate (OpenIDM 4.x)

##### Caution

In a clustered configuration, the following procedure should be performed on the 'clustered-first' node. The 'clustered-additional' nodes within the environment must be restarted in order for the new certificate to take effect.

To replace the out-of-the-box OpenIDM self-signed certificate with an existing signed certificate:​

1. Shut down the OpenIDM instance.
2. Back up the existing security/keystore and security/truststore files.
3. Delete the openidm-localhost certificate from both the existing keystore and truststore files using the keytool command:
$keytool -delete -alias openidm-localhost -keystore security/keystore.jceks -storetype JCEKS$ keytool -delete -alias openidm-localhost -keystore security/truststore
4. Generate a new PKCS12 keystore using the existing CA signed certificate, private key and CA certificate chain:
$openssl pkcs12 -export -in cert.pem -inkey key.pem -certfile chain.pem -name openidm-signed-cert -out cert.pkcs12 You will be prompted for a password when generating the new PKCS12 keystore file; you must enter the existing OpenIDM keystore password. 5. Import the PKCS12 keystore generated in step 4 into the existing OpenIDM keystore using the keytool command: $ keytool -importkeystore -srckeystore cert.pkcs12 -srcstoretype pkcs12 -destkeystore security/keystore.jceks -storetype JCEKS
$keytool -import -file cert.pem -keystore security/truststore -alias openidm-signed-cert 6. Edit the boot.properties file (located in /path/to/openidm/conf/boot) and set the openidm.https.keystore.cert.alias as follows: openidm.https.keystore.cert.alias=openidm-signed-cert 7. Restart the OpenIDM instance. #### See Also #### Related Training N/A #### Related Issue Tracker IDs N/A ## How do I renew my existing CA certificate in use by IDM/OpenIDM (All versions)? The purpose of this article is to provide information on renewing an existing Certificate Authority (CA) signed certificate that is currently being used by IDM/OpenIDM. #### Renewing an existing CA certificate Renewing an existing CA signed certificate that is in use by IDM/OpenIDM and due to expire is effectively the same as requesting and installing a new CA signed certificate; the only difference being there is no need to import the CA root and intermediary certificates into the IDM/OpenIDM truststore as they are already present. ##### Caution In a pre-IDM 5 clustered configuration, the following procedure should be performed on the 'clustered-first' node. The 'clustered-additional' nodes within the environment must be restarted in order for the new certificate to take effect. To renew an existing CA certificate: 1. Generate a new Certificate Signing Request (CSR) via the keytool command: $ keytool -certreq -alias openidm-signed-cert -keystore security/keystore.jceks -storetype JCEKS -file request.csr
replacing openidm-signed-cert with the alias of the existing certificate currently in use by IDM/OpenIDM. This can be found as follows depending on your version:
• IDM 6.5 and later: look at the alias specified for the idm.jwt.session.module.encryption secret in the secrets.json file (located in /path/to/idm/conf).
• IDM 6: look at the openidm.https.keystore.cert.alias value in the boot.properties file (located in install-dir/resolver).
• Pre-IDM 6: look at the openidm.https.keystore.cert.alias value in the boot.properties file (located in /path/to/idm/conf/boot).
2. Submit the generated CSR request to your CA.
4. Shutdown the IDM/OpenIDM instance.
5. Import the signed certificate provided by your CA into the existing IDM/OpenIDM keystore.
$keytool -keystore security/keystore.jceks -storetype JCEKS -import -alias openidm-signed-cert -file signed.crt -trustcacerts  replacing openidm-signed-cert with the alias of the existing certificate currently in use by IDM/OpenIDM. 6. Restart the IDM/OpenIDM instance. #### See Also #### Related Training N/A #### Related Issue Tracker IDs N/A ## Configuration ## How do I run the command-line interface in IDM (All versions) and OpenIDM 4.x if my install and project directories are different? The purpose of this article is to provide information on running the command-line interface (cli.sh) in IDM/OpenIDM when your install and project directories are different; this means the boot.properties file is in a different location to the one expected by the command-line utilities. This information applies to Unix® and Linux® systems. #### Background information By default, the command-line utilities run with the properties defined in your project's boot.properties file (located in /path/to/idm/resolver/ (IDM 6 and later) or /path/to/idm/conf/boot/ (pre-IDM 6)). This means you will encounter the following error if you have installed IDM/OpenIDM in one directory (for example, /opt/openidm) but run IDM/OpenIDM with the project directory (-p switch) set to a different directory (for example, /etc/openidm): /opt/openidm$ ./cli.sh

Executing ./cli.sh...
Starting shell in /opt/openidm
No boot properties file detected at /opt/openidm/resolver/boot.properties

To overcome this issue, you must set system variables in the cli.sh script to point to your project directory.

#### Setting system variables (IDM 6 and later)

You can either edit your cli.sh script to make the changes permanent or specify the IDM_ENVCONFIG_DIRS environment variable when you run the script. You should not specify JAVA_OPTS when running the script because of the following known issue: OPENIDM-12316 (cli.sh fails with NullPointerException when it's started with -Didm.envconfig.dirs at command line).

The following examples demonstrate this, where:

• The project directory is /etc/idm
• The boot.properties file is located in /etc/idm/altresolver

Edit the cli.sh script

You should update the cli.sh script by setting the idm.envconfig.dirs property to the location of your boot.properties file, for example:

java "$LOGGING_CONFIG"$JAVA_OPTS -classpath "$OPENIDM_HOME/bin/*:$OPENIDM_HOME/bundle/*" \
-Didm.envconfig.dirs="/etc/idm/altresolver/" \
-Dopenidm.system.server.root="$OPENIDM_HOME" \ org.forgerock.openidm.shell.impl.Main "$@"


Set IDM_ENVCONFIG_DIRS when running the script

You can specify this environment variable when you run the command-line utilities as follows:

/opt/openidm$IDM_ENVCONFIG_DIRS=/etc/idm/altresolver ./cli.sh Executing ./cli.sh... Starting shell in /opt/openidm Using boot properties at /etc/idm/altresolver/boot.properties  #### Setting system variables (pre-IDM 6) You can either edit your cli.sh script to make the changes permanent or specify the JAVA_OPTS when you run the script. Edit the cli.sh script You should update the cli.sh script by inserting the following system variables above the java$JAVA_OPTS -classpath line:

JAVA_OPTS="$JAVA_OPTS -Dopenidm.boot.file=/path/to/project/dir/conf/boot/boot.properties" JAVA_OPTS="$JAVA_OPTS -Dlauncher.project.location=/path/to/project/dir"


The changes would look like this if your project directory was /etc/openidm:

JAVA_OPTS="$JAVA_OPTS -Dopenidm.boot.file=/etc/openidm/conf/boot/boot.properties" JAVA_OPTS="$JAVA_OPTS -Dlauncher.project.location=/etc/openidm"

java $JAVA_OPTS -classpath "$OPENIDM_HOME/bin/*:$OPENIDM_HOME/bundle/*" \ -Dopenidm.system.server.root="$OPENIDM_HOME" \
org.forgerock.openidm.shell.impl.Main "$@"  Set JAVA_OPTS when running the script You can specify these options when you run the command-line utilities as follows (with an example project directory of /etc/openidm): /opt/openidm$ JAVA_OPTS='-Dopenidm.boot.file=/etc/openidm/conf/boot/boot.properties -Dlauncher.project.location=/etc/openidm' ./cli.sh

Executing ./cli.sh...
Starting shell in /opt/openidm
Using boot properties at /etc/openidm/conf/boot/boot.properties

N/A

## How do I load OSGI bundles and JAR files into IDM/OpenIDM (All versions)?

You can load OSGI bundles and JAR files from separate locations using the launcher.json​ configuration script (located in the /path/to/idm/bin directory by default). The default locations defined within this file are relative to the OPENIDM_HOME directory unless an absolute path is specified. If required, you can locate the launcher.json file in a different location providing you start IDM/OpenIDM with the -c option and specify the path. See Integrator's Guide › Advanced Startup Configuration for further information about the launcher.json file.

To load OSGI bundles and JAR files:

1. Add location, includes and excludes properties to launcher.json to specify the absolute path to where the files are located and to define the jars you want to include or exclude from loading. For example:
{
"location":"/path/to/separate/location",
"includes":["*.jar"]
}, 

2. Restart the IDM/OpenIDM instance to apply these changes.

N/A

N/A

## How do I implement keep-alive functionality for the managed repository in IDM/OpenIDM (All versions)?

The purpose of this article is to provide information on implementing keep-alive functionality for the managed repository in IDM/OpenIDM to prevent issues when idle connections are closed by the network infrastructure. This configuration applies when you are using a JDBC database.

#### Implementing keep-alive functionality (IDM 5 and later)

IDM 5 and later uses the Hikari connection pool by default. See Integrator's Guide › Managing the Repository › Understanding the JDBC Connection Configuration File and Hikari Project Page for further information on configuring the connection pool settings.

You cannot configure keep-alive functionality within Hikari; however, if you do require keep-alive functionality, you can set the TCP keep alive instead using the mechanism provided by the JDBC datasource. Both MySQL™ and PostgreSQL® provide a tcpKeepAlive configuration property, which can be added to the datasource.jdbc-default.json file (located in the /path/to/idm/conf directory), for example:

{
"driverClass" : "org.postgresql.Driver",
"jdbcUrl" : "jdbc:postgresql://&{openidm.repo.host}:&{openidm.repo.port}/openidm",
"databaseName" : "openidm",
"connectionTimeout" : 30000,
"connectionPool" : {
"type" : "hikari",
"minimumIdle" : 20,
"maximumPoolSize" : 50
},
"tcpKeepAlive" : "true"
}


When set to true, connections in the Hikari connection pool are tested when they are retrieved using the JDBC Connections isValid() method to ensure that a closed connection is never returned.

Verifying the keep-alive changes

You can make use of any Network Traffic Analyzer (such as Wireshark) or simply output a tcpdump on the IDM server to check that the JDBC Connections driver is invoking the isValid() method.

#### Implementing keep-alive functionality (OpenIDM 4.x)

You can implement keep-alive functionality by adding the following properties to the connectionPool block in the datasource.jdbc-default.json file (located in the /path/to/openidm/conf directory) and specify the number of seconds after which you want a keep-alive statement sent (the first property just defines the SQL statement to send):

"connectionTestStatement" : "SELECT 1",
"idleConnectionTestPeriodInSeconds" : "nnn"


For example, the following configuration would ensure that connections that had been idle for more than 180 seconds were sent a keep-alive statement to prevent them closing:

    "connectionPool" : {
"type" : "bonecp",
"connectionTestStatement" : "SELECT 1",
"idleConnectionTestPeriodInSeconds" : "180"
}


Verifying the keep-alive changes

For testing purposes, you can make the following changes to the logging.properties file (located in the /path/to/idm/conf directory) to verify that the keep-alive functionality is working:

1. Change the global logging level to FINER:
.level=FINER
2. Uncomment the following logging levels and ensure they are all set to FINER. They should now look like this in your logging.properties file:
org.forgerock.openidm.provisioner.level = FINER
org.forgerock.openidm.repo.level = FINER
org.forgerock.openidm.recon.level = FINER

3. Restart OpenIDM to apply these changes.
4. Check the OpenIDM log file (openidm0.log.n, which is located in the /path/to/openidm/logs directory) for the following entry (which corresponds to the statement you defined):
SELECT 1
You can also check that this statement is firing at the correct interval; in this example, it would be every 180 seconds per the idleConnectionTestPeriodInSeconds property.
5. Revert these changes once you have finished testing:
• Change the global logging level back to INFO.
• Comment out the logging levels in step 2.

#### Implementing keep-alive functionality (OpenIDM 3.x)

You can implement keep-alive functionality by adding the following properties to the connection block in the repo.jdbc.json file (located in the /path/to/openidm/conf directory) and specify the number of seconds after which you want a keep-alive statement sent (the first property just defines the SQL statement to send):

"connectionTestStatement" : "SELECT 1",
"idleConnectionTestPeriodInSeconds" : "nnn"


For example, the following configuration for a MySQL database would ensure that connections that had been idle for more than 180 seconds were sent a keep-alive statement to prevent them closing:

    "connection" : {
"dbType" : "MYSQL",
"jndiName" : "",
"driverClass" : "com.mysql.jdbc.Driver",
"jdbcUrl" : "jdbc:mysql://localhost:3306/openidm?allowMultiQueries=true&characterEncoding=utf8",
"defaultCatalog" : "openidm",
"maxBatchSize" : 100,
"maxTxRetry" : 5,
"enableConnectionPool" : true,
"connectionTimeoutInMs" : 30000,
"connectionTestStatement" : "SELECT 1",
"idleConnectionTestPeriodInSeconds" : "180"
},




Verifying the keep-alive changes

For testing purposes, you can make the following changes to the logging.properties file (located in the /path/to/idm/conf directory) to verify that the keep-alive functionality is working:

1. Change the global logging level to FINER:
.level=FINER
2. Uncomment the following logging levels and ensure they are all set to FINER. They should now look like this in your logging.properties file:
org.forgerock.openidm.provisioner.level = FINER
org.forgerock.openidm.repo.level = FINER
org.forgerock.openidm.recon.level = FINER

3. Restart OpenIDM to apply these changes.
4. Check the OpenIDM log file (openidm0.log.n, which is located in the /path/to/openidm/logs directory) for the following entry (which corresponds to the statement you defined):
SELECT 1
You can also check that this statement is firing at the correct interval; in this example, it would be every 180 seconds per the idleConnectionTestPeriodInSeconds property.
5. Revert these changes once you have finished testing:
• Change the global logging level back to INFO.
• Comment out the logging levels in step 2.

N/A

N/A

## How do I modify the startup parameters for the IDM/OpenIDM (All versions) Windows Service?

The purpose of this article is to provide information on modifying the startup parameters for the IDM/OpenIDM Microsoft® Windows® service. You will need to modify startup parameters if your install and project directories are different.

#### Modifying startup parameters if your install and project directories are different

The following process assumes IDM/OpenIDM is installed as a Windows Service. If it is not installed, install it per: Installation Guide › Installing as a Windows Service before proceeding with these steps:

1. Launch a Command Prompt window and navigate to your install bin directory, for example D:\idm-6.0.0\bin.
2. Enter the following command to display the Properties window, replacing IDM with the name of your service:
prunmgr.exe //ES//IDM
Make the following changes in the Properties window:
• General tab: ensure the path to the executable and the arguments are set correctly, for example, where D:\idm-6.0.0 is your install directory and IDM is the name of your service:
D:\idm-6.0.0\bin\amd64\prunsrv.exe //RS//IDM
• Java tab: set the class path as follows:
bin\*;framework\*
• Java tab: update the Java® options to include the following line, where D:\idm-6.0.0 is your install directory:
-Dopenidm.system.server.root=D:\idm-6.0.0
• Startup tab: set the Working Path to your install directory, for example, D:\idm-6.0.0.
• Startup tab: set Method to start.
• Startup tab: set the arguments to the your project directory, for example, where D:\idm-6.0.0\project is your project directory:
-c
bin/launcher.json
-p
D:\idm-6.0.0\project

It is important to put these values on separate lines as shown in this example.
3. Check the other settings in the Properties window are correct and click Apply, followed by OK to save your changes.
4. Start IDM/OpenIDM from the Services window and verify that it is working correctly.

#### Troubleshooting

This section covers some common issues you may encounter with this setup:

• Ignored logging changes
• Inconsistent 32-bit and 64-bit architectures

Ignored logging changes

If you make changes to the logging.properties file to change log levels and they are ignored, you should ensure you are updating the correct logging.properties file. If you have followed the above configuration to have separate install and project directories, you must edit the logging.properties file in the conf directory within your project directory (rather than the install directory).

Inconsistent 32-bit and 64-bit architectures

If you see an error similar to the following in the Windows Event Viewer:

[2017-11-12 14:07:29] [error] %1 is not a valid Win32 application.

It means that prunsrv.exe is trying to load jvm.dll, which fails if the architectures do not match. To resolve it, you should ensure you are consistently using either 32-bit or 64-bit architectures for the ImagePath and the Java installation. In particular, check the following registry keys:

• LOCAL_MACHINE\SYSTEM\ControlSet001\Services\IDM - this points to the ImagePath:
• 64-bit - bin\amd64\prunsrv.exe
• 32-bit - bin\i386\prunsrv.exe
• HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Apache Software Foundation\Procrun 2.0\openidm\Parameters\Java - this points to the Java installation.

You can either change one of the registry entries, that is, either update the ImagePath or the path to the Java installation so they both point to 32-bit or 64-bit architectures consistently, update the Java tab in the Properties window (for example, by running prunmgr.exe //ES//IDM) or by initially setting the environment variable ARCH=i386 or ARCH=amd64 before running install.bat to install the server with the appropriate ImagePath.

##### Note

If you cannot get your changes to work successfully, you should use regedit to export the following registry key: HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\IDM (replacing IDM with the name of your service) and attach the output when you raise a Support ticket.

N/A

## How do I customize authorization rules for http requests in IDM/OpenIDM (All versions)?

#### Overview

Authorization rules for http requests are derived from the access.js and router-authz.js files (located in the /path/to/idm/script and /path/to/idm/bin/defaults/script directories respectively). These two files are used together to validate inbound REST requests and determine if the user has access.

access.js allows you to specify authorization rules for each http request, where the configurations for each http request follow a set format:

• pattern - resource requested, for example, managed/user. You can also use "*" to indicate all patterns are allowed.
• roles - role of requesting user, for example, internal/role/openidm-authorized. In pre-IDM 6.5, you do not need to include the full path; you can just refer to the role name, for example, openidm-authorized
• methods - comma separated list of methods to which access is being granted (for example, create, read, patch etc.) You can also use "*" to indicate all methods are allowed or "" to indicate no methods are allowed.
• actions - comma separated list of allowed actions. The possible values depend on the URL being exposed as detailed in Integrator's Guide › Understanding the Access Configuration Script (access.js). You can also use "*" to indicate all actions are allowed or "" to indicate no actions are allowed.
• customAuthz (optional) - reference to function names of scripts contained within router-authz.js.
• excludePatterns (optional) - resources to which access is not permitted.

The access.js file format is described in more detail in Integrator's Guide › Understanding the Access Configuration Script (access.js).

router-authz.js contains a set of functions, where each function must return a boolean value. These scripts all have access to the openidm.[method]() functionality along with the request, config and context variables, which all contain useful information.

The router-authz.js file is described in more detail in Integrator's Guide › Understanding the Router Authorization Script (router-authz.js); further information on openidm.[method]() calls can be found in Integrator's Guide › Function Reference.

#### Customizing authorization rules for http requests

You can update and add entries to access.js to provide simple authorization rules, such as restricting certain actions to a given role. For greater control, you can combine this with calls to an appropriate function (or functions) written within the router-authz.js file to provide context-based authorization rules.

##### Note

You should copy the router-authz.js file to the /path/to/idm/script directory and update the copy rather than the default file itself.

Additionally, if you add new roles or custom http requests to IDM/OpenIDM, you should configure the appropriate access by updating access.js to include the new roles and/or custom http requests.

Example 1

The info http request in IDM/OpenIDM (which provides detailed information about a running IDM/OpenIDM instance) is configured by default to be accessible to all roles:

        {
"pattern"    : "info/*",
"roles"      : "*",
"actions"    : "*"
},


You could change this so it is only accessible to users assigned the internal/role/openidm-admin role by updating this as follows:

        {
"pattern"    : "info/*",
"actions"    : "*"
},


Example 2

If you had a new custom http request that you wanted to be accessible to users assigned a new role or the existing internal/role/openidm-cert role, you would add something similar to the following to access.js:

{
"pattern" : "custom/*",
"roles"   : "managed/role/NewRole,internal/role/openidm-cert",
"methods" : "*", // default to all methods allowed
"actions" : "*", // default to all actions allowed
}


N/A

## How do I configure specific managed objects to be case insensitive in IDM/OpenIDM (All versions)?

The purpose of this article is to provide information on making specific objects (such as user name or email) case insensitive to avoid duplicates being created where the name is the same but the case differs.

#### Background information

IDM/OpenIDM is case-sensitive. This can cause issues with search (where valid entries are not found due to their case) and also with duplicate objects being created. The search issue is addressed in the documentation: Integrator's Guide › Configuring Case Sensitivity For Data Stores and this article addresses the issue with duplicate objects.

1. Updates the object (user name in this example) so it is stored in lower case to ensure all entries are stored consistently.
2. Adds a new policy that tests uniqueness by first converting the entry to lower case before doing the comparison.

Once these changes are implemented, any new or updated entries will be checked and stored in this way to prevent duplicates. However, existing entries for this object will not be affected, so you will need to convert them to lower case to ensure lower case comparisons are meaningful.

If you store email in lower case, you will encounter issues with the self-service password reset functionality where accounts cannot be found if users enter their email in mixed case. See Converting incoming password reset requests for further information.

Finding duplicate entries

If you already have duplicate entries, it is recommended you use the REST API to search for all users and look for duplicates (using SQL queries to search the repository is not recommended because userName is stored in many tables). Once you have identified duplicate entries, you can manually clean up the data. This example command is looking for duplicate userNames and uses  jq on the command line to prettify the result (you can install jq as outlined in Download jq or just exclude | jq. from the command):

$curl -X GET -H "X-OpenIDM-Username: openidm-admin" -H "X-OpenIDM-Password: openidm-admin" "http://localhost:8080/openidm/managed/user?_queryFilter=true&_fields=userName,mail" | jq . | sort | grep userName % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 1299 0 1299 0 0 4723 0 --:--:-- --:--:-- --:--:-- 4723 "userName": "bjensen@example.com", "userName": "BJENSEN@example.com", "userName": "user001", "userName": "USER001", "userName": "jdoe", "userName": "JDoe",  ##### Note Migrating and cleaning up old data is outside the scope of ForgeRock support; if you want more tailored advice, consider engaging Deployment Support Services. #### Configuring objects to be case insensitive The following process updates the userName object to be case insensitive; the same concept can be used with other objects: 1. Define a new uniqueLC policy in the policy.js file (located in the /path/to/idm/bin/defaults/script directory) to perform a lower case comparison for uniqueness: 1. Add the following definition below the existing unique policyId in the policies definition section:  { "policyId" : "uniqueLC", "policyExec" : "uniqueLC", "policyRequirements" : ["UNIQUE_LC"] },  2. Add the following function below the existing policyFunctions.unique function in the policies function section:  policyFunctions.uniqueLC = function(fullObject, value, params, property) { var queryParams,existing,requestId,requestBaseArray; if (value && value.length) { queryParams = { "_queryFilter": property + ' eq "' + value.replace(/"/g, '\\"').toLowerCase() + '"' }; requestId = resourceName.leaf(); existing = openidm.query(resourceName.parent().toString(), queryParams); if (existing.result.length !== 0 && (!requestId || (existing.result[0]._id != requestId))) { return [{"policyRequirement": "UNIQUE"}]; } } return []; };  2. Update the object in the managed.json file (located in the /path/to/idm/conf directory) to use this new policy by replacing the unique policy with uniqueLC, for example:  "userName" : { "description" : "", "title" : "Username", "viewable" : true, "searchable" : true, "userEditable" : false, "policies" : [ { "policyId" : "uniqueLC", "params" : { } },  3. Update managed.json to store the object (userName in this example) in lower case in the repository by adding the following code to onStore:  "onStore" : { "type" : "text/javascript", "globals" : { }, "source" : "if (typeof object.userName != "undefined" && object.userName != null) { object.userName = object.userName.toLowerCase();}" },  #### Converting incoming password reset requests When a password reset request is submitted, a query is run to search for the user by email. If you store emails in lower case, you will also need to convert incoming password reset requests to lower case to prevent accounts not being found if users enter their email in mixed case. The following process enables you to convert the email received in the incoming request to lower case to ensure it matches stored emails: 1. Create a script (called submitEmail.js in this example) to convert the query string for email to lower case. For example: if (request.method == "action" && request.action == "submitRequirements" && request.content.input.queryFilter.indexOf("mail eq ") === 0) { request.content.input.queryFilter = request.content.input.queryFilter.toLowerCase(); }  2. Add the following block to router.json (located in the /path/to/idm/conf directory) to call this script when the request is made:  { "pattern": "selfservice/reset", "onRequest": { "type": "text/javascript", "file": "script/submitEmail.js" } }  The query string for email will now be converted to lower case for all incoming requests that go through the router. #### See Also #### Related Training N/A #### Related Issue Tracker IDs ## How do I stop IDM (All versions) prompting users for their current password during password reset? The purpose of this article is to provide information on configuring IDM to not prompt users for their current password when they reset it using the user password reset feature. You will need to use this configuration in situations where the user will not know their password; for example, if they log in with a social provider or if you have just imported new users into IDM. #### Configuring IDM You can configure IDM so that users are not prompted for their current password by setting the password isProtected property to false in the managed.json file (located in the /path/to/idm/conf directory). For example:  "password" : { "title" : "Password", "description" : "Password", "type" : "string", ... "isProtected": false, "usageDescription" : "", "isPersonal" : false,  Setting the isProtected property to false means users won't be asked to reauthenticate (enter their current password) when they reset their password. #### See Also #### Related Training N/A #### Related Issue Tracker IDs ## How do I manage configuration changes within a cluster in OpenIDM 3.x and 4.x? The purpose of this article is to provide information on configuration management within a cluster in OpenIDM. This information does not apply to IDM 5 and later, since IDM 5 introduced improvements to simplify the configuration and management of a cluster. #### Typical configuration The following shows a typical cluster configuration for two OpenIDM nodes: Node 1 Node 2 openidm.node.id=idm1 openidm.instance.type=clustered-first # openidm.fileinstall.enabled=false # openidm.config.repo.enabled=false # felix.fileinstall.disableConfigSave=false openidm.node.id=idm2 openidm.instance.type=clustered-additional openidm.fileinstall.enabled=false # openidm.config.repo.enabled=false # felix.fileinstall.disableConfigSave=false This node applies changes made to the JSON files on disk both at startup and runtime to the current instance and will be persisted within the repository. Changes made via REST will be persisted within the repository and written back to the on-disk JSON configuration files. This node does not apply changes made to the JSON files on disk either at startup or runtime. Changes made via REST will be persisted within the repository and written back to the on-disk JSON configuration files. Configuration properties The following configuration properties determine how and when the configuration is loaded from, or written to the on-disk JSON configuration files: Configuration property Meaning openidm.fileinstall.enabled This property specifies whether changes made to the on-disk JSON configuration files will be loaded by OpenIDM, applied to the active configuration and persisted within the repository. The default is true. Set in the system.properties file (located in the /path/to/openidm/conf directory). openidm.config.repo.enabled This property specifies whether the OpenIDM configuration will be persisted within the repository or whether it will only be stored within memory. The default is true. Set in the system.properties file (located in the /path/to/openidm/conf directory). felix.fileinstall.disableConfigSave This property specifies whether changes to the active configuration will be persisted back to the on-disk JSON configuration files. The default is true. This property actually behaves in the opposite way to what one would expect; a value of true ensures that the on-disk JSON files are updated based on the active configuration and a value of false prevents the update of the JSON files. Set in the config.properties file (located in the /path/to/openidm/conf directory). #### Known issue There is a known issue when modifying the configuration via both the Admin UI and on-disk JSON configuration files: OPENIDM-6588 (In a multi-node cluster updating a config file directly on one node does not update the corresponding file on other nodes). This issue causes the configuration for two nodes in a cluster to become out of sync at runtime. This affects behavior as follows: • Configuration changes performed via the REST interface or the Admin UI will propagate to all of the nodes within the cluster. The propagation of changes occurs via an event mechanism, which utilizes the shared repository to notify cluster instances of changes. • Configuration changes made to the on-disk JSON files, regardless of which node they occur on, will only be applied if the openidm.fileinstall.enabled property is commented out or explicitly set to true. When applied, the changes are not propagated to other nodes in the cluster and will only take immediate effect on the node where the changes occurred. ##### Note This issue has been fixed in IDM 5.0. See Release Notes › Core Releases for further information on the changes to cluster management. #### Making configuration changes For a typical cluster configuration, you should apply changes to the cluster as follows in order to ensure the configuration remains consistent across all nodes at all times: • Whenever possible, perform changes via the Admin UI in order to ensure that configuration updates are propagated to all nodes in the cluster. See OpenIDM Integrator's Guide › Configuring OpenIDM from the Admin UI for further information. • When it is necessary to modify a configuration object that is not accessible via the Admin UI: • Use a REST client (such as Postman or curl) to modify the configuration object directly. See OpenIDM Integrator's Guide › Configuring OpenIDM Over REST for further information. This is the preferred method. • Modify the on-disk JSON files directly if you are unable to or prefer not to use REST. You should follow this process: 1. Shut down all of the clustered-additional nodes and ensure that the openidm.fileinstall.enabled=false property has been set within the system.properties file on clustered-additional nodes. 2. Modify the JSON files on the clustered-first node. 3. Restart each of the clustered-additional nodes in order to reload the updated configuration from the repository. #### See Also #### Related Training N/A #### Related Issue Tracker IDs ## How do I re-create the internal OrientDB repository in IDM 5 and OpenIDM 3.x, 4.x? The purpose of this article is to provide information on re-creating the internal OrientDB® repository in IDM/OpenIDM. Although the internal repository cannot be used in production, you may want to clean and reset it for evaluation purposes. The internal OrientDB repository has been replaced with DS in IDM 5.5. #### Re-creating the internal repository ##### Caution This process will remove all data from the internal repository including linkage data. You should only proceed if you do not need to keep the existing links. You can re-create the internal repository as follows: 1. Shutdown the IDM/OpenIDM instance. 2. Delete the /path/to/idm/db/openidm directory (including all sub-directories). 3. Restart the IDM/OpenIDM instance. The startup process will load all the JSON configuration files and re-create the internal repository. #### See Also #### Related Training N/A #### Related Issue Tracker IDs N/A ## Integration with AM/OpenAM ## 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. ##### Note If you are passing a session cookie (not applicable in this example), you will need to include the X-Requested-With header as discussed in Integrator's Guide › Using Message Level Security. #### 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",
}' '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.1" '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: $ 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 -X POST -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":[]}



N/A

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

The purpose of this article is to provide assistance with setting up the OPENAM_SESSION authentication module in OpenIDM 4.5 for integration with OpenAM. 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.

#### Changes in IDM 5.x

IDM 5.5

Changes were made in IDM 5.5 to introduce a new OAUTH_CLIENT module (which replaces the OPENID_CONNECT module introduced in IDM 5) and to deprecate the OPENAM_SESSION module.

See the following documentation links for further information in IDM 5.5:

IDM 5

Changes were made in IDM 5 to introduce a new OPENID_CONNECT module and to remove the OPENAM_SESSION module integration from the UI login. This means you should only use the OPENAM_SESSION module in situations where the client application has already authenticated to OpenAM in a separate workflow; otherwise you should use the new OPENID_CONNECT module.

See the following documentation links for further information in IDM 5:

#### Configuring the OPENAM_SESSION authentication module

OpenIDM does not manage sessions (that is, it has no concept of destroying or invalidating sessions in the same way that OpenAM does).

There are three key requirements when configuring the OPENAM_SESSION authentication module to ensure it behaves as expected:

• Set the JWT_SESSION module timeouts to 5 seconds.
• Set the OPENAM_SESSION module to exclusively use OpenAM login.
• Ensure there is a user in your OpenAM identity repository that has the openidm-admin role.

Configuring the OPENAM_SESSION authentication module

You should configure the OPENAM_SESSION module per the Samples documentation: Configuring OpenIDM for the Full Stack Sample and then ensure you follow these steps:

1. Edit the authentication.json file (located in the /path/to/idm/conf directory) and set the following timeout properties to 5 seconds for the JWT_SESSION module:
                "maxTokenLifeSeconds" : "5",
"tokenIdleTimeSeconds" : "5",

For example, the configuration for this module would now look similar to this:
        "sessionModule" : {
"name" : "JWT_SESSION",
"properties" : {
"keyAlias" : "openidm-localhost",
"keystoreType" : "&{openidm.keystore.type}",
"keystoreFile" : "&{openidm.keystore.location}",
"maxTokenLifeSeconds" : "5",
"tokenIdleTimeSeconds" : "5",
"sessionOnly" : true,
}

2. Edit the ui-configuration.json file (located in the /path/to/idm/conf directory) and set the following property to true:
                "openamUseExclusively" : true,

For example, the configuration relating to the OPENAM_SESSION module would now look similar to this:
                "defaultNotificationType" : "info",
"openamUseExclusively" : true,
"openamAuthEnabled" : true,
"openamLoginLinkText" : "Login with AM"

3. Ensure there is a user in your OpenAM identity repository that has the openidm-admin role. The users in the OpenAM identity repository (typically OpenDJ) should be in sync with the users in the OpenIDM repository (the way this is reconciled will depend on which repository holds the master data in your deployment). You should ensure that one user in your OpenIDM repository has been assigned the openidm-admin role. You can either assign this role via the admin UI or REST as detailed in OpenIDM Integrator's Guide › Managing Users, Groups, Roles and Relationships › Granting a Role to a User.

N/A

N/A

## 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"

N/A

N/A

## How do I migrate my existing BPMN workflows after upgrading to IDM 5.5 or applying Security Advisory #201705?

#### Migrating a BPMN Workflow

After upgrading to IDM 5.5 or applying Security Advisory #201705, existing BPMN workflows must be modified in order to to attach a scriptTaskListener to each userTask within the workflow. The scriptTaskListener must inject any required user input within the process context, making it available to other workflow stages.

The attached workflowScriptTaskHelper.xsl file can be used to assist with migration and will automatically transform basic BPMN workflows. Complex workflows or those which do not already include a userTask may require additional manual intervention:

• On Mac® OS X® or Linux®, you must execute the following XSLT script to migrate your BPMN files:
xsltproc workflowScriptTaskHelper.xsl path/to/your/project.bpmn20.xml  | xmllint -format -

• On Microsoft® Windows®, the Microsoft Command Line Transformation Utility (msxsl.exe) can be used in conjunction with the Microsoft Core XML Services to migrate your BPMN files:
msxsl.exe path/to/your/project.bpmn20.xml workflowScriptTaskHelper.xsl -o path/to/your/updated.bpmn20.xml


N/A

N/A

## How do I use workflow scripts to make calls back to IDM/OpenIDM (All versions)?

#### Using workflow scripts to make calls back to IDM/OpenIDM

Example scripts are included in this article for the following use cases:

• How do I query IDM/OpenIDM for a list of all managed users? - this example calls openidm.query from a workflow.
• How do I query IDM/OpenIDM for a list of all managed provisioning roles? - this example calls openidm.query from a workflow.
• How do I patch a managed user to add additional roles? - this example calls openidm.patch from a workflow.
• How do I retrieve a managed user's attributes? -  this example calls openidm.query from a workflow.

Querying IDM/OpenIDM for a list of all managed users

To achieve this in a workflow, you could add the following scriptTask code to the workflow XML file:

    <scriptTask id="scripttask1" name="Read Users" scriptFormat="groovy">
<script>
params = [_queryId:'query-all-ids']
out:println "script task using resolver: " + openidm.query('managed/user', params)
execution.setVariable('params', params)
</script>
</scriptTask> 


Querying IDM/OpenIDM for a list of all managed provisioning roles

To achieve this in a workflow, you could add the following scriptTask code to the workflow XML file:

   <scriptTask id="scripttask1" name="Read Roles" scriptFormat="groovy">
<script>
params = [_queryId:'query-all-ids']
out:println "script task using resolver: " + openidm.query('managed/role', params)
execution.setVariable('params', params)
</script>
</scriptTask> 


To achieve this in a workflow, you could add the following scriptTask code to the workflow XML file:

    <scriptTask id="scripttask1" name="Patch User" scriptFormat="groovy">
<script>
patchValue = [[operation: 'replace', field:'description',value:'testing']]
out:println "script task using resolver: " + openidm.patch('managed/user/f03d01e8-b3e3-41b0-b2df-50776e9df744', null, patchValue)
execution.setVariable('patchValue', patchValue)
</script>
</scriptTask> 


Retrieving a managed user's attributes

To achieve this in a workflow, you could add the following scriptTask code to the workflow XML file:

    <scriptTask id="scripttask1" name="Retrieve Attributes" scriptFormat="groovy">
<script>
execution.setVariable("startUserFromRepo", startUserFromRepo)
</script>
</scriptTask>


N/A

## How do I use RequireJS to load dependencies inside a workflow in IDM 5.x, 6 and OpenIDM 4.x?

The purpose of this article is to provide information on loading dependencies (external libraries) inside a workflow using RequireJS. You might want to load dependencies to either reuse JavaScript® methods, or call standard jQuery or jQuery UI functions. An example is given in this article to embed the jQuery UI Datepicker function in a workflow. This information does not apply to IDM 6.5 and later because that uses the Vue JS framework.

#### Background information

• Workflow definitions are manged by Activiti; the JavaScript engines used by Activiti do not support CommonJS, which includes RequireJS. This means you need to load the RequireJS library (r.js) in order to load dependencies:
• JDK 8 uses the Nashorn JavaScript engine, which does not support CommonJS.
• JDK 7 uses the Rhino JavaScript engine bundled within the JVM; this version of Rhino is pre-CommonJS support.
• Activiti uses the JVM's ScriptEngineManager to locate a supported JavaScript engine, which means the JDK's embedded version of Rhino is always used instead of the version bundled with IDM/OpenIDM (which does support CommonJS).
• Workflow forms are loaded as follows:
1. The UI interrogates the workflow engine via a REST call.
2. It extracts the form definition from the process definition.
3. It dynamically renders it using different mechanisms based on the form type.
• The entire form file is loaded with RequireJS provided you use the recommended activiti:formKey attribute to refer to the HTML template in the workflow definition. See Integrator's Guide › Using Custom Templates for Activiti Workflows for further information.
• Module Loader is available from within the form since Module Loader has jQuery in its scope (as '$'). • jQuery is included in the UI dependencies. • jQuery-ui is not included in the UI dependencies, which means jQuery UI functions are not available by default in the UI. To use jQuery UI functions, you therefore need to load them from the form using RequireJS. #### Loading dependencies using RequireJS You can load external libraries within a workflow using RequireJS as follows, depending on where the call is coming from: • Workflow definition - scriptTask: <scriptTask id="test" name="Test Task" scriptFormat="javascript" activiti:autoStoreVariables="false"> <script> load("path/to/r.js"); require(["path/to/module"], function(module) { //some code}); </script> </scriptTask>  • Workflow XHTML form: <script> require(["path/to/module"], function(module) { //some code}); </script>   #### Datepicker example You can load jQuery UI functions using RequireJS. The following example demonstrates this by loading the jQuery UI Datepicker function into a workflow XHTML form: 1. Include the following in your workflow XHTML form to provide the Datepicker input, load the jQuery-ui library and dynamically load the CSS: <div class="form-group"> <p>Enter Date: <input type = "text" id = "datepicker"></p> </div> ... <script> function loadCss(url) { var link = document.createElement("link"); link.type = "text/css"; link.rel = "stylesheet"; link.href = url; document.getElementsByTagName("head")[0].appendChild(link); }$(document).ready(function() {
require(["https://code.jquery.com/ui/1.10.4/jquery-ui.js"], function() {
$( "#datepicker" ).datepicker(); }) }); </script>  The above example code renders a Datepicker in the workflow form as follows: #### See Also #### Related Training N/A #### Related Issue Tracker IDs N/A ## Task Scanner ## How do I configure the Task Scanner in IDM/OpenIDM (All versions) to find a user's start date between today and n number of days in the future? The purpose of this article is to provide information on configuring the Task Scanner in IDM/OpenIDM to find a user's start date between today and n number of days in the future using the sunset/date property. #### Configuring the Task Scanner You can configure the Task Scanner to find a user's start date by writing a new task scanner query. In this example, I want to match user records with a sunset date between today and 7 days in the future: 1. Create a new query in the repo.jdbc.json file (located in the /path/to/idm/conf directory) that will be invoked by the task scanner. In this example, the query is called scan-tasks-between-before-after-date and will return users (objects) whose scan property (sunset/date) is between the specified before and after dates: "scan-tasks-between-before-after-date" : "SELECT fullobject FROM${_dbSchema}.${_mainTable} obj INNER JOIN${_dbSchema}.${_propTable} prop ON obj.id = prop.${_mainTable}_id INNER JOIN ${_dbSchema}.${_propTable} complete ON obj.id = complete.${_mainTable}_id INNER JOIN${_dbSchema}.objecttypes objtype ON objtype.id = obj.objecttypes_id WHERE ( prop.propkey=${property} AND prop.propvalue <${condition.before}  AND prop.propvalue > ${condition.after} AND objtype.objecttype =${_resource} )"

2. Copy the sample configuration file (​schedule-taskscan_sunset.json) to the /path/to/idm/conf directory.
3. Update the configuration file to reference your new query and include the before and after dates within the condition property for the period you are interested in, for example:
{
"enabled" : true,
"type" : "cron",
"schedule" : "0 0 * * * ?",
"concurrentExecution" : false,
"invokeContext" : {
"waitForCompletion" : false,
"maxRecords" : 2000,
"scan" : {
"object" : "managed/user",
"property" : "sunset/date",
"condition" : {
"before" : "${Time.now + 7d}", "after" : "${Time.now  + 1d}"
},
},
"recovery" : {
"timeout" : "10m"
}
},
"script" : {
"type" : "text/javascript",
"file" : "script/sunset.js"
}
}
}
}

The ${condition.before} and${condition.after} references in your query are replaced with the values you specified in the condition property when the scan task is run.
##### Note

You must ensure you have updated your managed/user object to include a complex attribute called sunset (that maps to the taskState property) as described in FAQ: Task Scanner in IDM/OpenIDM.

N/A

N/A

## How do I convert a date stored in DS/OpenDJ to a format that the Task Scanner in IDM/OpenIDM (All versions) can use?

The purpose of this article is to provide information on converting a date stored in DS/OpenDJ to a format that the Task Scanner in IDM/OpenIDM can use. This can be useful if you want to import the date stored in DS/OpenDJ for inclusion in a Task Scanner process.

#### Converting dates

DS/OpenDJ stores dates as a string (for example, 201612062359Z), whereas the Task Scanner expects dates in the ISO 8601 Zulu time format (for example, 2016-12-06T23:59:00.000Z).

You can convert the DS/OpenDJ dates using a transform script similar to the following:

1. Create a convertdate.js file in the /path/to/idm/script directory with the following contents:
var ldapDate = source.dateTest;
var openIdmDate = "";

openIdmDate = ldapDate.replace(/^([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})Z$/, "$1-$2-$3T$4:$5.00.000Z");

openIdmDate;

2. Change the configuration of the required DS/OpenDJ date attribute(s) in the sync.json file (located in the /path/to/idm/conf directory) to use the new transform script. This example uses an attribute called startDate:
{
"source" : "",
"transform" : {
"type" : "text/javascript",
"file" : "script/convertdate.js"
},
"target" : "startDate"
},


You can convert the IDM/OpenIDM date back to the DS/OpenDJ format if you want to write the attribute back to DS/OpenDJ using another transform script similar to the following:

ldapDate = openIdmDate.replace(/^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2}).([0-9]{3})Z$/, "$1$2$3$4$5")


N/A

N/A

## FAQ: General IDM/OpenIDM

The purpose of this FAQ is to provide answers to commonly asked general questions regarding IDM/OpenIDM.

#### Q. Are there any restrictions on the characters that can be included in the userName attribute?

A. The restrictions on userName and other managed object attributes are configured in managed.json (IDM / OpenIDM 4.x) or policy.json (OpenIDM 3.x); these files are located in the /path/to/idm/conf directory. By default, userName is configured so that it is:

• required
• not-empty
• unique
• no-internal-user-conflict
• does not contain the the backslash ("/") character

You can customize these policies in managed.json or policy.json, and policy.js.

##### Note

If the DS/OpenDJ Attribute Value Uniqueness plugin has been configured for the attribute mapped to IDM/OpenIDM's userName, then DS/OpenDJ will not allow the creation of more than one account with the same value for this attribute. See Administration Guide › Implementing Attribute Value Uniqueness for further information.

#### Q. What is the purpose of the lastSync attribute?

A. The lastSync attribute was introduced in OpenIDM 4.5 for user managed objects and is used as the state in a managed object to remember what assignments were pushed to the target resources, on a per mapping basis. This attribute resolves issues with role assignments in earlier versions of OpenIDM that occurred when local updates to a managed user were performed, but implicit sync was disabled on the mapping; this meant that the change event was forgotten on the next reconciliation, which resulted in divergences between the source and target assignment, especially when "mergeWithTarget" and "removeFromTarget" strategies were selected.

You must not remove this attribute as it could cause future upgrades to fail.

#### Q. Why can't users log in to IDM/OpenIDM with their existing passwords once they have been synced from DS/OpenDJ?

A. When users are synced from DS/OpenDJ, the users will exist in IDM/OpenIDM but cannot log in until their password has been changed. This is because user passwords in DS/OpenDJ are one-way encrypted and cannot be retrieved until a password change has occurred. Additionally, you must be using the LDAP Passthrough authentication method. See Integrator's Guide › Managing Authentication, Authorization and Role-Based Access Control › Supported Authentication Modules for further information.

You can configure a password policy to force users to change their password when they next login. See Integrator's Guide › Managing Passwords › Enforcing Password Policy for further information.

#### Q. Can dynamically assigned roles (via effectiveRoles.js) be used to authorize external REST requests?

A. No, this is a known limitation of effectiveRoles.js.

#### Q. Is Elasticsearch 6 supported for audit logging?

A. No, Elasticsearch 6.x is not currently supported for audit logging because 6.0 introduced a breaking change with regards to how indices are handled (you can now only have one _type per index). An RFE exists to provide this support in a future release: CAUD-424 (ElasticSearch Audit Handler: provide support for ElasticSearch 6.0).

Per the Elasticsearch documentation (Removal of mapping types):

Indices created in Elasticsearch 6.0.0 or later may only contain a single mapping type. Indices created in 5.x with multiple mapping types will continue to function as before in Elasticsearch 6.x. Mapping types will be completely removed in Elasticsearch 7.0.0.

This is considered a "phased roll-in" intended to give vendors and implementers some phase-in time. As a result, a possible workaround is to create the index in Elasticsearch 5 and then upgrade to Elasticsearch 6.

#### Q. What values can I use when specifying rotation times and intervals for audit logs?

A. For rotationTimes, rotationInterval and rotationRetentionCheckInterval, you can specify the time period using the following units:

Time Period Unit
Day "days", "day", "d"
Hour "hours", "hour", "h"
Minutes "minutes", "minute", "min", "m"
Seconds "seconds", "second", "sec", "s"
Miliseconds "milliseconds", "millisecond", "millisec", "millis", "milli", "ms"
Microseconds

"microseconds", "microsecond", "microsec", "micros", "micro", "us", "\u03BCs", "\u00B5s"

The last two support 'mu' and 'micro sign' abbreviations.

Nanoseconds "nanoseconds", "nanosecond", "nanosec", "nanos", "nano", "ns"
##### Note

rotationRetentionCheckInterval cannot be left blank; a reasonable value for this would be 5 seconds but could be set to 5 minutes or more depending on how you have the rotation interval configured.

See Integrator's Guide › Audit Log Reference › Audit Event Handler Configuration for further information.

#### Q. What values can I use when specifying the rotationFileSuffix for audit logs?

A. The rotationFileSuffix should be a timestamp, where the allowed values comply with the Java SimpleDateFormat syntax. The default suffix format is -yyyy.MM.dd-HH.mm.ss.

#### Q. Why are the timestamps displayed in the audit log and openidm log different?

A. The timestamps used in the logs are different as the logs serve different purposes:

• Audit logs use timestamps in UTC format (for example, 2018-07-18T08:48:00.160Z); UTC is a unified standard that is not affected by daylight saving time changes. The format used in audit logs is not configurable since UTC provides the consistency needed for auditing when IDM servers are deployed globally across different timezones.
• openidm log uses the system time since it is primarily used for diagnosing issues where local timestamps are needed in troubleshooting analysis.

This does mean that timestamps will be different if your system uses a format other than UTC.

#### Q. Does IDM/OpenIDM provide protection against XSS, SQL injection and CSRF attacks?

A. Yes, IDM/OpenIDM provides protection as follows:

SQL injection

IDM/OpenIDM JDBC repositories use prepared statements (where input is parameterized appropriately) to prevent SQL injection. However, you do still need to set appropriate authorization settings to only allow required access. The recommended way of allowing access is to change the default to allow nothing and then use the white list to make functionality accessible as needed. If you build your own scripted SQL connectors, you should ensure that these queries are parameterized in a similar way to those provided.

XSS

The ForgeRock UI has been hardened against XSS and we are not aware of any exploits; it has been submitted to white hat review and they have confirmed this.

CSRF

See How does IDM/OpenIDM (All versions) protect against CSRF attacks? for further information.

#### Q. Can I use the openidm_proxy user in IDM/OpenIDM?

A. No, the openidm_proxy user is a left over artifact from functionality that was never implemented. It has now been removed from the openidm.sql script and will no longer be created as detailed in OPENIDM-1590 (openidm_proxy user created in openidm.sql script is not required and should be removed).

## FAQ: Installing and configuring IDM/OpenIDM

The purpose of this FAQ is to provide answers to commonly asked questions regarding installing and configuring IDM/OpenIDM.

#### Q. Is IDM/OpenIDM compatible with Oracle Java Development Kit (JDK) 11?

A. Yes, as of IDM 6.5, Oracle JDK 11 is supported. You should only use supported versions to prevent compatibility issues.

#### Q. Can IDM/OpenIDM be used with OpenJDK?

A. Yes, OpenJDK is supported in IDM/OpenIDM. See Release Notes › Preparing the Java Environment for details of versions.

#### Q. How do I integrate IDM, AM and DS?

A. You should refer to ForgeRock Identity Platform Version 6: Integrating IDM, AM, and DS or Integrating IDM, AM, and DS (version 5.5), which collects the information you need to set up integration in one place. For additional features, refer to the following chapters from IDM documentation: Samples Guide › Integrating IDM With the ForgeRock Identity Platform and the Integrator's Guide › Setting Up User-Managed Access (UMA), Trusted Devices, and Privacy.

See How does the OIDC authorization flow work when IDM (All versions) is integrated with AM? for further information.

#### Q. Do I need to change the default symmetric encryption key for production?

A. No, you do not. IDM/OpenIDM generates a symmetric key and a private key the first time the server is started. See How do I change the symmetric key in IDM/OpenIDM (All versions)? for further information.

However, you should change the default keystore password as per: How do I change the default keystore password in IDM/OpenIDM (All versions)?

#### Q. Does IDM/OpenIDM support encryption keys with 256-bit AES encryption?

A. Yes, IDM/OpenIDM does support keys with 256-bit AES encryption and as of Java 9, so does Java. With earlier versions of Java, you must install the Oracle Java JCE unlimited strength jars if you want to use keys with 256-bit AES encryption. See Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files Download for further information and links to download the jars.

#### Q. How do I configure IDM/OpenIDM for case insensitive searching?

A. IDM/OpenIDM is case-sensitive, but this can cause issues where valid entries are not found due to their case. This issue also affects queries done using queryFilter as the case-sensitivity of queryFilter depends on the repository's collation. You can resolve this by configuring the repository for case sensitivity as detailed in Integrator's Guide › Configuring Case Sensitivity For Data Stores.

#### Q. Can IDM/OpenIDM be configured to use multiple OpenICF Connector servers and failover with Active Directory Domain Controllers?

A. No, IDM/OpenIDM can only use one OpenICF Connector server at a time. For failover purposes, you should have two or more Active Directory Domain Controllers (DC) with the OpenICF Connector server installed and if one becomes unavailable, your system administrator should change the target IP to another available DC.

#### Q. Can you configure IDM/OpenIDM reconciliation to continue implicit synchronization even when failure occurs?

A. No, IDM/OpenIDM performs implicit synchronization on an all or nothing basis according to the failure compensation configuration. There is no way to have implicit synchronization occur on specific objects within a mapping but not others.

#### Q. How do I configure IDM/OpenIDM to handle large data sets for reconciliation?

A. You should refer to the documentation for information on improving reconciliation performance in your version of IDM/OpenIDM:

See How do I identify reconciliation performance issues in IDM/OpenIDM (All versions)? for further information on troubleshooting reconciliation performance.

## FAQ: Clusters in IDM/OpenIDM

The purpose of this FAQ is to provide answers to commonly asked questions regarding clusters in IDM/OpenIDM. Clusters are used to provide high availability in IDM/OpenIDM.

#### Q. What are the main features of a cluster configuration?

A. The main features of a cluster configuration are:

#### Q. How does the keystore get loaded in a clustered environment?

A. The keystore is handled differently depending on which version of IDM/OpenIDM you are using.

IDM 5 and later

As of IDM 5, the OpenIDM keystore is no longer persisted in the repository. In a clustered environment, you must copy the initialized keystore to each instance in the cluster or point to a single, centralized keystore. See Integrator's Guide › Configuring an IDM Instance as Part of a Cluster for more information.

Pre-IDM 5

In earlier versions of OpenIDM, you have different types of instance (clustered-first and clustered-additional), which affects how the keystore is loaded. The keystore is loaded as follows, which explains why it is important to always start the clustered-first node before any other nodes:

clustered-first node:

• The Crypto Service activates and generates a new secret key (if not present).
• The Security Manager activates and generates a new private key (if not present), reloads the keystore within the JVM, and stores the entire keystore in the following file: security/keystore.jceks.
• Normal operation follows.

• The Crypto Service activates, but does not generate, a new secret key.
• The Crypto Service does not add any decryptionTransformers.
• The Security Manager performs the following tasks:
• Activates and reads in the keystore from the repository.
• Overwrites the local keystore.
• Reloads the keystore within the JVM.
• Calls the Crypto Service to update the keySelector with the new keystore. It also adds adecryptionTransformer to allow the keys to be decrypted.

See OpenIDM Integrator's Guide › Configuring an OpenIDM Instance as Part of a Cluster for further information.

#### Q. What does IDM/OpenIDM's cluster management service do?

A. The cluster management service performs the following tasks:

• Detects when a node has failed or timed out.
• Notifies other components (for example, the scheduler) about a node failure.
• Provides a REST interface for getting information about the cluster. See Integrator's Guide › Managing Nodes Over REST for further information.

The logic for managing the cluster is defined in the cluster.json file. See IDM Integrator's Guide › Configuring an IDM Instance as Part of a Cluster or OpenIDM Integrator's Guide › Editing the Cluster Configuration File for further information depending on your version.

#### Q. Do nodes in a cluster share the same configuration?

A. Yes, the configuration should always be the same; this is achieved by directing each instance to the same database.

Configuration is found in the following three locations:

• Database - this configuration is always the same since it is shared. It is initially loaded from the filesystem configuration on the cluster-first node and propagated to the other (additional) nodes.
• Configuration on filesystem - this configuration can diverge in pre-IDM 5. See How do I manage configuration changes within a cluster in OpenIDM 3.x and 4.x? for further information on this divergence and how to prevent it.
• Configuration in memory - this configuration could diverge if an instance gets cut from its cluster due to a networking issue or a misconfigured load balancer; in which case, changes from the database may not be detected and therefore, the configuration in memory will not be updated.

#### Q. How do I upgrade nodes in a cluster?

A. Updating nodes from a cluster is not presently supported. As a general practice, do not apply the update process to more than one node in a cluster. if you're updating a cluster, follow these steps:

1. Redirect client traffic to a different IDM/OpenIDM system or cluster.
2. Shut down every node in the cluster you want to upgrade.
3. Upgrade a single node in the cluster.
4. Clone the upgraded node to the other IDM/OpenIDM instances in the cluster.
5. Redirect client traffic back to the upgraded cluster.

See Installation Guide › Updating Servers for further details.

#### Q. Can I configure a cluster over multiple subnets or data centers?

A. IDM/OpenIDM clustering requires a shared repository for all of the nodes in the cluster and otherwise does not have any direct communication between the nodes. Therefore configuring a cluster on multiple subnets versus a single subnet should effectively be the same. Please ensure you still observe the following cluster requirements (from the documentation):

##### Caution

Clustering across multiple subnets has not been configured or tested by us; it is strongly recommended that you test this configuration in a development environment first to ensure it meets your needs.

#### Q. How do I stop LiveSync running the same scheduled job on multiple nodes in a cluster?

A. You must ensure the persisted property is set to true in the schedule file (for example, the schedule-livesync.json file):

{
"enabled"             : true,
"persisted"           : true,
...
}


If this property is excluded or set to false, LiveSync will process changes concurrently.

See Integrator's Guide › Configuring Persistent Schedules for further information.

#### Q. Why am I seeing errors about current Object revision being different than expected during synchronization?

A. When you are synchronizing changes in a clustered environment, you may see errors such as:

Update rejected as current Object revision 293 is different than expected by caller 291, the object has changed since retrieval.

This could happen in the following scenario:

1. Node 1 starts a sync task and reads the source user that has changed.
2. Node 2 starts a sync task and completes it.
3. Node 1 then finishes processing but cannot save because the object has changed since it was read, resulting in the revision clash.

Or, where both nodes are running a LiveSync against the same system object, causing the LiveSync token version to change before one of the nodes has a chance to update it.

Providing you are not experiencing any other issues, such as users not being synced correctly, you can ignore these errors.

N/A

## FAQ: Task Scanner in IDM/OpenIDM

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

#### Q. What date format is used in the Task Scanner for dates such as the sunset/date property?

A. All dates in the Task Scanner, including the sunset/date property, use the ISO 8601 Zulu time format (for example, 2017-12-06T23:59:00.000Z). An example sunset/date property looks like this in the managed/user object:

"sunset": {
"date": "2017-08-01T12:00:00.000Z",
},


#### Q. What is the taskState property used for in the sample configuration file?

A. The taskState property in the sample configuration file (schedule-taskscan_sunset.json) references the variable names (sunset/task-started and sunset/task-completed) that are used in the managed/user object:

"taskState" : {
},


These variables are used to store the Task Scanner start message (date and time) and completed message (date and time) in the sunset/date property in the managed/user object (see example above).

#### Q. Do I need to change the managed/user object to use the sample configuration file provided with IDM/OpenIDM?

A. Yes, you need to add an object attribute called sunset that maps to the taskState property included in the sample configuration file (schedule-taskscan_sunset.json). An example user record with this sunset object attribute included looks like this:

{
"phoneNumber": "12345678",
"familyName": "Full",
"givenName": "Moon",
"sunset": {
"date": "2017-01-01T12:00:00.000Z"
},
"active": "true",
"email": "moony@example.com",
"accountStatus": "active",
"roles": "internal/role/openidm-authorized",
"lastPasswordAttempt": "Mon Nov 06 2017 20:16:41 GMT+0200 (CEST)"
}

##### Note

The task-completed and task-started attributes must be set to null initially for the Task Scanner to use them correctly.

Once you have added this object attribute, the task-started and task-completed variables in the managed/user object are updated each time the task runs.

#### Q. How do I refer to task-started and task-completed in the .js script given that dashes are not permitted in JavaScript variable names?

A. You must refer to these variables as follows: ['task-started'] and ['task-completed'] in the .js script called from the configuration file, otherwise your script will not be valid.

If you do not include these variables correctly, you will see the following error when IDM/OpenIDM starts:

SEVERE: OpenIDM failure during startup, ACTIVE_NOT_READY: Required services
not all started [org.forgerock.openidm.managed] 


#### Q. How is the task-completed date used?

A. The task-completed date is used in the scan-tasks query, which is specified in the database configuration file (repo.jdbc.json - located in the /path/to/idm/conf directory). For example:

"scan-tasks" : "SELECT fullobject FROM ${_dbSchema}.${_mainTable} obj INNER JOIN ${_dbSchema}.${_propTable} prop ON obj.id = prop.${_mainTable}_id LEFT OUTER JOIN${_dbSchema}.${_propTable} complete ON obj.id = complete.${_mainTable}_id AND complete.propkey=${taskState.completed} INNER JOIN${_dbSchema}.objecttypes objtype ON objtype.id = obj.objecttypes_id WHERE ( prop.propkey=${property} AND prop.propvalue <${condition.before} AND objtype.objecttype = ${_resource} ) AND ( complete.propvalue is NULL )",  This example scan-tasks query means only managed users who have not already been scanned (that is, with a null "taskState.completed") are selected. #### See Also #### Related Training ## FAQ: IDM/OpenIDM compatibility with third-party products The purpose of this FAQ is to provide answers to commonly asked questions regarding IDM/OpenIDM compatibility with third-party products. #### Frequently asked questions #### Q. What repositories are supported in production? A. For IDM 6, the following repositories are supported for use in production: • DS 6.5 - by default, IDM uses an embedded DS instance for testing purposes. The embedded instance is not supported in production. If you want to use DS as a repository in production, you must set up an external instance: Installation Guide › Using an External DS Repository. • Oracle MySQL™ version 5.6 and 5.7 with MySQL JDBC Driver Connector/J 5.1.18 or later • MariaDB version 10.0, 10.1 and 10.2 with MySQL JDBC Driver Connector/J 5.1.18 or later • Microsoft® SQL Server™ 2012, 2014 and 2016 • Oracle Database 11gR2 and 12c, 12c Release 1 (12.1), and 12c Release 2 (12.2) • PostgreSQL® 9.3.10, 9.4.5, 9.6 and 10 • IBM® DB2, 10.1, 10.5 and 11 For other versions of IDM/OpenIDM, you should check the Release Notes › Before You Install section in the applicable release notes. #### Q. Is Amazon Web Services (AWS) RDS supported for production use in IDM/OpenIDM? A. The repositories supported for IDM/OpenIDM are also supported in the cloud, which includes AWS RDS. Within AWS RDS, there are several databases available, including AWS Aurora. See Amazon Relational Database Service (RDS) for further information. However, any configuration issues specific to these cloud-based repositories are outside the scope of ForgeRock support; if you want more tailored advice, consider engaging Deployment Support Services. ##### Note There is a known performance issue using AWS Aurora PostgreSQL 1.1 (compatible PostgreSQL v9.6.6) If you are using this version as a repository, you should upgrade to AWS Aurora PostgreSQL 1.3 (compatible PostgreSQL v9.6.9) to avoid introducing performance impacts. See Amazon Aurora PostgreSQL updates Version 1.3: Fixed a known performance limitation on heavy write workloads that caused waits on the LWLock:buffer_content and IO:ControlFileSyncUpdate events. #### Q. Does IDM/OpenIDM support MySQL clusters for high availability? A. IDM/OpenIDM has not been tested with MySQL clusters. An RFE has been raised for this: OPENIDM-2661 (Need support for clustered mysql repository). #### Q. What version of Activiti is used with IDM/OpenIDM? A. IDM/OpenIDM uses Activiti 5.15. #### Q. Does IDM/OpenIDM support a remote Activiti installation? A. No, remote Activiti installations have not been tested with the cREST (Commons REST) API. #### Q. Does IDM/OpenIDM support the NDB Cluster engine? A. No, the NDB Cluster engine is not supported; IDM/OpenIDM currently only supports the InnoDB engine for MySQL. #### Q. Is IDM/OpenIDM FIPS 140-2 compliant? A. ForgeRock conforms to FIPS 140-2 for encryption and hashing ciphers for both inflight messaging, protocol tunnels and credential storage. In addition, the ForgeRock solution has been certified in deployments against rigorous DoD STIG requirements and is in process at FedRAMP certification. All of these certifications require proper FIPS 140-2 compliance. The solution allows deployments to choose ciphers; the most common ones used in deployments tend to be SHA-256 and AES-256, however we support stronger key lengths on both of these. A common trend for mobility is support for elliptical curve cryptography due to its high security yet low process power nature and of course is also recommended by NIST as part of FIPS 140-2. Regarding FIPS 140-2 certification, ForgeRock does not write its own crypto modules, but our software can utilize underlying crypto modules (usually those associated with Java®) which have options to be executed in FIPS-compliant mode. #### See Also #### Related Training N/A ## Known Issues ## AM 5.x and 6.0.0.x, IDM 6.x and Rest2LDAP cannot connect to DS 5.x or 6 after restricting DS cipher suites or Java upgrade The purpose of this article is to provide assistance if connections to DS fail with a java.io.EOFException after restricting cipher suites in DS, installing DS using Production mode or upgrading to Java® JDK 11 or JDK 1.8.0_192 (or later). This issue affects various use cases including AM connecting to a DS configuration store, identity store, CTS store and so on; IDM connecting to an external DS repository or connections to DS using the Rest2LDAP gateway servlet. #### Symptoms A java.io.EOFException occurs before an SSL connection is established. You will see this error occurring in different logs depending on what is trying to connect to DS. AM If you are using DS as an identity store, you will notice that you cannot see any identities in the repository. You will also see the following Connect Errors in the CoreSystem, IdRepo or Session debug logs depending on what type of stores you are using DS for (configuration, identity or CTS): Connect Error: No operational connection factories available at org.forgerock.opendj.ldap.LdapException.newLdapException(LdapException.java:206) at org.forgerock.opendj.ldap.LdapException.newLdapException(LdapException.java:144) at org.forgerock.opendj.ldap.LdapException.newLdapException(LdapException.java:113) at org.forgerock.opendj.ldap.LoadBalancer.getMonitoredLdapClient(LoadBalancer.java:411) at org.forgerock.opendj.ldap.LoadBalancer.access$3300(LoadBalancer.java:68)
at org.forgerock.opendj.ldap.LoadBalancer$LdapClientSocketImpl.getLoadBalancedContext(LoadBalancer.java:787) at org.forgerock.opendj.ldap.LoadBalancer$LdapClientSocketImpl.lambda$getLoadBalancedContext$4(LoadBalancer.java:797)
...
Caused by: Connect Error: The LDAP connection has failed because an error occurred during the SSL handshake: java.io.EOFException
at org.forgerock.opendj.ldap.LdapException.newLdapException(LdapException.java:206)
at org.forgerock.opendj.ldap.LdapException.newLdapException(LdapException.java:144)
at org.forgerock.opendj.ldap.LdapException.newLdapException(LdapException.java:113)
at org.forgerock.opendj.grizzly.GrizzlyLdapSocketConnector$CompletionHandlerAdapter$1.failed(GrizzlyLdapSocketConnector.java:274)
... 28 more
Caused by: java.io.EOFException
... 27 more


IDM

You will see the following errors in openidm0.log after starting IDM:

May 28, 2019 2:27:01 PM org.glassfish.grizzly.filterchain.DefaultFilterChain execute
FEIN: GRIZZLY0013: Exception during FilterChain execution
java.io.EOFException
at org.glassfish.grizzly.ssl.SSLBaseFilter$SSLTransportFilterWrapper.handleRead(SSLBaseFilter.java:1145) at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
...

May 28, 2019 2:27:01 PM org.forgerock.openidm.repo.opendj.impl.OpenDJRepoService waitForConnection
WARNUNG: Unable to get DS connection. Next attempt at Tues May 28 14:28:01 CEST 2019


Rest2LDAP

You will see connect errors similar to the following on the Rest2LDAP side if logging has been enabled:

29-May-2019 15:07:42.780 WARNING [OpenDJ LDAP SDK Client Selector(1) SelectorRunner] org.forgerock.i18n.slf4j.LocalizedLogger.warn Connection factory 'CachedConnectionPool(size=0[in:0 + out:0 + pending:0], maxSize=24, blocked=0, ldapClient=org.forgerock.opendj.ldap.LdapClientImpl@2517fc05)' is no longer operational: Connect Error


You can enable logging in the Rest2LDAP gateway servlet (if it runs in the Apache Tomcat™ web container) by specifying logging properties in the logging.properties file (located in the WEB-INF/classes directory where the gateway servlet is deployed).

SSL debugging - AM

If you enable SSL debug logging for AM, you will just see that the secure ciphers are being ignored, for example:

Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384


You can enable SSL debug logging as described in FAQ: SSL/TLS secured connections in AM/OpenAM and Policy Agents (Q. How do I debug SSL connection issues?).

SSL debugging - DS

If you enable SSL debug logging for DS, you may see errors similar to the following in the DS server.out log:

%% Initialized:  [Session-7, SSL_NULL_WITH_NULL_NULL]
LDAPS 0.0.0.0 port 40636(2) SelectorRunner, fatal error: 40: no cipher suites in common
javax.net.ssl.SSLHandshakeException: no cipher suites in common
%% Invalidated:  [Session-7, SSL_NULL_WITH_NULL_NULL]
LDAPS 0.0.0.0 port 40636(2) SelectorRunner, SEND TLSv1.2 ALERT:  fatal, description = handshake_failure
LDAPS 0.0.0.0 port 40636(2) SelectorRunner, WRITE: TLSv1.2 Alert, length = 2
LDAPS 0.0.0.0 port 40636(2) SelectorRunner, fatal: engine already closed.  Rethrowing javax.net.ssl.SSLHandshakeException: no cipher suites in common
Using SSLEngineImpl.


You can enable SSL debug logging as described in FAQ: SSL certificate management in DS/OpenDJ (Q. How do I debug a SSL handshake error?).

Additionally, the server.out log does not show the more secure cipher suites that have been enabled.

#### Recent Changes

Upgraded to JDK 1.8.0_192 or later, or JDK 11.

Restricted cipher suites in DS to more secure ones such as TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, which use protocol version TLSv1.2.

Installed DS using the --productionMode setup option (which restricts the available ciphers and forces the protocol version to TLSv1.2).

#### Causes

AM connects to DS using the embedded LDAP SDK and IDM connects to DS using the Grizzly LDAP connector (which in turn uses the Rest2LDAP servlet).

These mechanisms for connecting to DS securely do not correctly support the TLSv1.2 protocol, whereas using the more secure ciphers and installing DS in production mode forces the protocol version to TLSv1.2. In Java versions prior to JDK 1.8.0_192, unsupported cipher suites were simply ignored, which is why these connections continued to work despite the mismatch in protocol versions.

Changes were introduced in JDK 1.8.0_192 (JDK-8162362 : Introduce system property to control enabled ciphersuites), which changed how the JDK determined which cipher suites (and resulting protocol) to use. As a consequence of these Java changes, AM, IDM and the Rest2LDAP cannot communicate with DS using a SSL/TLS secured connection because it uses different cipher suites and protocol to the DS server; both the client and server must support the same cipher suites and protocol agreed upon when attempting to establish a secure connection.

#### Solution

This issue can be resolved by as follows:

• If you are experiencing this specific issue with AM connecting to DS, this can be resolved by upgrading to AM 6.5 or later; you can download this from BackStage.
• If you are experiencing this specific issue with IDM or Rest2LDAP connecting to DS, this can be resolved by upgrading to DS 6.5 or later; you can download this from BackStage.

Workaround

You can workaround this issue using one of the following options:

• Downgrade to JDK 1.8.0_191 or earlier.
• Add one or more cipher suites that use the TLSv1.1 or TLSv1.0 protocol version, for example: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, and so on. See Security Guide › TLS Protocols and Cipher Suites for further information. You should review any security risks of using alternative cipher suites before proceeding.
##### Note

Java 8 does not support keys with 256-bit AES encryption by default, so you may need to install the Oracle® Java JCE unlimited strength jars if you want to use keys with 256-bit AES encryption. See Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files Download for further information and links to download the jars.

N/A

## SSLHandshakeException or ClassCastException when using an HSM and Java 11 with ForgeRock products

The purpose of this article is to provide assistance if you encounter an SSLHandshakeException or ClassCastException when using a Hardware Security Module (HSM) via the PKCS11 module with Java® 11. This issue affects all ForgeRock products that are compatible with Java 11 (AM, DS, IDM and IG 6.5 and later).

#### Symptoms

In DS/OpenDJ, you will see the following in the logs:

Unable to connect to the server: 91 (Connect Error) Additional Information: The LDAP connection has failed because an error occurred during the SSL handshake: java.io.EOFException


If you enable SSL debug logging, you will see one of the following errors depending on whether you are using TLS 1.3 or storing EC keys:

• Using TLS 1.3 with Java 11:
javax.net.ssl.SSLHandshakeException: Cannot produce CertificateVerify signature
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:321)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:264)
at java.base/sun.security.ssl.CertificateVerify$T13CertificateVerifyMessage.<init>(CertificateVerify.java:905) at java.base/sun.security.ssl.CertificateVerify$T13CertificateVerifyProducer.onProduceCertificateVerify(CertificateVerify.java:1077)
at java.base/sun.security.ssl.CertificateVerify$T13CertificateVerifyProducer.produce(CertificateVerify.java:1070) at java.base/sun.security.ssl.SSLHandshake.produce(SSLHandshake.java:436) at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.goServerHello(ClientHello.java:1224)
at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.consume(ClientHello.java:1160) at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.onClientHello(ClientHello.java:849)
at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.consume(ClientHello.java:810) at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392) at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:444) at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:421) at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:178) at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:164) at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1152) at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1063) at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:402) at TLSServer$ServerThread.run(TLSServer.java:92)
Caused by: java.security.InvalidKeyException: No installed provider supports this key: sun.security.pkcs11.P11Key$P11PrivateKey at java.base/java.security.Signature$Delegate.chooseProvider(Signature.java:1163)
at java.base/java.security.Signature$Delegate.engineInitSign(Signature.java:1204) at java.base/java.security.Signature.initSign(Signature.java:546) at java.base/sun.security.ssl.SignatureScheme.getSignature(SignatureScheme.java:473) at java.base/sun.security.ssl.CertificateVerify$T13CertificateVerifyMessage.<init>(CertificateVerify.java:895) 

• Storing EC keys in the PKCS11 module and using Java 11:
java.lang.ClassCastException: class sun.security.pkcs11.P11Key$P11PrivateKey cannot be cast to class java.security.interfaces.ECPrivateKey (sun.security.pkcs11.P11Key$P11PrivateKey is in module jdk.crypto.cryptoki of loader 'platform'; java.security.interfaces.ECPrivateKey is in module java.base of loader 'bootstrap')
at java.base/sun.security.ssl.SignatureScheme.getPreferableAlgorithm(SignatureScheme.java:436)
at java.base/sun.security.ssl.CertificateVerify$T13CertificateVerifyMessage.<init>(CertificateVerify.java:867) at java.base/sun.security.ssl.CertificateVerify$T13CertificateVerifyProducer.onProduceCertificateVerify(CertificateVerify.java:1077)
at java.base/sun.security.ssl.CertificateVerify$T13CertificateVerifyProducer.produce(CertificateVerify.java:1070) at java.base/sun.security.ssl.SSLHandshake.produce(SSLHandshake.java:436) at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.goServerHello(ClientHello.java:1224)
at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.consume(ClientHello.java:1160) at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.onClientHello(ClientHello.java:849)
at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.consume(ClientHello.java:810)   You can enable SSL debugging as indicated in the following articles depending on your product: #### Recent Changes Upgraded to Java 11. Implemented an HSM via the PKCS11 module and kept the default protocol (TLS 1.3 is the default protocol used for a PKCS11 HSM). Used EC keys stored in PKCS11. #### Causes There are two JDK bugs that are causing these issues: These errors are a result of bugs in the JDK rather than being issues with ForgeRock products. #### Solution Until the JDK bugs are fixed, you can workaround these issues as follows: • SSLHandshakeException error - you can either use TLS 1.2 or you can downgrade Java to JDK 1.8. • ClassCastException error - the only workaround for this issue is to downgrade Java to JDK 1.8. #### See Also #### Related Training N/A #### Related Issue Tracker IDs ## An illegal reflective access operation has occurred when using Java 11 with ForgeRock products The purpose of this article is to provide assistance if you encounter "An illegal reflective access operation has occurred" warning when using ForgeRock products with Java® 11. This issue affects AM 6.5.x, DS 6.5.x, IDM 6.5.x, IG 6.5.x and Java Agent 5.6.x. #### Symptoms You will see An illegal reflective access operation has occurred warning when installing and using AM (including Amster and ssoadm tools), Java Agents, DS, IDM and IG. The subsequent two lines following this warning vary depending on which product you are using and what you were doing at the time it occurred. Here are some examples of the types of error you will see by product: • AM: WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by org.codehaus.groovy.vmplugin.v7.Java7$1 (file:/path/to/tomcat/webapps/openam/WEB-INF/lib/groovy-2.4.6.jar (about:blank)) to constructor java.lang.invoke.MethodHandles$Lookup(java.lang.Class,int) WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.vmplugin.v7.Java7$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

• Java Agent:
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.forgerock.openam.sdk.com.google.inject.internal.cglib.core.$ReflectUtils$1 (file:/tmp/5.6.0/java/java_agents/tomcat_agent/lib/jee-agents-installtools-5.6.0.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of org.forgerock.openam.sdk.com.google.inject.internal.cglib.core.$ReflectUtils$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

• DS:
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.opends.server.util.Platform$PlatformIMPL (file:/path/to/ds/lib/opendj.jar) to constructor sun.security.tools.keytool.CertAndKeyGen(java.lang.String,java.lang.String) WARNING: Please consider reporting this to the maintainers of org.opends.server.util.Platform$PlatformIMPL
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

• IDM:
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.apache.felix.framework.ext.ClassPathExtenderFactory$DefaultClassLoaderExtender (file:/path/to/idm/bin/felix.jar) to method java.net.URLClassLoader.addURL(java.net.URL) WARNING: Please consider reporting this to the maintainers of org.apache.felix.framework.ext.ClassPathExtenderFactory$DefaultClassLoaderExtender
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release


#### Recent Changes

Installed AM 6.5.x, DS 6.5.x, IDM 6.5.x or IG 6.5.x with Java 11.

Installed Java Agent 5.6.x with Java 11.

#### Causes

These warnings occur when using Groovy with Java 11. For reference, these known issues are:

Whenever you use functionality that accesses Groovy scripting, you will see these warnings.

Additionally, there is a similar compatibility issue with Felix: FELIX-5765 (An illegal reflective access operation has occurred).

#### Solution

These messages can be safely ignored because they do not impact the use or functionality of ForgeRock products. However, if you do not want to see them, you can downgrade Java to JDK 1.8 or whitelist these warnings.

N/A

## Property substitutions no longer work in system configuration files in IDM 5.5 and 6.x

#### Symptoms

Variables that have been defined in boot.properties are no longer resolved when configuration data is retrieved with REST calls or openidm.read. For example, using an openidm.read() call with the variable in the form &{idm.variable.name} does not result in the expected property value being substituted and instead the literal &{idm.variable.name} is returned.

#### Recent Changes

Upgraded to IDM 5.5 or later.

#### Causes

Changes have been made to how system properties are read and variables are no longer automatically substituted. This change makes it easier to administer configurations via REST since you can now configure one server, retrieve the configuration and push it to another server (previously this was not possible since the variables were automatically substituted meaning what you retrieved could not be applied to other servers). Additionally, this change improves security as there is no longer a risk of exposing substituted values over REST, which could contain sensitive data such as passwords.

#### Solution

This issue can be resolved by using the identityServer.getProperty method to resolve variables in system configuration files.

N/A

## Finding org.forgerock.json.crypto.JsonCryptoException: Decryption failed errors in IDM/OpenIDM

The purpose of this article is to provide assistance if you encounter "org.forgerock.json.crypto.JsonCryptoException: Decryption failed" errors in IDM/OpenIDM. These errors can occur in a variety of situations but indicate the same issue.

#### Symptoms

You will see the "org.forgerock.json.crypto.JsonCryptoException: Decryption failed" error in different contexts depending on where the issue is occurring. Common related errors include:

• Configuration invalid and could not be parsed, can not start JDBC repository:
WARNING: Configuration invalid and could not be parsed, can not start JDBC repository:
at org.forgerock.json.crypto.JsonDecryptFunction.traverseMap(JsonDecryptFunction.java:48)
at org.forgerock.json.JsonValueTraverseFunction.traverse(JsonValueTraverseFunction.java:50)
at org.forgerock.json.JsonValueTraverseFunction.apply(JsonValueTraverseFunction.java:42)
at org.forgerock.json.JsonValueTraverseFunction.traverseMap(JsonValueTraverseFunction.java:80)
at org.forgerock.json.crypto.JsonDecryptFunction.traverseMap(JsonDecryptFunction.java:52)
at org.forgerock.json.JsonValueTraverseFunction.traverse(JsonValueTraverseFunction.java:50)
at org.forgerock.json.JsonValueTraverseFunction.apply(JsonValueTraverseFunction.java:42) 

• Failed to load configuration file to bootstrap jdbc-default:
WARNING: Failed to load configuration file to bootstrap jdbc-default
at org.forgerock.json.crypto.JsonDecryptFunction.traverseMap(JsonDecryptFunction.java:48)
at org.forgerock.json.JsonValueTraverseFunction.traverse(JsonValueTraverseFunction.java:50)
at org.forgerock.json.JsonValueTraverseFunction.apply(JsonValueTraverseFunction.java:42)
at org.forgerock.json.JsonValueTraverseFunction.traverseMap(JsonValueTraverseFunction.java:80)
at org.forgerock.json.crypto.JsonDecryptFunction.traverseMap(JsonDecryptFunction.java:52)
at org.forgerock.json.JsonValueTraverseFunction.traverse(JsonValueTraverseFunction.java:50)
at org.forgerock.json.JsonValueTraverseFunction.apply(JsonValueTraverseFunction.java:42)


• OpenICF Provisioner Service configuration has errors:
SEVERE: OpenICF Provisioner Service configuration has errors
org.forgerock.json.JsonValueException: /configurationProperties/credentials: org.forgerock.json.crypto.JsonCryptoException: Decryption failed
at org.forgerock.json.crypto.JsonDecryptFunction.traverseMap(JsonDecryptFunction.java:48)
at org.forgerock.json.JsonValueTraverseFunction.traverse(JsonValueTraverseFunction.java:50)
at org.forgerock.json.JsonValueTraverseFunction.apply(JsonValueTraverseFunction.java:42)
at org.forgerock.json.JsonValueTraverseFunction.traverseMap(JsonValueTraverseFunction.java:80)
at org.forgerock.json.crypto.JsonDecryptFunction.traverseMap(JsonDecryptFunction.java:52)
at org.forgerock.json.JsonValueTraverseFunction.traverse(JsonValueTraverseFunction.java:50)
at org.forgerock.json.JsonValueTraverseFunction.apply(JsonValueTraverseFunction.java:42)

• Configuration invalid, can not start Audit service:
WARNING: Configuration invalid, can not start Audit service.
at org.forgerock.json.crypto.JsonDecryptFunction.traverseMap(JsonDecryptFunction.java:48)
at org.forgerock.json.JsonValueTraverseFunction.traverse(JsonValueTraverseFunction.java:50)
at org.forgerock.json.JsonValueTraverseFunction.apply(JsonValueTraverseFunction.java:42)
at org.forgerock.json.JsonValueTraverseFunction.traverseMap(JsonValueTraverseFunction.java:80)
at org.forgerock.json.crypto.JsonDecryptFunction.traverseMap(JsonDecryptFunction.java:52)
at org.forgerock.json.JsonValueTraverseFunction.traverse(JsonValueTraverseFunction.java:50)
at org.forgerock.json.JsonValueTraverseFunction.apply(JsonValueTraverseFunction.java:42)

• The activate method has thrown an exception:
SEVERE: Bundle: org.forgerock.openidm.authnfilter [59] [org.forgerock.openidm.authentication(20)] The activate method has thrown an exception
org.apache.felix.log.LogException: org.forgerock.json.JsonValueException: /serverAuthContext/authModules/0/properties/password: org.forgerock.json.crypto.JsonCryptoException: Decryption failed
at org.forgerock.json.crypto.JsonDecryptFunction.traverseMap(JsonDecryptFunction.java:48)
at org.forgerock.json.JsonValueTraverseFunction.traverse(JsonValueTraverseFunction.java:50)
at org.forgerock.json.JsonValueTraverseFunction.apply(JsonValueTraverseFunction.java:42)
at org.forgerock.json.JsonValueTraverseFunction.traverseMap(JsonValueTraverseFunction.java:80)
at org.forgerock.json.crypto.JsonDecryptFunction.traverseMap(JsonDecryptFunction.java:52)
at org.forgerock.json.JsonValueTraverseFunction.traverse(JsonValueTraverseFunction.java:50)
at org.forgerock.json.JsonValueTraverseFunction.apply(JsonValueTraverseFunction.java:42)

##### Note

The affected field is indicated in these errors by the /password or /credentials part just before the common error. You may see other fields mentioned depending on your configuration.

#### Recent Changes

Copied configuration files from one instance to another.

Copied the keystore from one instance to another.

#### Causes

The affected field (typically password or credential) was encrypted with a different key to the one being used to decrypt it. The key must not be changed in the keystore between encryption and decryption taking place. This situation typically occurs when configuration has been shared between environments and the keys in those environments do not match, but can also happen when keystores are copied between environments.

#### Solution

##### Note

Please be aware of the following:

This issue can be resolved as follows:

1. Ensure all keystores and truststores are the same across all servers if you have a clustered deployment; you can compare checksums of the keystore files to check this, for example using sha1 or md5 checksums.
2. Identify which file(s) need updating:
• For the "Configuration invalid and could not be parsed, can not start JDBC repository" error, you should update the datasource.jdbc-default.json file (located in the /path/to/idm/conf directory).
• For the "Configuration invalid, can not start Audit service" error, you should update the audit.json file (located in the /path/to/idm/conf directory).
• For "OpenICF Provisioner Service configuration has errors", you should update your provisioner configuration files.
• For the other errors, you should search all files in the /path/to/idm/conf directory for $crypto blocks and update any files that you find. You can use a grep command such as the following to find them: $ grep -iR "cipher" *
3. Shutdown the IDM/OpenIDM instance.
4. Remove the $crypto block from the relevant configuration file(s) for the affected field noted in the error and replace it with plain text. For example, to update the password field in the datasource.jdbc-default.json file, you would change the password field from:  "password" : { "$crypto" : {
"type" : "x-simple-encryption",
"value" : {
"stableId" : "openidm-sym-default",
"salt" : "cQT6VZXz9G91RV87dbLM+A==",
"data" : "YTpjLiT1igQ1ATrHIKcsiQ==",
"keySize" : 16,
"purpose" : "idm.config.encryption",
"iv" : "CaorpaRq6v410nPFRjmIXw==",
"mac" : "Q+GQGOQllGy4DPq8Ti88MQ=="
}
},

To:
  "password" : "plain_text_value",

5. Restart the IDM/OpenIDM instance. The startup process will re-encrypt the plain text values with the key in the instance keystore.
6. Repeat steps 3 to 5 on all servers if you have a clustered deployment.

N/A

## Resource exception: 500 Internal Server Error keeps happening in IDM/OpenIDM (All versions)

#### Symptoms

The following error is shown on startup or after specific operations that affect users in the repository (such as a reconciliation or deleting a user):

WARNING: Resource exception: 500 Internal Server Error: "/password: org.forgerock.json.crypto.JsonCryptoException: Decryption failed"
at org.forgerock.openidm.audit.util.RouterActivityLogger.log(RouterActivityLogger.java:133)
at org.forgerock.json.resource.FilterChain$Cursor.handleRead(FilterChain.java:105) at org.forgerock.json.resource.Resources$CollectionInstanceIdContextFilter.filterRead(Resources.java:522)
at org.forgerock.json.resource.FilterChain$Cursor.handleRead(FilterChain.java:103) at org.forgerock.json.resource.FilterChain.handleRead(FilterChain.java:252) at org.forgerock.json.resource.Router.handleRead(Router.java:333)   ##### Note The affected field is indicated in this error by the /password part just after "Resource exception: 500 Internal Server Error". #### Recent Changes The keystore has been updated. #### Causes Repository data was encrypted with a different key to the one being used to decrypt it. The key must not be changed in the keystore between encryption and decryption taking place. #### Solution ##### Note If you want to change the encryption key, see How do I change the symmetric key in IDM/OpenIDM (All versions)? for details on the recommended process to avoid future decryption issues. This issue can be resolved by re-creating the data in the repository; this option is only feasible if you have a valid backup. You can use the following process to identify the data that has been encrypted with the wrong key. Identifying data encrypted with the wrong key One way of identifying data that has been encrypted with the wrong key is to look for invalidly encrypted fields since any operation that tries to decrypt an attribute encrypted with a different key will fail. For example: 1. Create a temporary onRetrieve script for managed users as follows (if a different field is noted in the error, replace password with the name of the affected field): try { if (typeof object.password != 'undefined' && object.password != null) { openidm.decrypt(object.password); } } catch (e) { logger.warn("unable to decrypt " + object.userName); }  2. Update the users section in the managed.json file (located in /path/to/idm/conf) to use this new script (called wrongKey.js in this example): "onRetrieve" : { "type" : "text/javascript", "file" : "wrongKey.js" },  3. Use a query such as the following to return all objects; a warning message will show the userName of any users who have a password (or other field specified in step 1) that cannot be decrypted: $ curl -u openidm-admin:openidm-admin "http://localhost:8080/openidm/managed/user?_queryFilter=true&executeOnRetrieve=true&_prettyPrint=true"

4. Remove the script and script hook added in steps 1 and 2.

N/A

N/A

## Given final block not properly padded error when starting IDM/OpenIDM (All versions)

#### Symptoms

The following error is shown when starting IDM/OpenIDM:

SEVERE: OpenICF Provisioner Service configuration has errors
at org.forgerock.json.crypto.JsonCryptoTransformer.transform(JsonCryptoTransformer.java:52)
at org.forgerock.json.JsonValue.applyTransformers(JsonValue.java:444)
at org.forgerock.json.JsonValue.<init>(JsonValue.java:294)
at org.forgerock.json.JsonValue.get(JsonValue.java:1200)
at org.forgerock.json.JsonValue.copy(JsonValue.java:1080)
at org.forgerock.json.JsonValue.copy(JsonValue.java:1080)
at org.forgerock.openidm.crypto.impl.CryptoServiceImpl.decrypt(CryptoServiceImpl.java:256)
...
at org.forgerock.json.crypto.simple.SimpleDecryptor.decrypt(SimpleDecryptor.java:92)
at org.forgerock.json.crypto.JsonCryptoTransformer.transform(JsonCryptoTransformer.java:50)
... 87 more
Caused by: javax.crypto.BadPaddingException: Given final block not properly padded


You may also see other variants of this error regarding the email service, for example:

WARNING: Configuration invalid, can not start external email client service.
org.forgerock.json.JsonException: org.forgerock.json.crypto.JsonCryptoException: javax.crypto.BadPaddingException: Given final block not properly padded

EVERE: Bundle: org.forgerock.openidm.external-email [71] [org.forgerock.openidm.external.email] The activate method has thrown an exception
org.apache.felix.log.LogException: org.forgerock.json.JsonException: org.forgerock.json.crypto.JsonCryptoException: javax.crypto.BadPaddingException: Given final block not properly padded


#### Recent Changes

Used an existing configuration with a new instance of IDM/OpenIDM.

Restarted a cluster or added a new node to the cluster in OpenIDM 3.x or 4.x.

This error typically occurs when the key in the current keystore is different to the key previously used to encrypt an attribute within IDM/OpenIDM's configuration. The key used when generating the $crypto block is referenced by the key value and the certificate matching this alias; the key must not be changed in the keystore between encryption and decryption taking place. This issue affects configuration files such as provisioner configuration files (for example, provisioner.openicf-ldap.json) and external.email.json (these files are located in the /path/to/idm/conf directory) where some attributes are automatically encrypted along with any value that has been manually encrypted using the CLI tool and added to the configuration. This mismatch in keys can happen when either: • You have made changes to the keystore, or: • You have used the configuration from another IDM/OpenIDM instance. It can also happen in OpenIDM 3.x and 4.x if you fail to start the clustered-first node before any other nodes due to the way in which the keystore is loaded. See FAQ: Clusters in IDM/OpenIDM (Q. How does the keystore get loaded in a clustered environment?) for further information. #### Solution This issue can be resolved as follows depending on your cause: • You have made changes to the keystore - this can be resolved using one of the following methods: • Revert any changes to the IDM/OpenIDM keystore and return the previous key to its original location. • Remove the crypto blocks from the configuration files and replace them with clear text passwords per the Removing crypto blocks example below. The clear text password will be re-encrypted when IDM/OpenIDM reads the configuration with the current secret key in the keystore of the installation. You should do this for all configuration files that contain$crypto blocks.
• You have used the configuration from another IDM/OpenIDM instance - this can be resolved using one of the following methods:
• Copy the keystore from the original IDM/OpenIDM instance (the one from which you took the configuration) to the new instance.
• Remove the crypto blocks from the configuration files and replace them with clear text passwords per the Removing crypto blocks example below. The clear text password will be re-encrypted when IDM/OpenIDM reads the configuration with the current secret key in the keystore of the installation. You should do this for all configuration files that contain $crypto blocks. • The clustered-first node was not the first node started - this can be resolved by ensuring you always start the clustered-first node first. Removing crypto blocks example You can remove crypto blocks as follows: 1. Shutdown the IDM/OpenIDM instance. 2. Update the configuration files to remove the$crypto blocks. For example, in an LDAP provisioner configuration file, you would change the following:
        "principal" : "cn=Directory Manager",
"credentials" : {
at org.forgerock.openidm.auth.modules.IDMAuthModuleWrapper$1.apply(IDMAuthModuleWrapper.java:127) ... Caused by: org.forgerock.openidm.script.ScriptThrownException: [object Object] {code=401, message=Access denied, user inactive}  #### Recent Changes Integrated IDM with AM per the documentation: Samples Guide › Configuring AM for Integration with IDM. #### Causes The amSessionCheck.js script (located in the /path/to/idm/bin/defaults/script/auth directory) checks that a user is active and specifically looks for an account status of 'active' (all lowercase). If the user's status is anything other than this, they are deemed not active and you will see the 401 response. The relevant part of the script is: if (managedUser.result[0].accountStatus !== "active") { throw { "code" : 401, "message" : "Access denied, user inactive" }; }  IDM uses 'active' by default to indicate the account status, but a different status may be used elsewhere. For example, a status coming from DS via a sync may be set to 'Active' (mixed case); in which case, IDM will determine the user is inactive and they will be unable to authenticate per this script's logic. #### Solution This issue can be resolved by changing the amSessionCheck.js script to accept valid account statuses as follows: 1. Navigate to the IDM Admin UI > Manage Users > [User] > Details tab and check the value of the Status field for the managed user who cannot log in. For example, it might be set to 'Active'. 2. Create a script/auth directory within your project. For example, if you are using the full-stack sample, you would create the following: /path/to/idm/samples/full-stack/script/auth  3. Copy the existing amSessionCheck.js file from /path/to/idm/bin/defaults/script/auth to the new script/auth directory you created in step 2. 4. Edit the new version of the amSessionCheck.js file and change the relevant part of the script from: !== "active"  to something that also includes the value identified in step 1, for example: !== ("active"||"Active")  So that the resulting section of the script now looks like this: if (managedUser.result[0].accountStatus !== ("active"||"Active")) { throw { "code" : 401, "message" : "Access denied, user inactive" }; }  5. Save the file and retest. All users should now be able to authenticate. #### See Also #### Related Training N/A #### Related Issue Tracker IDs N/A ## Authentication fails with IDM (All versions) integrated AM when session-jwt cookie size exceeds browser limits The purpose of this article is to provide assistance if authentication fails in an environment where IDM is integrated with AM using the OAUTH_CLIENT module (IDM 5.5 and later) or the OPENID_CONNECT module (IDM 5). #### Symptoms Authentication fails. If you examine network traffic using your browser's Developer Tools or by capturing a HAR file, you will notice the following: • The /openidm/authentication POST call is successful (200 OK response) and you can see the response to this request contains a Set-Cookie for session-jwt. • The session-jwt cookie set is larger than 4096 bytes. • The subsequent /openidm/managed/user/userID GET call fails (403 Forbidden response) and the session-jwt cookie is not set (null). You can capture a HAR file as described in: How do I create a HAR file for troubleshooting IDM/OpenIDM (All versions)? #### Recent Changes Changed the default alias (openidm-localhost) for the encryption key used by the Jetty® web server to service SSL requests. Assigned additional authorization roles to the user(s) who cannot authenticate. #### Causes The session-jwt cookie is larger than 4096 bytes, which is the limit for most browsers per RFC 6265. As a result, IDM sends the session-jwt cookie correctly and it's received by the browser (shown in the POST call), but the browser does not save the cookie nor send it in the next request (shown in the GET call), which causes the authentication flow to fail. The session-jwt cookie contains a lot of information and certain items can cause it to be too big, including (but not limited to): • Public key length, particularly if the public key in use exceeds the default length of 2048 bit. • Number of authorization roles, particularly if the user has more than one authorization role assigned to them. • Length of realm names and/or use of sub-realms as this results in longer URLs within the cookie. Public key length If you're unsure what the public key length is in your environment, you can check it as follows providing you have Java® keytool and openssl installed: 1. Check the alias of the certificate currently in use as follows depending on your version (it's set to openidm-localhost in a default installation): • IDM 6.5 and later: look at the alias specified for the idm.jwt.session.module.encryption secret in the secrets.json file (located in /path/to/idm/conf): { "secretId" : "idm.jwt.session.module.encryption", "types": [ "ENCRYPT", "DECRYPT" ], "aliases": [ "&{openidm.https.keystore.cert.alias|openidm-localhost}" ] },  • Pre-IDM 6.5: look for the value of the following property in the boot.properties file: openidm.https.keystore.cert.alias 2. Navigate to the /path/to/idm/security directory. 3. Run the following keytool command to return the public key, ensuring you substitute your alias, password and keystore details as needed: $ keytool -list -rfc -storetype JCEKS -keystore keystore.jceks -storepass changeit -alias openidm-localhost | openssl x509 -inform pem -pubkey
This will give you an output similar to this:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkOgv6oQT5bKk...
kwIDAQAB
<SNIP>
-----END PUBLIC KEY-----
4. Save this output (including the headers) to a text file.
5. Run the following command referencing the file you just created:
$openssl rsa -noout -text -inform PEM -in pubkey.txt -pubin This will give you an output similar to this, where the public key length is shown (2048 bit in this example): Public-Key: (2048 bit) Modulus: 00:90:e8:2f:ea:84:13:e5:b2:a4:5a:81:56:05:04: <SNIP> 5d:93 Exponent: 65537 (0x10001) #### Solution This issue can be resolved by reducing the length of the session-jwt cookie to below 4096 bytes. Depending on what caused the large session-jwt cookie, the following suggestions may help: #### See Also #### Related Training N/A #### Related Issue Tracker IDs ## Customizing Java Log Format to use SimpleFormatter fails in IDM/OpenIDM (All versions) The purpose of this article is to provide assistance when customizing the Java® Log Format to use the SimpleFormatter format fails in IDM/OpenIDM. #### Symptoms The SimpleFormatter log format does not work in IDM/OpenIDM. For example, the following format string in logging.properties (located in the /path/to/idm/conf directory) does not work: java.util.logging.SimpleFormatter.format = "%4$s: %5$s [%1$tc]%n"


Similarly, the following format string in startup.sh does not work:

-Djava.util.logging.SimpleFormatter.format="%4$s: %5$s [%1$tc]%n" The JVM fails to pick up the new format and continues to write the logs using the default format. #### Recent Changes N/A #### Causes This issue always occurs when running OpenIDM with Java 6; the formatting fails because the$ symbol is removed from the format by the JVM, resulting in an UnknownFormatException.

Similarly, this issue occurs with Java 7 and 8 if the format string is specified in the startup.sh file instead of the logging.properties file.

#### Solution

This issue can be resolved by upgrading to Java 7 or later and specifying the format string in the logging.properties file, which applies the SimpleFormatter formatting correctly.

Alternatively, if you use Java 6 (or use Java 7 or 8, and want to make changes to the startup.sh file), you must escape the $symbol using \. For example, you would add the following system property to the java exec line in the startup.sh file (Java 6, 7 and 8): -Djava.util.logging.SimpleFormatter.format="%4\$s: %5\$s [%1\$tc]%n"

Or specify the format string as follows in the the logging.properties file (Java 6 only):

java.util.logging.SimpleFormatter.format = "%4\$s: %5\$s [%1\$tc]%n" #### See Also #### Related Issue Tracker IDs ## Configuration invalid, can not start JDBC repository error when starting OpenIDM 4.5.x The purpose of this article is to provide assistance if you see a "Configuration invalid, can not start JDBC repository" error when starting OpenIDM 4.5.x. This error only occurs when you are using either MySQL™ or PostgreSQL® as your repository, and have more than one database connection configuration file. #### Symptoms The following message are shown when you start OpenIDM: Executing ./startup.sh... Using OPENIDM_HOME: /opt/openidm Using PROJECT_HOME: /opt/openidm Using OPENIDM_OPTS: -Xmx1024m -Xms1024m Using LOGGING_CONFIG: -Djava.util.logging.config.file=/opt/openidm/conf/logging.properties Using boot properties at /opt/openidm/conf/boot/boot.properties May 5, 2017 3:27:17 PM org.forgerock.openidm.repo.jdbc.impl.JDBCRepoService init WARNING: Configuration invalid, can not start JDBC repository. java.lang.NullPointerException at org.forgerock.openidm.repo.jdbc.impl.JDBCRepoService.init(JDBCRepoService.java:898) at org.forgerock.openidm.repo.jdbc.impl.JDBCRepoService.activate(JDBCRepoService.java:202) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.felix.scr.impl.helper.BaseMethod.invokeMethod(BaseMethod.java:227) at org.apache.felix.scr.impl.helper.BaseMethod.access$500(BaseMethod.java:38)
at org.apache.felix.scr.impl.helper.BaseMethod$Resolved.invoke(BaseMethod.java:591) at org.apache.felix.scr.impl.helper.BaseMethod.invoke(BaseMethod.java:472) at org.apache.felix.scr.impl.helper.ActivateMethod.invoke(ActivateMethod.java:146) at org.apache.felix.scr.impl.manager.ImmediateComponentManager.createImplementationObject(ImmediateComponentManager.java:226) at org.apache.felix.scr.impl.manager.ImmediateComponentManager.createComponent(ImmediateComponentManager.java:118) at org.apache.felix.scr.impl.manager.AbstractComponentManager$Unsatisfied.activate(AbstractComponentManager.java:997)
at org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:333)
at org.apache.felix.scr.impl.manager.DependencyManager.serviceChanged(DependencyManager.java:170)
at org.apache.felix.framework.util.EventDispatcher.invokeServiceListenerCallback(EventDispatcher.java:932)
at org.apache.felix.framework.util.EventDispatcher.fireEventImmediately(EventDispatcher.java:793)
at org.apache.felix.framework.util.EventDispatcher.fireServiceEvent(EventDispatcher.java:543)
at org.apache.felix.framework.Felix.fireServiceEvent(Felix.java:4419)
at org.apache.felix.framework.Felix.registerService(Felix.java:3423)
at org.apache.felix.framework.BundleContextImpl.registerService(BundleContextImpl.java:346)
at org.apache.felix.scr.impl.manager.AbstractComponentManager.registerService(AbstractComponentManager.java:449)
at org.apache.felix.scr.impl.manager.AbstractComponentManager.registerComponentService(AbstractComponentManager.java:460)
at org.apache.felix.scr.impl.manager.AbstractComponentManager$Unsatisfied.activate(AbstractComponentManager.java:1009) at org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:333) at org.apache.felix.scr.impl.manager.AbstractComponentManager.enable(AbstractComponentManager.java:157) at org.apache.felix.scr.impl.config.UnconfiguredComponentHolder.enableComponents(UnconfiguredComponentHolder.java:68) at org.apache.felix.scr.impl.BundleComponentActivator.loadDescriptor(BundleComponentActivator.java:253) at org.apache.felix.scr.impl.BundleComponentActivator.initialize(BundleComponentActivator.java:147) at org.apache.felix.scr.impl.BundleComponentActivator.<init>(BundleComponentActivator.java:111) at org.apache.felix.scr.impl.Activator.loadComponents(Activator.java:285) at org.apache.felix.scr.impl.Activator.bundleChanged(Activator.java:203) at org.apache.felix.framework.util.EventDispatcher.invokeBundleListenerCallback(EventDispatcher.java:868) at org.apache.felix.framework.util.EventDispatcher.fireEventImmediately(EventDispatcher.java:789) at org.apache.felix.framework.util.EventDispatcher.fireBundleEvent(EventDispatcher.java:514) at org.apache.felix.framework.Felix.fireBundleEvent(Felix.java:4403) at org.apache.felix.framework.Felix.startBundle(Felix.java:2092) at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1291) at org.apache.felix.framework.FrameworkStartLevelImpl.run(FrameworkStartLevelImpl.java:304) at java.lang.Thread.run(Thread.java:745) May 5, 2017 3:27:17 PM org.forgerock.openidm.logging.LogServiceTracker logEntry SEVERE: Bundle: org.forgerock.openidm.repo-jdbc [13] [org.forgerock.openidm.repo.jdbc] The activate method has thrown an exception org.apache.felix.log.LogException: org.forgerock.openidm.config.enhanced.InvalidException: Configuration invalid, can not start JDBC repository. at org.forgerock.openidm.repo.jdbc.impl.JDBCRepoService.init(JDBCRepoService.java:959) at org.forgerock.openidm.repo.jdbc.impl.JDBCRepoService.activate(JDBCRepoService.java:202) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.felix.scr.impl.helper.BaseMethod.invokeMethod(BaseMethod.java:227) at org.apache.felix.scr.impl.helper.BaseMethod.access$500(BaseMethod.java:38)
at org.apache.felix.scr.impl.helper.BaseMethod$Resolved.invoke(BaseMethod.java:591) at org.apache.felix.scr.impl.helper.BaseMethod.invoke(BaseMethod.java:472) at org.apache.felix.scr.impl.helper.ActivateMethod.invoke(ActivateMethod.java:146) at org.apache.felix.scr.impl.manager.ImmediateComponentManager.createImplementationObject(ImmediateComponentManager.java:226) at org.apache.felix.scr.impl.manager.ImmediateComponentManager.createComponent(ImmediateComponentManager.java:118) at org.apache.felix.scr.impl.manager.AbstractComponentManager$Unsatisfied.activate(AbstractComponentManager.java:997)
at org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:333)
at org.apache.felix.scr.impl.manager.DependencyManager.serviceChanged(DependencyManager.java:170)
at org.apache.felix.framework.util.EventDispatcher.invokeServiceListenerCallback(EventDispatcher.java:932)
at org.apache.felix.framework.util.EventDispatcher.fireEventImmediately(EventDispatcher.java:793)
at org.apache.felix.framework.util.EventDispatcher.fireServiceEvent(EventDispatcher.java:543)
at org.apache.felix.framework.Felix.fireServiceEvent(Felix.java:4419)
at org.apache.felix.framework.Felix.registerService(Felix.java:3423)
at org.apache.felix.framework.BundleContextImpl.registerService(BundleContextImpl.java:346)
at org.apache.felix.scr.impl.manager.AbstractComponentManager.registerService(AbstractComponentManager.java:449)
at org.apache.felix.scr.impl.manager.AbstractComponentManager.registerComponentService(AbstractComponentManager.java:460)
at org.apache.felix.scr.impl.manager.AbstractComponentManager$Unsatisfied.activate(AbstractComponentManager.java:1009) at org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:333) at org.apache.felix.scr.impl.manager.AbstractComponentManager.enable(AbstractComponentManager.java:157) at org.apache.felix.scr.impl.config.UnconfiguredComponentHolder.enableComponents(UnconfiguredComponentHolder.java:68) at org.apache.felix.scr.impl.BundleComponentActivator.loadDescriptor(BundleComponentActivator.java:253) at org.apache.felix.scr.impl.BundleComponentActivator.initialize(BundleComponentActivator.java:147) at org.apache.felix.scr.impl.BundleComponentActivator.<init>(BundleComponentActivator.java:111) at org.apache.felix.scr.impl.Activator.loadComponents(Activator.java:285) at org.apache.felix.scr.impl.Activator.bundleChanged(Activator.java:203) at org.apache.felix.framework.util.EventDispatcher.invokeBundleListenerCallback(EventDispatcher.java:868) at org.apache.felix.framework.util.EventDispatcher.fireEventImmediately(EventDispatcher.java:789) at org.apache.felix.framework.util.EventDispatcher.fireBundleEvent(EventDispatcher.java:514) at org.apache.felix.framework.Felix.fireBundleEvent(Felix.java:4403) at org.apache.felix.framework.Felix.startBundle(Felix.java:2092) at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1291) at org.apache.felix.framework.FrameworkStartLevelImpl.run(FrameworkStartLevelImpl.java:304) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.NullPointerException at org.forgerock.openidm.repo.jdbc.impl.JDBCRepoService.init(JDBCRepoService.java:898) ... 41 more May 5, 2017 3:27:17 PM org.forgerock.openidm.logging.LogServiceTracker logEntry SEVERE: Bundle: org.forgerock.openidm.repo-jdbc [13] [org.forgerock.openidm.repo.jdbc] Component instance could not be created, activation failed -> May 5, 2017 3:27:24 PM org.ops4j.pax.web.service.jetty.internal.ServerControllerImpl$Stopped start
WARNING: HTTP is not enabled in Pax Web configuration - removing connector: 0.0.0.0:8080@2ceb65b4{HTTP/1.1}{0.0.0.0:0}
OpenIDM ready


Once OpenIDM has started, it seems to function normally.

#### Recent Changes

Upgraded to, or installed OpenIDM 4.5.x.

Configured an additional database connection configuration file (for example, datasource.jdbc-activiti.json per the solution in JobEntity was updated by another transaction concurrently exception when using workflows in OpenIDM 4.x).

#### Causes

The repository service attempts to start before the data source it needs is available, which causes this error. Once all the data sources are registered, the repository service is able to find the correct data source and then proceeds to start correctly, which is why OpenIDM then functions normally.

#### Solution

Firstly, this error is harmless and can be ignored since OpenIDM functions normally once started. However, this issue can be resolved by upgrading to IDM 5 or later; you can download this from BackStage.

Workaround

If you have multiple database connection configuration files in the /path/to/openidm/conf directory but do not need them all, you can delete the unused ones since this error does not happen if you only have one file.

N/A

N/A

## Double-clicks on Self-Service Registration page causes duplicate entries in IDM 5.x, 6 and OpenIDM 4.x

The purpose of this article is to provide assistance if duplicate user entries are created in IDM/OpenIDM when a user double-clicks the Submit button on the Self-Service Registration page.

#### Symptoms

Issues may arise during Self-Registration when a user double-clicks the submit form. For example, a user is created multiple times in the IDM/OpenIDM database. These duplicate entries prevent the user logging in until the duplicate entry is removed.

N/A

#### Causes

There is a known issue OPENIDM-7789 when a user double-clicks the Submit button on the Self-Service Registration page, two concurrent REST calls are sent, which creates two profiles. The profiles have unique userNames (meaning the userName uniqueness policy is still being enforced) but the presence of duplicate entries prevents a user logging in.

#### Solution

This issue can be resolved by updating the definition for the Submit button in the following files (located in the /path/to/idm/ui/selfservice/default/templates/user/process/registration directory):

• userDetails-initial.html

You should add the ondblclick="" setting to the Submit definition so that it looks like this:

<input type="submit" class="btn btn-lg btn-primary btn-block btn-uppercase" ondblclick="" value="t 'common.form.save'" /


This change implies an empty action for double-clicks, which means the second click is ignored and only one user profile is created.

N/A

## Link in Password Reset and User Registration emails in IDM/OpenIDM (All versions) does not work in Microsoft Outlook

The purpose of this article is to provide assistance if the link in the Password Reset and User Registration emails generated by IDM/OpenIDM does not work in Microsoft® Outlook®. This issue can affect all Outlook versions (2007, 2010, 2013, 2016, 2019 and Office 365).

#### Symptoms

The link included in the Password Reset and User Registration emails does not work when clicked in Outlook. It works when copied to a browser in Outlook 2007 or 2010.

#### Recent Changes

Configured the Password Reset and/or User Registration functionality.

#### Causes

There are limitations in Outlook regarding hyperlink length:

• In Outlook 2007 and 2010, hyperlinks do not work if they exceed approximately 1030 characters. The URL is intact and can be copied to a browser.
• In Outlook 2013, 2016, 2019 and Office 365, hyperlinks are truncated after a certain length (in excess of 2000 characters). Since the link has been truncated, it is unusable even if copied.

#### Solution

This issue can be resolved in a single node deployment by upgrading to IDM 5.5 or later (IDM 6.0.0.5 resolves this in a cluster environment); you can download this from BackStage. Once you have upgraded IDM, you can change the snapshotToken configuration within your Self Service configuration files (selfservice-reset.json and selfservice-registration.json) to use type: uuid and storage: local. For example, your configuration would look similar to this after the change:

"snapshotToken" : {
"type" : "uuid",
"keyPairAlgorithm" : "RSA",
"keyPairSize" : 1024,
"jweAlgorithm" : "RSAES_PKCS1_V1_5",
"encryptionMethod" : "A128CBC_HS256",
"jwsAlgorithm" : "HS256",
"tokenExpiry" : 1800
},
"storage" : "local"


After these configuration changes, you will see much shorter links in the following format:

https://idm.example.com/ui/#passwordReset/&token=a009b272-2b23-4a8a-bd08-e89e4a32ef8b&code=12721e49-760e-4a20-81b8-48f8013e2cf8

See Integrator's Guide › Tokens and User Self-Service and Self-Service REST API Reference › The Self-Service Process Flow for further information.

##### Note

You should be aware of the following:

• There is a known issue with the uuid type in multi-node deployments: OPENIDM-12796 (jsonstorage "local" self-service with "uuid" option fails in multi-node cluster scenario). This is fixed in IDM 6.0.0.5.
• Changes to the password reset or registration modules via the Admin UI may revert the changes made to the snapshotToken section in the configuration files and the token may change back to the long token format. If this occurs, check the configuration files (selfservice-reset.json and selfservice-registration.json) and update them again per the above example.

Workaround (Outlook 2007 and 2010 users)

A suggested workaround for this issue is to customize the email sent to end users to advise Outlook 2007 and 2010 users to copy and paste the link into their browser instead. The link should be left for users not affected by this issue. You can do this by changing the Email text for the Password Reset and/or User Registration emails.

The following example guides you through changing the Email text for the Password Reset email. The same concept applies to the User Registration email, which is found under Configure > User Registration:

1. Navigate as follows in the admin UI: Configure > Password Reset and click the pencil icon against Email Validation.
2. Remove the following text:
<h3>Click to reset your password</h3><h4><a href="%link%">Password reset link</a></h4>
And replace with your customized message, for example:
<h3>Click to reset your password</h3><h4><a href="%link%">Password reset link</a></h4> <h4> If you are an Outlook 2007/2010 user, please copy and paste the following link into your browser to reset your password: %link%</h4>


The resulting email in this example will look like this:

Click to reset your password
https://idm.example.com/ui/#passwordReset/&token=eyAidHlwIjogIkpXRSIsICJhbGciOiAiSFMyNTYiIH0.ZXlBaWRIbHdJam9nSWtwWFZDSXNJQ0psYm1NaU9pQWlRVEV5T0VOQ1F5MUlVekkxTmlJc0lDSmhiR2NpT2lBaVVsTkJNVjgxSWlCOS5OWEFHLUlBampRYW54eHpsYmFhTXNVYjBQWTNsZ05VbG9SYlFUOGVZYmVGbE5VcVdMR200SVNLM29MTzlSOTlwdWJleEFhVHRWRDFGOFRldzE0M2ZXLTWVBbVpSLXRjV19fOTVlODRwNWhVNnpxZkstVWZvSnVmNU5MVG82aXhvQmdqX2NvY3B3YnI3UEx6bDBfUEdTcU10k1VVdKbUN1RUdRUzRWSG56TGR2NGhWUm13OWh2MHRYWVhqTEJ2ZXRib1UwcHZjeFRQR254WmJ5TjlJajJBT0tIc21pbWQ0NWFwcFhYLXNzY0REX00uc3FGZjkxMDI3UWFIOUZzZFdQTlNpUS52SlM1czR2SUpxd0VuZno3c3Z6SXlDRL5ZjcwSmZnWFRGUThpeTJpMjJpWmxNNVFqSElveFZsVzd2SThKbndBUlVUOUNvV21kcm1HdDUtNHJTaHZ3UFRyVlZsVFYNmlMb0hyMVNHWEQ3S0VUOUxkbm9rYkxSLXJMOHA2NTF3SE1WNXdqWTFTYkkyVDM2dkw0RVQ0b3Z1UUd1Zm11UjV5anI1Z1RJSEZuR1hnMEZVNnBNQVllMFQxMTJQUWZTMGhfUEhiYXJUN2xCMktDN2t2WExlVFFhT1RtcHhWTkUbnlscmJEelRfcndQc0FqQXJTQURtREw0YlFBeExvZ21INk9nU2FBLWhDelNVOEhOa21OR3ZFaUY4eFZ2aUhwb2VHYkhJemExc1lVSzRicGFxVUk4TDVxaWl3STFWNEtIWllYUjZBMDRpcTAxXy1FQWpiVHNwZmVWR2o2YWhraHlYMU5IVW9XSkZCRkxzLXBuU2RraGQ3SDUxeEpfR19keVFQLndCaHhac3ZXOGUzN1I5UlgzTlpHbmc.wKygX_XVRDedaLX5ME5kjZlpo1InkT013zg38mE5E3Q&code=0b9b0e2e-6370-4f5e-9a68-73bb86f5d06f

##### Note

You can also change the email text by editing the PasswordResetConfigView.js and/or UserRegistrationConfigView.js files located in the /path/to/idm/ui/admin/default/org/forgerock/openidm/ui/admin/selfservice directory.

N/A

## Failed to load checksum file from archive error in OpenIDM 4.x

#### Symptoms

The following error is shown when upgrading from OpenIDM 4.0:

org.forgerock.json.resource.InternalServerErrorException: Server Error {"code":500,"reason":"Internal Server Error","message":"Failed to load checksum file from archive."}
at org.forgerock.json.resource.ResourceException.newResourceException(ResourceException.java:239)
at org.forgerock.json.resource.ResourceException.getException(ResourceException.java:330)
at org.forgerock.openidm.shell.impl.HttpRemoteJsonResource.handle(HttpRemoteJsonResource.java:373)
at org.forgerock.openidm.shell.impl.HttpRemoteJsonResource.action(HttpRemoteJsonResource.java:131)
at org.forgerock.openidm.shell.impl.UpdateCommand$GetArchiveDataStepExecutor.execute(UpdateCommand.java:318) at org.forgerock.openidm.shell.impl.UpdateCommand.execute(UpdateCommand.java:194) at org.forgerock.openidm.shell.impl.RemoteCommandScope.update(RemoteCommandScope.java:199)   You may also see an error similar to the following in the OpenIDM log: Oct 04, 2016 11:15:27 AM org.forgerock.openidm.servlet.internal.ServletConnectionFactory$4 handleException
WARNING: Resource exception: 500 Internal Server Error: "Failed to load checksum file from archive." org.forgerock.json.resource.InternalServerErrorException: Failed to load checksum file from archive.
at org.forgerock.json.resource.Router.handleAction(Router.java:241) 


#### Recent Changes

Installed, or upgraded to OpenIDM 4.x.

#### Causes

The checksum file is missing.

The checksum file is used by the OpenIDM Update mechanism. It should not be modified and contains the checksums of all the files distributed with the release, which are then used to identify modified files and/or files which do not originate from ForgeRock during the upgrade. See Installation Guide › OpenIDM Update Checksums for further information.

##### Caution

It is important to ensure the checksum file is deployed when installing or upgrading OpenIDM; failing to do so will prevent you updating OpenIDM in the future.

#### Solution

This issue can be resolved by ensuring the .checksums.csv file is located within the root of the OpenIDM installation directory. If it does not exist, you should extract the original file from the OpenIDM 4.x installation bundle and copy it to your OpenIDM installation directory.

N/A

## JobEntity was updated by another transaction concurrently exception when using workflows in OpenIDM 4.x

The purpose of this article is to provide assistance if you receive a "SEVERE: exception during job execution: JobEntity [id=1234] was updated by another transaction concurrently" exception when using workflows in OpenIDM 4.x. This issue only affects JDBC repositories.

#### Symptoms

The following error is shown in the OpenIDM log when using a workflow task:

Aug 24, 2016 11:17:33 AM org.activiti.engine.impl.jobexecutor.ExecuteJobsRunnable run
SEVERE: exception during job execution: JobEntity [id=7727] was updated by another transaction concurrently
org.activiti.engine.ActivitiOptimisticLockingException: JobEntity [id=7727] was updated by another transaction concurrently
at org.activiti.engine.impl.db.DbSqlSession$CheckedDeleteOperation.execute(DbSqlSession.java:246) at org.activiti.engine.impl.db.DbSqlSession.flushDeletes(DbSqlSession.java:609) at org.activiti.engine.impl.db.DbSqlSession.flush(DbSqlSession.java:477) at org.activiti.engine.impl.interceptor.CommandContext.flushSessions(CommandContext.java:171) at org.activiti.engine.impl.interceptor.CommandContext.close(CommandContext.java:118) at org.activiti.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:66) at org.activiti.engine.impl.interceptor.JtaTransactionInterceptor.execute(JtaTransactionInterceptor.java:64) at org.activiti.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:31) at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:40) at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:35) at org.activiti.engine.impl.jobexecutor.ExecuteJobsRunnable.run(ExecuteJobsRunnable.java:52) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)


This is an intermittent error and will not occur every single time.

#### Recent Changes

Upgraded to, or installed OpenIDM 4.x.

Implemented the workflow functionality.

#### Causes

The Activiti Workflow module was modified in OpenIDM 4.0 to use the same connection pool as the repository, which means that both Activiti and the repository module now share the same transaction manager.

#### Solution

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

Workaround

Alternatively, this issue can be resolved by separating the Activiti datasource away from the repository datasource to mimic the setup in earlier versions of OpenIDM. You can do this by creating a separate datasource for Activiti and then configuring the workflow to use this new datasource:

1. Shutdown the OpenIDM instance.
2. Copy the datasource.jdbc-default.json file applicable to your repository type (for example, from the /path/to/openidm/db/postgresql/conf directory if you are using the PostgreSQL® repository) to the /path/to/openidm/conf directory and rename it datasource.jdbc-activiti.json. You will now have two database connection configuration files in this directory.
3. Update workflow.json (located in the /path/to/openidm/conf directory) and change the useDataSource from default to activiti so that it uses the new database connection configuration file:
{
"enabled" : true,
"useDataSource" : "activiti",
"workflowDirectory" : "&{launcher.project.location}/workflow"
}


4. Delete the contents of the /path/to/openidm/felix-cache directory.
5. Restart the OpenIDM instance.
##### Note

These changes will increase the number of connections since you will have two separate connection pools. You can manage the connection pools for both the repository and the Activiti module as described in How do I configure the connection pool for the managed repository in IDM/OpenIDM (All versions)? by applying the changes to the relevant datasource.jdbc-default.json file.

N/A

## Repository password is not encrypted in OpenIDM 3.x or 4.x log and configuration files

#### Symptoms

The repository password is shown in clear text in the following files:

##### Caution

There is a known security issue, which is detailed as issue #201602-01: Unencrypted Repo JDBC Password: OpenIDM Security Advisory #201602

#### Recent Changes

Upgraded to OpenIDM 3.x or 4.x.

#### Causes

Passwords specified in the repo.jdbc.json file or the datasource.jdbc-default.json file are no longer automatically encrypted during the initial startup of OpenIDM.

#### Solution

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

Workaround

Alternatively, you can encrypt the repository password using the OpenIDM Command-Line Interface (CLI). This is accessed using the cli.sh command (Linux® and Unix®) or the cli.bat command (Microsoft® Windows®). The following process uses the cli.sh command; substitute cli.bat instead if you use Microsoft Windows.

1. Ensure you have performed an initial start of the OpenIDM instance with the correct JDBC password specified in the repo.jdbc.json file or the datasource.jdbc-default.json file and that the instance started and functions correctly.
2. Shutdown the OpenIDM instance.
3. Execute the ./cli.sh encrypt command within the root of the OpenIDM installation:
$cd /path/to/openidm$ ./cli.sh encrypt [JDBCpassword]

4. Copy the encrypted value from the output of the CLI. This includes everything between the ----- BEGIN ENCRYPTED VALUE ---- and ----- END ENCRYPTED VALUE ------ lines. For example:
-----BEGIN ENCRYPTED VALUE-----
{
"$crypto" : { "value" : { "iv" : "5UWV+SLe/Z9gg/7lZRO+Ng==", "data" : "7rol/iYruQ4xauop0hq6cQ==", "cipher" : "AES/CBC/PKCS5Padding", "key" : "openidm-sym-default" }, "type" : "x-simple-encryption" } } ------END ENCRYPTED VALUE------ 5. Edit the repo.jdbc.json file or the datasource.jdbc-default.json file and replace the value for the password property with the encrypted value you copied in step 4. For example, the password property would now look like this:  "password" : { "$crypto" : {
"value" : {
"iv" : "5UWV+SLe/Z9gg/7lZRO+Ng==",
"data" : "7rol/iYruQ4xauop0hq6cQ==",
"key" : "openidm-sym-default"
},
"type" : "x-simple-encryption"
}
},

6. Save the changes you made to the repo.jdbc.json file or the datasource.jdbc-default.json file.
7. Start the OpenIDM instance. It will now read the encrypted value from the repo.jdbc.json file or the datasource.jdbc-default.json file and will no longer output clear text in the log file.
##### Note

If you are running a cluster, you will need to perform the above process on each of the nodes in the cluster.

N/A

N/A

## How do I check what patches are installed for ForgeRock products?

#### Overview

This article provides details for checking what patches are installed by product:

You can also use the patchinfo utility in AM/OpenAM and IG/OpenIG as detailed in How do I use the patchinfo utility to check what patches are installed for AM/OpenAM (All versions) or IG/OpenIG (All versions)?

#### Checking for patches in AM/OpenAM

Providing you have unzipped your patches directly in the openam directory as recommended, you can check what patches are installed as follows:

$cd /path/to/tomcat/webapps/openam/WEB-INF$ ls README.*



Where each README represents a set of installed patches. READMEs are named to indicate either the ticket number where the patch was given (README.1.12345) or the security advisory ID (README.201608).

Embedded DS/OpenDJ

You can check what patches are installed using the status -V command as follows:

$cd$HOME/[am_instance]/opends/bin
$./status -V Wed Nov 29 11:27:09 MST 2017 ForgeRock Directory Services 5.5.0+OPENDJ-1234,OPENDJ-5678 Build 20171019141329 Any installed patches will be listed after the product name and version as an issue tracker ID (JIRA). #### Checking for patches in Policy Agents You can check the debug log to see what patch version you have installed, for example: ###################################################### # OpenAM Web Agent # # Version: 4.1.0-27 # # Revision: 39e5be3 # # Container: IIS 7.5, 8.x WINNT 32/64bit/WINNT # # Build date: Nov 2 2017 13:42:43 # ###################################################### For Web policy agents 4.x, you can also check the version using the agentadmin --v command as follows: $ ./agentadmin --v

OpenAM Web Agent for Apache Server 2.2.x 64bit
Version: 4.1.0-25
Revision: 42ff535
Build machine: delacroix
Build date: Sep 15 2017 16:44:11

#### Checking for patches in DS/OpenDJ

You can check what patches are installed using the status -V command as follows:

$cd /path/to/ds/bin$ ./status -V

Wed Nov 29 11:27:09 MST 2017
ForgeRock Directory Services 5.5.0+OPENDJ-1234,OPENDJ-5678
Build 20171019141329


Any installed patches will be listed after the product name and version as an issue tracker ID (JIRA).

#### Checking for patches in IDM/OpenIDM

You can check what patches are installed using the PS command when running IDM/OpenIDM interactively, for example:

ps
START LEVEL 12
ID   State         Level  Name
[   0] [Active     ] [    0] System Bundle (4.2.1)
[   1] [Resolved   ] [    1] javax.transaction API v.1.1 (3.1.1)
[   2] [Active     ] [    1] OpenIDM System Bundle (4.5.0)
...
[ 135] [Active     ] [   10] OpenIDM Core Bundle (4.5.0.OPENIDM-1234-5678)
...


Any installed patches will be listed after a product bundle as an issue tracker ID (JIRA). Patches only apply to a bundle (not the whole product), so you will need to check all bundles for patches, focusing on any that start OpenIDM, ForgeRock or OpenICF. You can search for version.JIRA_prefix to easily find the patched bundles, for example:

(4.5.0.OPENIDM
(4.5.0.OPENICF
(4.5.0.CREST


#### Checking for patches in IG/OpenIG

Providing you have unzipped your patches directly in the top-level IG/OpenIG WAR directory as recommended, you can check what patches are installed as follows:

$cd /path/to/jetty/webapps/root/WEB-INF$ ls README.*



Where each README represents a set of installed patches. READMEs are named to indicate either the ticket number where the patch was given (README.1.12345) or the security advisory ID (README.201606).

N/A

## How do I install an IDM/OpenIDM patch (All versions) supplied by ForgeRock support?

The purpose of this article is to provide information on installing an IDM/OpenIDM patch that has been supplied by ForgeRock support. It also includes the necessary steps for installing a UI patch.

#### Installing a non-UI patch (All versions)

Typically, a patch for IDM/OpenIDM includes one or more replacement bundles in the form: openidm-<component>--<openidm_version>.jar, for example: openidm-config-6.5.0.jar or openidm-repo-jdbc-6.0.0.jar

We also provide the shasum so you can verify that the files are not corrupted.

You can install an IDM/OpenIDM patch as follows:​

1. Shutdown the IDM/OpenIDM instance.
$cd /path/to/idm$ ./shutdown.sh

2. Back up the existing versions of the files in the /path/to/idm/bundle directory that have been supplied in the patch.
3. Delete these files once they have been backed up.
4. Copy the replacement files supplied in the patch to the /path/to/idm/bundle directory.
5. Delete the felix cache:
$cd /path/to/idm$ rm -rf felix-cache/*

6. Start the IDM/OpenIDM server:
$cd /path/to/idm$ ./startup.sh

#### Installing a UI patch (IDM 6.5 and later)

Typically, a UI patch for IDM 6.5 and later is delivered as a zip file.

##### Caution

If you have customized the UI (for example, made changes to the logo, css or similar), replacing the contents of the ui/enduser directory will remove these customizations. In which case, you will need to reapply your customizations after you have installed the patch.

You can install an IDM UI patch as follows:​

1. Shutdown the IDM instance.
$cd /path/to/idm$ ./shutdown.sh

2. Back up the /path/to/idm/ui/enduser directory.
3. Extract the patch zip to a temporary location:
$unzip /tmp/patch.zip 4. Replace the contents in the /path/to/idm/ui/enduser directory with the contents of the extracted zip. 5. Delete the felix cache: $ cd /path/to/idm
$rm -rf felix-cache/*  6. Start the IDM server: $ cd /path/to/idm
$./startup.sh  #### Installing a UI patch (Pre-IDM 6.5) Typically, a UI patch for IDM/OpenIDM includes either or both of the following replacement bundles: openidm-ui-admin-<version>.jar and/or openidm-ui-enduser-<version>.jar We also provide the shasum so you can verify that the files are not corrupted. ##### Caution If you have customized the UI (for example, made changes to the logo, css or similar), deleting the ui/admin and/or ui/selfservice directories will remove these customizations. In which case, you will need to reapply your customizations after you have installed the patch. You can install an IDM/OpenIDM UI patch as follows:​ 1. Shutdown the IDM/OpenIDM instance. $ cd /path/to/idm
$./shutdown.sh  2. Back up and delete the following file and corresponding ui directory if the openidm-ui-admin-<version>.jar has been supplied in the patch: • /path/to/idm/bundle/openidm-ui-admin-*.jar • /path/to/idm/ui/admin 3. Back up and delete the following file and corresponding ui directory if the openidm-ui-enduser-<version>.jar has been supplied in the patch: • /path/to/idm/bundle/openidm-ui-enduser-*.jar • /path/to/idm/ui/selfservice 4. Copy the replacement files supplied in the patch to the /path/to/idm/bundle directory. 5. Navigate to the /path/to/idm/ui/admin directory and execute the following command if the openidm-ui-admin-<version>.jar has been supplied in the patch: $ cd /path/to/idm/ui/admin
$jar -xvf /path/to/idm/bundle/openidm-ui-admin-<version>.jar  6. Navigate to the /path/to/idm/ui/selfservice directory and execute the following command if the openidm-ui-enduser-<version>.jar has been supplied in the patch: $ cd /path/to/idm/ui/selfservice
$jar -xvf /path/to/idm/bundle/openidm-ui-enduser-<version>.jar  7. Delete the felix cache: $ cd /path/to/idm
$rm -rf felix-cache/*  8. Reapply any customizations to the ui/admin and/or ui/selfservice directories. 9. Start the IDM/OpenIDM server: $ cd /path/to/idm
\$ ./startup.sh

N/A

N/A