public boolean checkAuthentication(Rdn[] userRDN, String password) {
        Log.debug("In LdapManager.checkAuthentication(userDN, password), userRDN is: " + Arrays.toString(userRDN) + "...");

        if (!sslEnabled && !startTlsEnabled && lastUnencryptedWarning.isBefore(Instant.now().minus(UNENCRYPTED_WARNING_SUPPRESSION.getValue()))) {
            Log.warn("Using unencrypted connection to LDAP service! Consider reconfiguring the connection between Openfire and your AD/LDAP server. This warning will be suppressed for {}", UNENCRYPTED_WARNING_SUPPRESSION.getValue());
            lastUnencryptedWarning = Instant.now();
        }


        JiveInitialLdapContext ctx = null;
        try {
            // See if the user authenticates.
            Hashtable<String, Object> env = new Hashtable<>();
            env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
            env.put(Context.PROVIDER_URL, getProviderURL(baseDN));
            if (sslEnabled) {
                env.put("java.naming.ldap.factory.socket", "org.jivesoftware.util.SimpleSSLSocketFactory");
                env.put(Context.SECURITY_PROTOCOL, "ssl");
            }

            /* If startTLS is requested we MUST NOT bind() before
             * the secure connection has been established. */
            if (!(startTlsEnabled && !sslEnabled)) {
                env.put(Context.SECURITY_AUTHENTICATION, "simple");
                env.put(Context.SECURITY_PRINCIPAL, createNewAbsolute( baseDN, userRDN ).toString() );
                env.put(Context.SECURITY_CREDENTIALS, password);
            } else {
                if (followReferrals) {
                    Log.warn("\tConnections to referrals are unencrypted! If you do not want this, please turn off ldap.autoFollowReferrals");
                }
            }

            if (connTimeout > 0) {
                    env.put("com.sun.jndi.ldap.connect.timeout", String.valueOf(connTimeout));
                } else {
                    env.put("com.sun.jndi.ldap.connect.timeout", "4000");
                }

            if (readTimeout > 0) {
                env.put("com.sun.jndi.ldap.read.timeout", String.valueOf(readTimeout));
            }
            if (ldapDebugEnabled) {
                env.put("com.sun.jndi.ldap.trace.ber", System.err);
            }
            if (followReferrals) {
                env.put(Context.REFERRAL, "follow");
            }
            if (!followAliasReferrals) {
                env.put("java.naming.ldap.derefAliases", "never");
            }

            Log.debug("Created context values, attempting to create context...");
            ctx = new JiveInitialLdapContext(env, null);

            if (startTlsEnabled && !sslEnabled) {

                Log.debug("... StartTlsRequest");

                // Perform a StartTLS extended operation
                StartTlsResponse tls = (StartTlsResponse)
                    ctx.extendedOperation(new StartTlsRequest());

                /* Open a TLS connection (over the existing LDAP association) and
                   get details of the negotiated TLS session: cipher suite,
                   peer certificate, etc. */
                try {
                    SSLSession session = tls.negotiate(new org.jivesoftware.util.SimpleSSLSocketFactory());

                    ctx.setTlsResponse(tls);
                    ctx.setSslSession(session);

                    Log.debug("... peer host: {}, CipherSuite: {}", session.getPeerHost(), session.getCipherSuite());

                    ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
                    ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, createNewAbsolute(baseDN, userRDN).toString());
                    ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);

                } catch (java.io.IOException ex) {
                    Log.error("Unable to upgrade connection to TLS; failing user authentication", ex);
                    return false;
                }

                // make at least one lookup to check authorization
                lookupExistence(
                        ctx,
                        createNewAbsolute( baseDN, userRDN ),
                        new String[] {usernameField});
            }

            Log.debug("... context created successfully, returning.");
        }
        catch (NamingException ne) {
            // If an alt baseDN is defined, attempt a lookup there.
            if (alternateBaseDN != null) {
                try {
                    if (ctx != null) {
                        ctx.close();
                    }
                }
                catch (Exception e) {
                    Log.error("An exception occurred while trying to authenticate against the alternate baseDN.", e);
                }
                try {
                    // See if the user authenticates.
                    Hashtable<String, Object> env = new Hashtable<>();
                    // Use a custom initial context factory if specified. Otherwise, use the default.
                    env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
                    env.put(Context.PROVIDER_URL, getProviderURL(alternateBaseDN));
                    if (sslEnabled) {
                        env.put("java.naming.ldap.factory.socket", "org.jivesoftware.util.SimpleSSLSocketFactory");
                        env.put(Context.SECURITY_PROTOCOL, "ssl");
                    }

                    /* If startTLS is requested we MUST NOT bind() before
                     * the secure connection has been established. */
                    if (!(startTlsEnabled && !sslEnabled)) {
                        env.put(Context.SECURITY_AUTHENTICATION, "simple");
                        env.put(Context.SECURITY_PRINCIPAL, createNewAbsolute(alternateBaseDN, userRDN).toString());
                        env.put(Context.SECURITY_CREDENTIALS, password);
                    }

                    if (connTimeout > 0) {
                        env.put("com.sun.jndi.ldap.connect.timeout", String.valueOf(connTimeout));
                    } else {
                        env.put("com.sun.jndi.ldap.connect.timeout", "4000");
                    }

                    if (ldapDebugEnabled) {
                        env.put("com.sun.jndi.ldap.trace.ber", System.err);
                    }
                    if (followReferrals) {
                        env.put(Context.REFERRAL, "follow");
                    }
                    if (!followAliasReferrals) {
                        env.put("java.naming.ldap.derefAliases", "never");
                    }
                    Log.debug("Created context values, attempting to create context...");
                    ctx = new JiveInitialLdapContext(env, null);

                    if (startTlsEnabled && !sslEnabled) {
                        Log.debug("... StartTlsRequest");

                        // Perform a StartTLS extended operation
                        StartTlsResponse tls = (StartTlsResponse)
                            ctx.extendedOperation(new StartTlsRequest());

                        /* Open a TLS connection (over the existing LDAP association) and
                           get details of the negotiated TLS session: cipher suite,
                           peer certificate, etc. */
                        try {
                            SSLSession session = tls.negotiate(new org.jivesoftware.util.SimpleSSLSocketFactory());

                            ctx.setTlsResponse(tls);
                            ctx.setSslSession(session);

                            Log.debug("... peer host: {}, CipherSuite: {}", session.getPeerHost(), session.getCipherSuite());

                            ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
                            ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, createNewAbsolute(alternateBaseDN, userRDN).toString());
                            ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);

                        } catch (java.io.IOException ex) {
                            Log.error("Unable to upgrade connection to TLS; failing user authentication", ex);
                            return false;
                        }

                        // make at least one lookup to check user authorization
                        lookupExistence(
                                ctx,
                                createNewAbsolute(alternateBaseDN, userRDN),
                                new String[] {usernameField});
                    }
                }
                catch (NamingException e) {
                    Log.debug("Caught a naming exception when creating InitialContext", ne);
                    return false;
                }
            }
            else {
                Log.debug("Caught a naming exception when creating InitialContext", ne);
                return false;
            }
        }
        finally {
            try {
                if (ctx != null) {
                    ctx.close();
                }
            }
            catch (Exception e) {
                Log.error("An exception occurred while trying to close the context after an authentication attempt.");
            }
        }
        return true;
    }
Returns true if the user is able to successfully authenticate against
the LDAP server. The "simple" authentication protocol is used.

@param userRDN the user's rdn to authenticate (relative to {@code baseDN}).
@param password the user's password.
@return true if the user successfully authenticates.
xmppserver/src/main/java/org/jivesoftware/openfire/ldap/LdapManager.java