Directory Services 7.4.3

Authentication mechanisms

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

LDAP is a stateful protocol, where the client sets up and maintains a connection with the server, potentially performing many operations or long-lived operations before disconnecting from the LDAP server. One of the LDAP operations, a bind, authenticates the client to the server. A bind is the first operation that a client performs after setting up a connection. Clients can bind again on the same connection to reauthenticate.

At the transport layer, DS servers support SSL and TLS protocols with mutual client authentication. This level of authentication is useful to properly secure connections. The authentication at this level is handled by the underlying JVM. The client identity verified at this level is not available to the DS server for the purpose of fine-grained authorization. For fine-grained authorization, you need LDAP authentication.

DS servers support multiple authentication mechanisms for LDAP operations:

Simple bind (name/password) authentication

The client application presents a bind DN/password combination. The server checks that the password matches the password on the entry with the specified bind DN.

This mechanism involves sending the credentials over the network. Always use secure connections at the transport layer when you expect simple LDAP binds. You can configure either or both LDAPS and StartTLS, depending on what the client applications support.

For additional information, refer to Simple binds.

Anonymous authentication

Simple bind authentication without credentials.

Anonymous authentication lets the server make authorization decisions when the client identity is unknown.

Allow anonymous authentication for publicly readable resources, such as root DSE attributes. Configure access control to let anonymous and other users read them.

For additional information, refer to Anonymous access.

SASL authentication

Simple Authentication and Security Layer (SASL) is a framework, rather than a single method. DS servers provide handlers for a number of SASL mechanisms, including strong authentication choices like the External SASL mechanism handler for certificate-based authentication, and the GSSAPI SASL mechanism handler for use with Kerberos v5 systems.

Certificate-based authentication is well-suited for applications where distributing keys is easier than protecting passwords. For additional information, refer to Certificate-based authentication.

GSSAPI-based authentication is useful for interoperation with Kerberos. For additional information, refer to Authenticate with Kerberos.

Authentication with proxied authorization

The client application binds with its credentials, and uses proxied authorization to perform operations as another user.

Client applications can use another means to authenticate the user before requesting proxied authorization. For details, refer to Proxied authorization.

Pass-through authentication to another LDAP directory

The client application binds with its credentials, and another LDAP directory service handles the authentication. This is known as pass-through authentication.

Pass-through authentication is useful when credentials are stored in a remote directory service, and the DS directory service stores part of the user profile. For details, refer to Pass-through authentication.

DS servers and HDAP gateways support multiple HTTP authentication mechanisms.

The identity from the HTTP request is mapped to an LDAP account for use in authorization decisions, so the mechanisms are known as authorization mechanisms. Their configuration is described in Configure HTTP Authorization. The following authorization mechanisms are available:

HTTP Basic authorization

The client application sends an HTTP request that uses HTTP Basic authentication.

The client application can alternatively send an HTTP request with username and password headers.

You configure DS software to map the HTTP username to an LDAP DN. The result is like a simple name/password bind.

This mechanism involves sending the credentials over the network. Always use secure connections at the transport layer when you allow HTTP Basic.

Anonymous authorization

The client application sends an HTTP request without authenticating.

You configure DS software either to map the HTTP request to anonymous authentication at the LDAP level, or to bind at the LDAP level as a specific user.

OAuth 2.0 authorization

The client application sends an HTTP request bearing an OAuth 2.0 access token that includes at least one scope whose value makes it possible to determine the user identity.

You configure DS software to resolve the access token, and to map the user identity from the scope to an LDAP account.

This mechanism involves sending the credentials over the network. Always use secure connections at the transport layer for OAuth 2.0 authorization.

Anonymous access

In LDAP, an anonymous bind is a bind operation using simple authentication with an empty DN and an empty password. DS servers apply access controls (ACIs) to let anonymous clients access only fully public information. Examples include information about the directory server in the root DSE, and LDAP schema definitions.

By default, DS servers disable anonymous access to directory data. ACIs take a user DN subject, ldap:///anyone, that matches anonymous and authenticated users.

When a client accesses the directory over HTTP, anonymous operations can be mapped either to a specific user identity or to an anonymous user (default). This is set using the HTTP Anonymous authorization mechanism for the HTTP endpoint.

Simple binds

In LDAP, a simple bind is name/password authentication. The client application presents a bind DN/password combination. The DS server checks that the password matches the password on the entry with the specified bind DN.

The LDAP connection transport layer must be secure for a simple bind. Otherwise, eavesdroppers can read the credentials.

DS servers provide two alternatives to secure the connection for a simple bind, both of which depend on certificates and public key infrastructure:

LDAPS

To support LDAP over SSL and TLS, DS servers have a separate connection handler that listens for traffic on a port dedicated to secure connections.

LDAP with StartTLS

DS servers support using the StartTLS extended operation on an insecure LDAP port. With StartTLS, the client initiates the connection on the LDAP port, and then negotiates a secure connection.

Pass-through authentication

Pass-Through Authentication (PTA), a remote LDAP service to determine the response to an authentication request. A typical use case for PTA involves passing authentication through to Active Directory for users coming from Microsoft Windows systems.

About PTA

You use PTA when the credentials for authenticating are stored in a remote directory service. In effect, the DS server redirects the bind operation against a remote LDAP server.

The method a server uses to redirect the bind depends on the mapping from the user entry in the DS server to the corresponding user entry in the remote directory. DS servers provide you several choices to set up the mapping:

  • When both the local entry in the DS server and the remote entry in the other server have the same DN, you do not have to set up the mapping. By default, the DS server redirects the bind with the original DN and password from the client application.

  • When the local entry in the DS server has an attribute holding the DN of the remote entry, you can specify which attribute holds the DN. The DS server redirects the bind on the remote server using the DN value.

  • When you cannot get the remote bind DN directly, you need an attribute and value on the DS entry that corresponds to an identical attribute and value on the remote server. In this case, you also need the bind credentials for a user who can search for the entry on the remote server. The DS server performs a search for the entry using the matching attribute and value, and then redirects the bind with the DN from the remote entry.

You configure PTA as an authentication policy that you associate with a user’s entry in the same way that you associate a password policy with a user’s entry. Either a user has an authentication policy for PTA, or the user has a local password policy.

Set up PTA

When setting up PTA, you need to know define:

  • Which remote server(s) to redirect binds to

  • How you map user entries in the DS server to user entries in the remote directory

Secure connections

When performing PTA, you protect communications between the DS server and the authenticating server. When you test secure connections with a CA that is not well-known, make sure the authentication server’s certificate is trusted by the DS server.

If the authentication server’s CA is well-known or already trusted by the DS server, you can skip these steps:

  1. Export the CA or server certificate from the authentication server.

    How you perform this step depends on the authentication directory server.

  2. Record the hostname used in the certificate.

    You use the hostname when configuring the secure connection.

  3. Import the trusted authentication server certificate into the DS server’s keystore.

Configure a PTA policy

Configure authentication policies with the dsconfig command. Notice that authentication policies are part of the server configuration, and therefore not replicated:

  1. Set up an authentication policy for PTA to the authentication server:

    $ dsconfig \
     create-password-policy \
     --hostname localhost \
     --port 4444 \
     --bindDN uid=admin \
     --bindPassword password \
     --policy-name "PTA Policy" \
     --type ldap-pass-through \
     --set primary-remote-ldap-server:remote-server.example.com:1636 \
     --set mapped-attribute:uid \
     --set mapped-search-base-dn:"dc=example,dc=com" \
     --set mapping-policy:mapped-search \
     --set use-ssl:true \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --no-prompt

    The policy shown here maps identities with this password policy to identities under dc=example,dc=com on the authentication server. Users must have the same uid values on both servers. This policy uses LDAPS between the DS server and the authentication server.

  2. Check that your policy has been added to the list:

    $ dsconfig \
     list-password-policies \
     --hostname localhost \
     --port 4444 \
     --bindDN uid=admin \
     --bindPassword password \
     --property use-ssl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --no-prompt
    
    Password Policy         : Type              : use-ssl
    ------------------------:-------------------:--------
    Default Password Policy : password-policy   : -
    PTA Policy              : ldap-pass-through : true
    Root Password Policy    : password-policy   : -

Use PTA To active directory

The steps below demonstrate how to set up PTA to Active Directory. The information that follows will help you make sense of the steps.

Entries on the DS side use uid as the naming attribute, and entries also have cn attributes. Active Directory entries use cn as the naming attribute. User entries on both sides share the same cn values. The mapping between entries therefore uses cn.

Consider a deployment where the DS account with cn=LDAP PTA User and DN uid=ldapptauser,ou=People,dc=example,dc=com corresponds to an Active Directory account with DN CN=LDAP PTA User,CN=Users,DC=internal,DC=forgerock,DC=com. The steps below enable the user with cn=LDAP PTA User on the DS server to authenticate through Active Directory:

$ ldapsearch \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=kvaughan,ou=people,dc=example,dc=com \
 --bindPassword bribery
 --baseDN dc=example,dc=com \
 uid=ldapptauser \
 cn

dn: uid=ldapptauser,ou=People,dc=example,dc=com
cn: LDAP PTA User
$ ldapsearch \
 --hostname ad.example.com \
 --port 636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --baseDN "CN=Users,DC=internal,DC=forgerock,DC=com" \
 --bindDN "cn=administrator,cn=Users,DC=internal,DC=forgerock,DC=com" \
 --bindPassword password \
 "(cn=LDAP PTA User)" \
 cn

dn: CN=LDAP PTA User,CN=Users,DC=internal,DC=forgerock,DC=com
cn: LDAP PTA User

The DS server must map the uid=ldapptauser,ou=People,dc=example,dc=com entry to the Active Directory CN=LDAP PTA User,CN=Users,DC=internal,DC=forgerock,DC=com entry. In order to do the mapping, the DS server must search for the user in Active Directory, using the cn value that it recovers from its own entry for the user. Active Directory does not allow anonymous searches, so part of the authentication policy configuration consists of the administrator DN and password the DS server uses to bind to Active Directory to search.

Finally, before setting up the PTA policy, make sure the DS server can connect to Active Directory over a secure connection to avoid sending passwords in the clear.

  1. Export the certificate from the Windows server.

    • Select start > All Programs > Administrative Tools > Certification Authority, then right-click the CA and select Properties.

    • In the General tab, select the certificate and select View Certificate.

    • In the Certificate dialog, select the Details tab, then select Copy to File.

    • Use the Certificate Export Wizard to export the certificate to a file, such as windows.cer .

  2. Copy the exported certificate to the system running the DS server.

  3. Import the server certificate into the DS keystore:

    $ keytool \
     -importcert \
     -alias ad-cert \
     -keystore /path/to/opendj/config/keystore \
     -storepass:file /path/to/opendj/config/keystore.pin \
     -storetype PKCS12 \
     -file ~/Downloads/windows.cer \
     -noprompt
    
    Certificate was added to keystore

    At this point, the DS server can connect securely to Active Directory.

  4. Set up an authentication policy for DS users to authenticate to Active Directory:

    # Create a trust manager provider to access the Active Directory certificate:
    $ dsconfig \
     create-trust-manager-provider \
     --hostname localhost \
     --port 4444 \
     --bindDN uid=admin \
     --bindPassword password \
     --provider-name PKCS12 \
     --type file-based \
     --set enabled:true \
     --set trust-store-type:PKCS12 \
     --set trust-store-file:config/keystore \
     --set trust-store-pin:"&{file:config/keystore.pin}" \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --no-prompt
    
    # Use the trust manager provider in the PTA policy:
    $ dsconfig \
     create-password-policy \
     --hostname localhost \
     --port 4444 \
     --bindDN uid=admin \
     --bindPassword password \
     --type ldap-pass-through \
     --policy-name "AD PTA Policy" \
     --set primary-remote-ldap-server:ad.example.com:636 \
     --set mapped-attribute:cn \
     --set mapped-search-base-dn:"CN=Users,DC=internal,DC=forgerock,DC=com" \
     --set mapped-search-bind-dn:"cn=administrator,cn=Users,DC=internal,DC=forgerock,DC=com" \
     --set mapped-search-bind-password:password \
     --set mapping-policy:mapped-search \
     --set trust-manager-provider:PKCS12 \
     --set use-ssl:true \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --no-prompt
  5. Assign the authentication policy to a test user:

    $ ldapmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=admin \
     --bindPassword password << EOF
    dn: uid=ldapptauser,ou=People,dc=example,dc=com
    changetype: modify
    add: ds-pwp-password-policy-dn
    ds-pwp-password-policy-dn: cn=AD PTA Policy,cn=Password Policies,cn=config
    EOF
  6. Check that the user can bind using PTA to Active Directory:

    $ ldapsearch \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --baseDN dc=example,dc=com \
     --bindDN uid=ldapptauser,ou=People,dc=example,dc=com \
     --bindPassword password \
     "(cn=LDAP PTA User)" \
     userpassword cn
    
    dn: uid=ldapptauser,ou=People,dc=example,dc=com
    cn: LDAP PTA User

    Notice that to complete the search, the user has authenticated with a password to Active Directory. No userpassword value is present in the DS service.

Assign PTA policies

You assign authentication policies in the same way as you assign password policies, by using the ds-pwp-password-policy-dn attribute.

Although you assign the PTA policy using the same attribute as for password policy, the authentication policy is not in fact a password policy. Therefore, the user with a PTA policy does not have the operational attribute pwdPolicySubentry.

Assign a PTA policy to a user

Users depending on PTA no longer need a local password policy, as they no longer authenticate locally.

Examples in the following procedure work for this user, whose entry is as shown below. Notice that the user has no userPassword attribute. The user’s password on the authentication server is password:

dn: uid=ptaUser,ou=People,dc=example,dc=com
uid: ptaUser
objectClass: top
objectClass: person
objectClass: organizationalperson
objectClass: inetorgperson
uid: ptaUser
cn: PTA User
sn: User

This user’s entry on the authentication server has uid=ptaUser. The PTA policy performs the mapping to find the user entry in the authentication server:

  1. Give an administrator access to update a user’s password policy:

    $ ldapmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=admin \
     --bindPassword password << EOF
    dn: ou=People,dc=example,dc=com
    changetype: modify
    add: aci
    aci: (targetattr = "ds-pwp-password-policy-dn")
     (version 3.0;acl "Allow Kirsten Vaughan to assign password policies";
     allow (all) (userdn = "ldap:///uid=kvaughan,ou=People,dc=example,dc=com");)
    EOF
  2. Update the user’s ds-pwp-password-policy-dn attribute:

    $ ldapmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=kvaughan,ou=people,dc=example,dc=com \
     --bindPassword bribery << EOF
    dn: uid=ptaUser,ou=People,dc=example,dc=com
    changetype: modify
    replace: ds-pwp-password-policy-dn
    ds-pwp-password-policy-dn: cn=PTA Policy,cn=Password Policies,cn=config
    EOF
  3. Check that the user can authenticate through to the authentication server:

    $ ldapsearch \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --baseDN dc=example,dc=com \
     --bindDN uid=ptaUser,ou=People,dc=example,dc=com \
     --bindPassword chngthspwd \
     "(uid=ptaUser)" \
     1.1
    
    dn: uid=ptaUser,ou=People,dc=example,dc=com

Assign a PTA policy to a group

Examples in the following steps use the PTA policy defined previously. The administrator’s entry is present on the authentication server:

  1. Give an administrator the privilege to write subentries, such as those used for password policies:

    $ ldapmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=admin \
     --bindPassword password << EOF
    dn: uid=kvaughan,ou=People,dc=example,dc=com
    changetype: modify
    add: ds-privilege-name
    ds-privilege-name: subentry-write
    EOF

    Notice here that the directory superuser, uid=admin, assigns privileges. Any administrator with the privilege-change privilege can assign privileges. However, if the administrator can update administrator privileges, they can assign themselves the bypass-acl privilege. Then they are no longer bound by access control instructions, including both user data ACIs and global ACIs. For this reason, do not assign the privilege-change privilege to normal administrator users.

  2. Create a subentry for a collective attribute that sets the ds-pwp-password-policy-dn attribute for group members' entries:

    $ ldapmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=kvaughan,ou=people,dc=example,dc=com \
     --bindPassword bribery << EOF
    dn: cn=PTA Policy for Dir Admins,dc=example,dc=com
    objectClass: collectiveAttributeSubentry
    objectClass: extensibleObject
    objectClass: subentry
    objectClass: top
    cn: PTA Policy for Dir Admins
    ds-pwp-password-policy-dn;collective: cn=PTA Policy,cn=Password Policies,cn=config
    subtreeSpecification: { base "ou=People", specificationFilter
      "(isMemberOf=cn=Directory Administrators,ou=Groups,dc=example,dc=com)"}
    EOF

    The base entry identifies the branch that holds administrator entries.

  3. Check that the DS server has applied the policy.

    • Make sure you can bind as the user on the authentication server:

      $ ldapsearch \
       --hostname remote-server.example.com \
       --port 1636 \
       --useSsl \
       --usePkcs12TrustStore /path/to/opendj/config/keystore \
       --trustStorePassword:file /path/to/opendj/config/keystore.pin \
       --bindDN "uid=kvaughan,ou=People,dc=example,dc=com" \
       --bindPassword bribery \
       --baseDN "dc=example,dc=com" \
       "(uid=kvaughan)" \
       1.1
      
      dn: uid=kvaughan,ou=People,dc=example,dc=com
    • Check that the user can authenticate through to the authentication server from the DS server:

      $ ldapsearch \
       --hostname localhost \
       --port 1636 \
       --useSsl \
       --usePkcs12TrustStore /path/to/opendj/config/keystore \
       --trustStorePassword:file /path/to/opendj/config/keystore.pin \
       --bindDN "uid=kvaughan,ou=people,dc=example,dc=com" \
       --bindPassword bribery \
       --baseDN dc=example,dc=com \
       "(uid=kvaughan)" \
       1.1
      
      dn: uid=kvaughan,ou=People,dc=example,dc=com

Certificate-based authentication

One alternative to simple binds with user name/password combinations consists of storing a digital certificate on the LDAP entry, and using the certificate as credentials during the bind. You can use this mechanism, for example, to let applications bind without using passwords.

By setting up a secure connection with a certificate, the client is in effect authenticating to the server. The server must close the connection if it cannot trust the client certificate. However, the certificate presented when establishing a secure connection does not authenticate the client. The secure connection is established by the JVM at the transport layer, independently of the LDAP protocol.

When binding with a certificate, the client must request the SASL external mechanism. The DS server maps the certificate to the client’s entry in the directory. When it finds a matching entry, and the entry contains a certificate, the DS server can check whether the certificate in the entry matches the certificate from the request. It depends on the certificate-validation-policy setting of the SASL external handler. On success, the server sets the authorization identity for the connection, and the bind is successful.

For the whole process of authenticating with a certificate to work smoothly, the DS server and the client must trust each others' certificates, and the DS server must be configured to map the certificate to the client entry.

Add certificate attributes to the client entry

Before a client tries to bind to DS servers using a certificate, create a certificate, and add appropriate certificate attributes to the client’s entry.

The ds-evaluation setup profile includes the entry, cn=My App,ou=Apps,dc=example,dc=com, used in these examples. The client key store password is stored in a MY_KEYSTORE_PIN environment variable:

  1. Create a certificate using the DN of the client entry as the subject DN.

    This example uses the dskeymgr command to generate a key pair. The certificate is signed by the private CA based on the deployment ID used when setting up DS servers. Servers set up with the same deployment ID trust the CA, and so can trust the client’s certificate:

    $ dskeymgr \
     create-tls-key-pair \
     --deploymentId $DEPLOYMENT_ID \
     --deploymentIdPassword password \
     --alias myapp-cert \
     --subjectDn "cn=My App,ou=Apps,dc=example,dc=com" \
     --keyStoreFile /path/to/opendj/my-keystore \
     --keyStorePassword $MY_KEYSTORE_PIN

    For more command options, refer to dskeymgr. The default validity for the certificate is one year.

  2. Make note of the certificate SHA-256 fingerprint.

    Later in this procedure you update the client application entry with the SHA-256 fingerprint, referred to henceforth as SHA265_FINGERPRINT:

    $ keytool \
     -list \
     -v \
     -alias myapp-cert \
     -keystore /path/to/opendj/my-keystore \
     -storepass $MY_KEYSTORE_PIN | awk '/SHA256:/{print $2}'
    
    SHA256_FINGERPRINT
  3. Modify the entry to add attributes related to the certificate.

    For example, add the client certificate fingerprint on the ds-certificate-fingerprint attribute. This example uses the SHA-256 fingerprint, which is the default for the fingerprint certificate mapper.

    To require that the certificate is issued by a known CA, use the ds-certificate-issuer-dn attribute. Use this to verify the certificate issuer whenever multiple CAs are trusted in order to prevent impersonation. Different CAs can issue certificates with the same subject DN, but not with the same issuer DN. You must also specify the issuer attribute in the certificate mapper configuration, as shown below.

    To map the certificate subject DN to an attribute of the entry, use the ds-certificate-subject-dn attribute.

    The following entry demonstrates all these attributes. Save the entry in a file addcert.ldif in order to edit the fingerprint:

    dn: cn=My App,ou=Apps,dc=example,dc=com
    changetype: modify
    add: objectclass
    objectclass: ds-certificate-user
    -
    add: ds-certificate-fingerprint
    ds-certificate-fingerprint: SHA256_FINGERPRINT
    -
    add: ds-certificate-issuer-dn
    ds-certificate-issuer-dn: CN=Deployment key,O=ForgeRock.com
    -
    add: ds-certificate-subject-dn
    ds-certificate-subject-dn: CN=My App, OU=Apps, DC=example, DC=com

    Replace the certificate fingerprint with the actual fingerprint before adding the certificate:

    $ ldapmodify \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=kvaughan,ou=People,dc=example,dc=com \
     --bindPassword bribery \
     addcert.ldif
  4. Check your work:

    $ ldapsearch \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --bindDN uid=kvaughan,ou=People,dc=example,dc=com \
     --bindPassword bribery \
     --baseDN dc=example,dc=com \
     "(cn=My App)"
    
    dn: cn=My App,ou=Apps,dc=example,dc=com
    objectClass: top
    objectClass: applicationProcess
    objectClass: simpleSecurityObject
    objectClass: ds-certificate-user
    cn: My App
    ds-certificate-fingerprint: SHA256_FINGERPRINT
    ds-certificate-issuer-dn: CN=Deployment key,O=ForgeRock.com
    ds-certificate-subject-dn: CN=My App, OU=Apps, DC=example, DC=com

Trust a third-party client certificate

If you control the client application, use your private CA to sign its certificate. This can be done as demonstrated in Add certificate attributes to the client entry. You can then skip this procedure.

To trust the client certificate, a trust manager must be able to trust the signing certificate (issuer). If the client certificate is self-signed or signed by an unknown CA, you must update the server’s truststore:

  1. Export the self-signed certificate or the CA certificate:

    $ keytool \
     -export \
     -alias myapp-cert \
     -keystore /path/to/opendj/my-keystore \
     -storepass:env MY_KEYSTORE_PIN \
     -keypass:env MY_KEYSTORE_PIN \
     -file /path/to/opendj/myapp-cert.crt
    
    Certificate stored in file </path/to/opendj/myapp-cert.crt>

    The command is similar for a CA certificate.

  2. Import the exported, trusted certificate into a server truststore.

    The following examples use the default server keystore and PIN:

    1. The following example imports the self-signed certificate exported in Step 1:

      $ keytool \
       -import \
       -alias myapp-cert \
       -file /path/to/opendj/myapp-cert.crt \
       -keystore /path/to/opendj/config/keystore \
       -storetype PKCS12 \
       -storepass:file /path/to/opendj/config/keystore.pin \
       -noprompt
      
      Certificate was added to keystore
    2. The following example imports an exported CA certificate in a file called ca.crt :

      $ keytool \
       -import \
       -alias ca-cert \
       -file ca.crt \
       -keystore /path/to/opendj/config/keystore \
       -storetype PKCS12 \
       -storepass:file /path/to/opendj/config/keystore.pin \
       -noprompt
      
      Certificate was added to keystore

Configure certificate mappers

DS servers use certificate mappers during binds to establish a mapping between a client certificate and the entry with the certificate. DS servers have the following certificate mappers:

Fingerprint Certificate Mapper

Looks for the certificate fingerprint in an attribute of the entry (default: ds-certificate-fingerprint).

Subject Attribute To User Attribute Mapper

Looks for a match between an attribute of the certificate subject and an attribute of the entry (default: match cn in the certificate to cn on the entry, or match emailAddress in the certificate to mail on the entry).

Subject DN to User Attribute Certificate Mapper

Looks for the certificate subject DN in an attribute of the entry (default: ds-certificate-subject-dn).

Subject Equals DN Certificate Mapper

Looks for an entry whose DN matches the certificate subject DN.

The following steps demonstrate how to use the Fingerprint Mapper default algorithm of SHA-256:

  1. List the certificate mappers to retrieve the correct name:

    $ dsconfig \
     list-certificate-mappers \
     --hostname localhost \
     --port 4444 \
     --bindDN uid=admin \
     --bindPassword password \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --no-prompt
    
    Certificate Mapper                  : Type                                : enabled
    ------------------------------------:-------------------------------------:--------
    Fingerprint Mapper                  : fingerprint                         : true
    Subject Attribute to User Attribute : subject-attribute-to-user-attribute : true
    Subject DN to User Attribute        : subject-dn-to-user-attribute        : true
    Subject Equals DN                   : subject-equals-dn                   : true
  2. Examine the current configuration:

    $ dsconfig \
     get-certificate-mapper-prop \
     --hostname localhost \
     --port 4444 \
     --bindDN uid=admin \
     --bindPassword password \
     --mapper-name "Fingerprint Mapper" \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --no-prompt
    
    Property              : Value(s)
    ----------------------:--------------------------------------------------------
    enabled               : true
    fingerprint-algorithm : sha256
    fingerprint-attribute : ds-certificate-fingerprint
    issuer-attribute      : The certificate issuer DN will not be verified.
    user-base-dn          : The server performs the search in all public naming
                          : contexts.
  3. Change the configuration as necessary.

  4. Set the External SASL Mechanism Handler to use the appropriate certificate mapper (default: Subject Equals DN):

    $ dsconfig \
     set-sasl-mechanism-handler-prop \
     --hostname localhost \
     --port 4444 \
     --bindDN uid=admin \
     --bindPassword password \
     --handler-name External \
     --set certificate-mapper:"Fingerprint Mapper" \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --no-prompt

Authenticate with the client certificate

Instead of providing a bind DN and password as for simple authentication, use the SASL EXTERNAL authentication mechanism, and provide the certificate. As a test with example data, you can try an anonymous search, then try with certificate-based authentication.

Before you try this example, make sure the DS server is set up to accept StartTLS from clients, and that you have set up the client certificate as described above. The password for the client key store is stored in a MY_KEYSTORE_PIN environment variable.

Also, if the DS server uses a certificate for StartTLS that was signed by a private CA, reference a truststore containing the CA certificate. In this example, the DS server uses a keystore with the CA certificate, and the client uses the keystore as its truststore.

Notice that the DS server does not allow an anonymous user to modify its description:

$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin << EOF
dn: cn=My App,ou=Apps,dc=example,dc=com
changetype: modify
replace: description
description: New description

EOF

# The LDAP modify request failed: 50 (Insufficient Access Rights)
# Additional Information:  The entry cn=My App,ou=Apps,dc=example,dc=com cannot be modified due to insufficient access rights

After the client binds successfully, it can modify its description:

$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --saslOption mech="EXTERNAL" \
 --certNickName myapp-cert \
 --keyStorePath /path/to/opendj/my-keystore \
 --keyStorePassword $MY_KEYSTORE_PIN <<EOF
dn: cn=My App,ou=Apps,dc=example,dc=com
changetype: modify
replace: description
description: New description

EOF

# MODIFY operation successful for DN cn=My App,ou=Apps,dc=example,dc=com

You can also try the same test with other certificate mappers.

This example uses the fingerprint mapper:

$ dsconfig \
 set-sasl-mechanism-handler-prop \
 --hostname localhost \
 --port 4444 \
 --bindDN uid=admin \
 --bindPassword password \
 --handler-name External \
 --set certificate-mapper:"Fingerprint Mapper" \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --no-prompt

$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --saslOption mech="EXTERNAL" \
 --certNickName myapp-cert \
 --keyStorePath /path/to/opendj/my-keystore \
 --keyStorePassword $MY_KEYSTORE_PIN <<EOF
dn: cn=My App,ou=Apps,dc=example,dc=com
changetype: modify
replace: description
description: New description

EOF

# MODIFY operation successful for DN cn=My App,ou=Apps,dc=example,dc=com

This example uses the subject attribute to user attribute mapper:

$ dsconfig \
 set-sasl-mechanism-handler-prop \
 --hostname localhost \
 --port 4444 \
 --bindDN uid=admin \
 --bindPassword password \
 --handler-name External \
 --set certificate-mapper:"Subject Attribute to User Attribute" \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --no-prompt

$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --saslOption mech="EXTERNAL" \
 --certNickName myapp-cert \
 --keyStorePath /path/to/opendj/my-keystore \
 --keyStorePassword $MY_KEYSTORE_PIN <<EOF
dn: cn=My App,ou=Apps,dc=example,dc=com
changetype: modify
replace: description
description: New description

EOF

# MODIFY operation successful for DN cn=My App,ou=Apps,dc=example,dc=com

This example uses the subject DN to user attribute mapper:

$ dsconfig \
 set-sasl-mechanism-handler-prop \
 --hostname localhost \
 --port 4444 \
 --bindDN uid=admin \
 --bindPassword password \
 --handler-name External \
 --set certificate-mapper:"Subject DN to User Attribute" \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --no-prompt

$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --saslOption mech="EXTERNAL" \
 --certNickName myapp-cert \
 --keyStorePath /path/to/opendj/my-keystore \
 --keyStorePassword $MY_KEYSTORE_PIN <<EOF
dn: cn=My App,ou=Apps,dc=example,dc=com
changetype: modify
replace: description
description: New description

EOF

# MODIFY operation successful for DN cn=My App,ou=Apps,dc=example,dc=com

Authenticate With a Third-Party Certificate

When a client application authenticates with a self-signed certificate or a certificate signed by a public CA, the easiest certificate mapper to use is the fingerprint mapper. When using any other certificate mapper, make sure that the client certificate is in the client’s entry, and that the SASL EXTERNAL handler has a certificate-validation-policy:ifpresent (default), or certificate-validation-policy:always. Any client certificate can be used to secure TLS for the connection. However, to trust the certificate for authentication, the server must ensure a unique match between the client’s certificate and the client’s entry.

A client application creating its own certificate can set subject DN, issuer DN, and other fields as desired, so these cannot be used to established trust. When obtaining a signature from a public CA, the client might set many fields as desired. The issuer DN guarantees only that the CA signed the certificate.

The following example demonstrates safe use of blind trust and fingerprint mapping. This demonstration is also appropriate when clients use certificates signed by public CAs, in which case, you could use the JVM trust manager, for example.

Enable a blind trust manager:

$ dsconfig \
 create-trust-manager-provider \
 --hostname localhost \
 --port 4444 \
 --bindDN uid=admin \
 --bindPassword password \
 --type blind \
 --provider-name "Blind Trust" \
 --set enabled:true \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --no-prompt

Use SHA-256 as the fingerprint certificate mapper algorithm, which is the default.

Configure the handler for SASL EXTERNAL binds to use the fingerprint mapper, rather than the default subject DN mapper. As in this example, do not enable a more lenient mapper when using blind trust or public trust:

$ dsconfig \
 set-sasl-mechanism-handler-prop \
 --hostname localhost \
 --port 4444 \
 --bindDN uid=admin \
 --bindPassword password \
 --handler-name External \
 --set certificate-mapper:"Fingerprint Mapper" \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --no-prompt

After making these configuration changes, enable the trust manager on the appropriate connection handler. The following command enables blind trust on the LDAP connection handler, where the client will use StartTLS. Notice that only blind trust is enabled. If you want to allow blind trust for some applications and private CA trust for others, use a separate connection handler listening on a separate port:

$ dsconfig \
 set-connection-handler-prop \
 --hostname localhost \
 --port 4444 \
 --bindDN uid=admin \
 --bindPassword password \
 --handler-name LDAP \
 --set trust-manager-provider:"Blind Trust" \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --no-prompt

Make sure the client application certificate fingerprints use SHA-256. The following command updates the example client entry to change the fingerprint appropriately:

$ SHA256_FINGERPRINT=$(keytool \
 -list \
 -v \
 -alias myapp-cert \
 -keystore /path/to/opendj/my-keystore \
 -storepass $MY_KEYSTORE_PIN | awk '/SHA256:/{print $2}')

$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=kvaughan,ou=People,dc=example,dc=com \
 --bindPassword bribery << EOF
dn: cn=My App,ou=Apps,dc=example,dc=com
changetype: modify
replace: ds-certificate-fingerprint
ds-certificate-fingerprint: $SHA256_FINGERPRINT

EOF

When the client binds successfully, it can modify its description. The server JVM checks client certificate validity and proves the client has the private key during the process of setting up TLS. During the SASL EXTERNAL bind, the server verifies that the fingerprint in the client entry matches the certificate:

$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --saslOption mech="EXTERNAL" \
 --certNickName myapp-cert \
 --keyStorePath /path/to/opendj/my-keystore \
 --keyStorePassword $MY_KEYSTORE_PIN <<EOF
dn: cn=My App,ou=Apps,dc=example,dc=com
changetype: modify
replace: description
description: New description

EOF

# MODIFY operation successful for DN cn=My App,ou=Apps,dc=example,dc=com

For additional verification during the bind, include the client certificate in the client’s entry.

Authenticate with Kerberos

Windows and Linux systems support Kerberos v5 authentication, which can operate safely on an open, unprotected network. In Kerberos authentication, the client application obtains temporary credentials for a service from an authorization server, in the form of tickets and session keys. The service server must be able to handle its part of the Kerberos mutual authentication process.

DS servers can interoperate with Kerberos systems through their GSSAPI SASL authentication mechanism.

Meet the following constraints when working with Kerberos systems:

  • The clocks on the host systems where the DS server runs must be kept in sync with other hosts in the system.

    For example, you can use Network Time Protocol (NTP) services to keep the clocks in sync.

  • Each DS server needs its own keytab file, the file which holds its pairs of Kerberos principals and keys.

  • DS server logging can display exceptions about unsupported encryption types when a mismatch occurs. The exceptions are visible only when you activate debug-level logging.

Configure DS as a Kerberos service server

Follow these steps when setting up DS servers as Kerberos service servers:

  1. Make sure the clock on the DS server host system is in sync with the other hosts' clocks in the Kerberos system.

  2. Make sure that DNS resolves fully qualified domain names (FQDN) correctly on all systems involved.

  3. Make sure the necessary ports are open on the DS server host system.

  4. Make sure the encryption strengths required by the Kerberos system are supported by the JVM that the DS server uses.

  5. Make sure that Kerberos is operating correctly for other services, including Kerberos client services on the DS server host.

    This step depends on the implementation, but usually includes adding a Kerberos principal for the host.

  6. Add a Kerberos principal for the DS server, such as ldap/ds.example.com.

  7. Create a keytab file for the DS server.

    This step depends on the Kerberos implementation, but generally consists of extracting the key for the DS server Kerberos principal, such as ldap/ds.example.com on the host where the DS server runs.

  8. Make the keytab file readable only by the DS server, and copy it to the /path/to/opendj/config/ directory.

  9. Configure the DS server to handle GSSAPI SASL authentication.

    The following example binds the server to server-fqdn, the DNS-resolvable FQDN for the system:

    $ dsconfig \
     set-sasl-mechanism-handler-prop \
     --handler-name GSSAPI \
     --set enabled:true \
     --set keytab:/path/to/opendj/config/opendj.keytab \
     --set server-fqdn:ds.example.com \
     --hostname localhost \
     --port 4444 \
     --bindDN uid=admin \
     --bindPassword password \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --no-prompt

    To accept Kerberos authentication requests for more than one service principal, add the --set bind-to-server-fqdn:false advanced option.

    In addition, the JVM may require setting --set server-fqdn:* instead of using the FQDN.

    Some JVMs may not support running without binding to the server FQDN.

  10. If your Kerberos principal user identifiers are not of the form name@realm, configure an appropriate identity-mapper for the GSSAPI SASL mechanism handler.

    By default, the DS server uses the regular expression identity mapper, which expects user identifiers to match the pattern ^([^@])@.$. It maps the string before @ to the value of the UID attribute. This works well for identifiers like bjensen@EXAMPLE.COM. For background information, refer to Identity mappers.

  11. Restart the DS server to ensure the configuration changes are taken into account:

    $ stop-ds --restart
    
    ...GSSAPI SASL mechanism using a server fully qualified domain name of:
     ds.example.com
    ...GSSAPI mechanism using a principal name of:
     principal="opendj/ds.example.com"
    ...The GSSAPI SASL mechanism handler initialization was successful
  12. Test that the mechanism works, by authenticating as a Kerberos user:

    $ ldapsearch \
     --hostname localhost \
     --port 1636 \
     --useSsl \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --baseDN dc=example,dc=com \
     --saslOption mech=GSSAPI \
     --saslOption authid=bjensen@EXAMPLE.COM \
     uid=bjensen \
     cn
    
    dn: uid=bjensen,ou=People,dc=example,dc=com
    cn: Barbara Jensen
    cn: Babs Jensen