Child pages
  • How to setup OpenDJ for password synchronization
Skip to end of metadata
Go to start of metadata

This page is work in progress and might contain errors or lack some steps.


The OpenDJ account change handler is an OpenDJ plugin and a remote OpenIDM agent. This plugin can be installed into OpenDJ 2.4.1 or newer server to notify OpenIDM 2.0.0 or 2.1.0 when password of an account has been updated.

An OpenDJ server can have the same plugin configured multiple times and the handler configuration has to be assigned to a password policy. This makes possible to have different configuration for example per group or root context.

The communication between the OpenDJ and the OpenIDM is secured multiple ways. The plugin use mutual authentication, transport secured by HTTPS protocol and the message itself is encrypted with a public key. Only the OpenIDM can decrypt the payload. The plugin use the JSON Patch format to update the managed object in OpenIDM.

Install the OpenDJ follow the Install Guide

If you want to enable the debug then change the Server Runtime Settings to:
-server -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005

Install and configure

Before you install it stop the OpenDJ instance:

$ bin/stop-ds

Download the OpenIDM Agents - OpenDJ from the download site and extract the archive and copy the content of the opendj directory to the OpneDJ installation directory. 

$ unzip

$ cp -R opendj/* OpenDJ-2.4.4

Update the configuration by appending it to the config.ldif:

$ cat config/openidm-pwsync-plugin-config.ldif >> config/config.ldif

(make sure the there is one empty line between the last object in the config.ldif and the newly added object; you may want to change the default configuration first, but you can do it afterwards with dsconfig)

The certificate of OpenIDM PasswordSync service need to be installed into the truststore and the client certificate and private key needs to be installed into the keystore.

The archive comes with some sample keys but you can generate and use your own.

Certificate and public key exchange

To secure the communication between the OpenDJ and OpenIDM some certificates has to be shared between the two servers. If the OpenDJ configured for LDAPS the wizard generates the required keystore files in config folder and configures the keymanagers. 

Two keys MUST shared between OpenIDM and OpenDJ before start.

The default OpenIDM server open and HTTPS listener on 8444 port and pick the first private key "openidm-localhost" from the configured keystore. The plugin connects to this port and the OpenDJ truststore MUST contain this certificate. This certificate is exported to openidm/samples/security/openidm-localhost-cert.txt file. 

The OpenDJ plugin use a private key to encrypt the message before sends over to OpenIDM. The private key alias configured with ds-cfg-ssl-cert-nickname property. When the OpenIDM decrypts this message it needs to have the public key. This MUST be imported into the security/keystore.jceks file with the same alias configured ds-cfg-realm. 

How to generate and configure new self-signed certificate 

Create a private key for the certificate (Optional if LDAPS is configured):

$ keytool -genkey -alias server-cert -keyalg rsa \
  -dname "CN=localhost, O=OpenDJ Self-Signed Certificate" \
  -keystore config/keystore -storetype JKS

In this case, the value of the -dname argument should be changed so that it is suitable for your environment.

You will be interactively prompted for both a password to protect the contents of the keystore and a password to protect the private key. Both passwords should be the same.

Generate a self-signed certificate for the key with the command (Optional if LDAPS is configured):

$ keytool -selfcert -alias server-cert -validity 3653 \
  -keystore config/keystore -storetype JKS

When you are prompted for the keystore password, enter the same password that you provided previously.

Create a text file with the keystore password config/ (Optional if LDAPS is configured):

$ echo [enter the keystore password here] > config/

The file should only contain the password that you chose to protect the contents of the keystore.

Export the public key for the certificate that you just created:

$ keytool -export -alias server-cert \
  -file config/OpenIDM-LDAP-client-cert.txt -rfc -keystore config/keystore \
  -storetype JKS

Import that exported public key and the certificate into the truststore of OpenIDM (This allows the OpenDJ to mutual authenticate with the private key):

$ keytool -import -alias opendj-server-cert \
  -file config/OpenIDM-LDAP-client-cert.txt -keystore openidm/security/truststore \
  -storetype JKS

Export the public key for the certificate of PasswordSync Service from OpenIDM keystore (you can use openidm/samples/security/openidm-localhost-cert.txt):

$ keytool -export -alias openidm-localhost -file openidm-localhost-cert.txt \
  -rfc -keystore openidm/security/keystore.jceks -storetype JCEKS

Create a new trust store and/or import the server certificate into OpenDJ truststore (The plugin use this key to encrypt the message):

$ keytool -import -alias openidm-localhost \
  -file config/openidm-localhost-cert.txt -keystore config/truststore \
  -storetype JKS

Type yes when you are prompted about whether you want to trust the certificate.

Make sure all certificates and private key are in place:

$ keytool -list -keystore config/truststore -storepass changeit
Keystore type: JKS
Keystore provider: SUN

Your keystore contains 3 entries

openidm-localhost, 2011.08.19., trustedCertEntry,
Certificate fingerprint (MD5): B8:B3:B4:4C:F3:22:89:19:C6:55:98:C5:DF:47:DF:06
remote-server-cert, 2011.07.13., trustedCertEntry,
Certificate fingerprint (MD5): 42:BB:1B:6D:D5:83:EB:BF:B9:08:93:70:A5:20:3D:84
server-cert, 2011.07.12., trustedCertEntry,
Certificate fingerprint (MD5): C6:3C:76:F2:A6:EB:DA:A7:49:FD:35:93:74:9E:7A:B2

$ keytool -list -keystore config/keystore -storepass changeit
Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

server-cert, 2011.07.12., PrivateKeyEntry,
Certificate fingerprint (MD5): C6:3C:76:F2:A6:EB:DA:A7:49:FD:35:93:74:9E:7A:B2

If you don't use LDAPS then you need to enable the two keymanagers in config/config.ldif  

dn: cn=JKS,cn=Key Manager Providers,cn=config
objectClass: ds-cfg-key-manager-provider
objectClass: ds-cfg-file-based-key-manager-provider
objectClass: top
ds-cfg-enabled: true
ds-cfg-java-class: org.opends.server.extensions.FileBasedKeyManagerProvider
ds-cfg-key-store-file: config/keystore
ds-cfg-key-store-type: JKS
ds-cfg-key-store-pin-file: config/
cn: JKS

dn: cn=JKS,cn=Trust Manager Providers,cn=config
objectClass: ds-cfg-file-based-trust-manager-provider
objectClass: ds-cfg-trust-manager-provider
objectClass: top
ds-cfg-enabled: true
ds-cfg-java-class: org.opends.server.extensions.FileBasedTrustManagerProvider
ds-cfg-trust-store-type: JKS
ds-cfg-trust-store-file: config/truststore
cn: JKS

To get more details you can enable the debug logger 

dn: cn=File-Based Debug Logger,cn=Loggers,cn=config
objectClass: ds-cfg-log-publisher
objectClass: ds-cfg-debug-log-publisher
objectClass: ds-cfg-file-based-debug-log-publisher
objectClass: top
ds-cfg-asynchronous: false
cn: File-Based Debug Logger
ds-cfg-enabled: true
ds-cfg-java-class: org.opends.server.loggers.debug.TextDebugLogPublisher
ds-cfg-default-debug-level: error
ds-cfg-log-file-permissions: 640
ds-cfg-log-file: logs/debug

Customize the configuration of the Notification Handler.

Notification Handler Config

dn: cn=OpenIDM Notification Handler,cn=Account Status Notification Handlers,cn=config
objectClass: top
objectClass: ds-cfg-account-status-notification-handler
objectClass: ds-cfg-openidm-account-status-notification-handler
cn: OpenIDM Notification Handler
ds-cfg-java-class: org.forgerock.openidm.agent.accountchange.OpenidmAccountStatusNotificationHandler
ds-cfg-enabled: true
ds-cfg-attribute: password
ds-task-id: for-username
ds-cfg-attribute-type: entryUUID
ds-cfg-attribute-type: uid
ds-cfg-log-file: logs/pwsync
ds-cfg-update-interval: 0 seconds
ds-cfg-referrals-url: https://localhost:8444/openidm/managed/user
ds-cfg-ssl-cert-nickname: server-cert
ds-cfg-realm: openidm-localhost
ds-certificate-subject-dn: cn=localhost,o=OpenIDM Self-Signed Certificate
ds-cfg-key-manager-provider: cn=JKS,cn=Key Manager Providers,cn=config
ds-cfg-trust-manager-provider: cn=JKS,cn=Trust Manager Providers,cn=config

You have configured the Password notification handler.


default value: password

      "replace" : "/password",
      "value" : "newPassw0rd"


default value: for-username



Specifies the attribute types that this plug-in will send along with the password change.


Specifies the log file location where the changed passwords are written when the plug-in cannot contact OpenIDM.


If this value is 0, then the updates are made synchronously in the foreground.



Specifies the nickname (also called the alias) of the certificate that the plug-in will use when performing SSL communication.


The alias of the private key that should be used to decrypt the session key.


The subject dn of the certificate that should be used to encrypt the session key.


Specifies the name of the key manager that is used.


Specifies the name of the trust manager that is used.

Start the OpenDJ instance:

$ bin/start-ds

You should notice a line like this in logs/server: 

[] category=EXTENSIONS severity=INFORMATION msgID=1049147 msg=Loaded extension from file '.../OpenDJ-2.4.0/lib/extensions/openidm-account-status-notification-handler.jar' (build <unknown>, revision <unknown>)

Activating the plugin so that password changes are captured and processed by the plugin:

$ dsconfig set-password-policy-prop \
--policy-name "Default Password Policy" \
--set "account-status-notification-handler:OpenIDM Notification Handler" \
--hostname localhost \
--port 4444 \
--trustStorePath config/admin-truststore \
--bindDN cn=Directory\ Manager \
--bindPassword <your_password> \


Test REST Service

POST [https://localhost:8080/openidm/managed/user?_action=patch&_query-id=for-username&uid=DDOE] HTTPS/1.1
      "replace" : "/password",
      "value" :
            "$crypto" :
                  "value" :
                        "data" : "VH4yKk02BpEH51eURTZkwA==",
                        "cipher" : "AES/ECB/PKCS5Padding",
                        "key" :
                              "data" : "klZOKaKL9jcFbR2GzryP45RXsA9iXdeXqqyPGTnb9cp9hLXhS15Fz57+TBa5iach3p8NySXAG0ljjbaZx5AYNjEPEopdS52MV2R7zr0YyJzst0IsoNFZy1TG1s7oHZT8MKkSqdIcHd92JeYW5UTJQIX2AhzG1sX6vMf0DRglsYU=",
                              "cipher" : "RSA/ECB/OAEPWithSHA1AndMGF1Padding",
                              "key" : "openidm-cert"
                  "type" : "x-simple-encryption"

Connect as cn=Directory Manager:

$ bin/ldapmodify -p 389 -D "cn=Directory Manager" -w <your_password>
dn: uid=user.0,ou=people,dc=example,dc=com
changetype: modify
replace: userPassword
userPassword: newPassword
Processing MODIFY request for uid=user.0,ou=people,dc=example,dc=com
MODIFY operation successful for DN uid=user.0,ou=people,dc=example,dc=com

Connect as user:

$ bin/ldapmodify -p 389 -D "uid=user.0,ou=people,dc=example,dc=com" -w password
dn: uid=user.0,ou=people,dc=example,dc=com
changetype: modify
replace: userPassword
userPassword: newPassword
Processing MODIFY request for uid=user.0,ou=people,dc=example,dc=com
MODIFY operation successful for DN uid=user.0,ou=people,dc=example,dc=com
  • No labels