User authentication

LdapLoginModule

Configure Kpow to read authentication and role information from LDAP.

For specifics on JAAS / LDAP configuration see the Jetty LdapLoginModule docs.

Steps to enable LDAP

To enable LdapLoginModule authentication you must:

  • Set the AUTH_PROVIDER_TYPE=jetty environment variable.
  • Create a JAAS configuration file
  • Start the JAR or Docker container with the java.security.auth.login.config Java parameter set to the location of your JAAS configuration file.

Configuration

Environment variable configuration

To activate Jetty JAAS authentication set the environment variable AUTH_PROVIDER_TYPE=jetty

JAAS configuration file

Create a JAAS LDAP configuration file (the kpow realm is very important).

Your JAAS LDAP configuration will vary depending on your LDAP server structure:

kpow {
  io.kpow.jaas.spi.LdapLoginModule required
  useLdaps="false"
  debug="true"
  contextFactory="com.sun.jndi.ldap.LdapCtxFactory"
  hostname="localhost"
  port="10389"
  bindDn="uid=admin,ou=system"
  bindPassword="AES:ARAOyh4tygxSknnTNknnuFXG+PYr0oLlN9UO/0XSq4RSOw=="
  authenticationMethod="simple"
  forceBindingLogin="true"
  userBaseDn="OU=Users,DC=example,DC=com"
  userRdnAttribute="uid"
  userIdAttribute="uid"
  userPasswordAttribute="userPassword"
  roleBaseDn="OU=Groups,DC=example,DC=com"
  roleNameAttribute="roleName"
  roleMemberAttribute="uniqueMember"
  roleObjectClass="groupOfUniqueNames";
};

Encrypt the LDAP bindPassword

Optionally encrypt the bindPassword parameter of your JAAS configuration, see the Kpow Secure Configuration Guide for details.

Kpow startup

Start the JAR or Docker container with the java.security.auth.login.config Java parameter set to the location of your JAAS configuration file.

The method for setting this Java parameter differs slightly depending on if you are using the Kpow JAR or Docker container.

JAR startup

Start the JAR with the java.security.auth.login.config Java parameter set to the location of your JAAS configuration file.

ENVIRONMENT_NAME="Trade Book (Staging)" \
BOOTSTRAP="127.0.0.1:9092,127.0.0.1:9093,127.0.0.1:9094" \
# more env vars ..
AUTH_PROVIDER_TYPE="jetty" \
java -Djava.security.auth.login.config=/opt/kpow/jaas/ldap-jaas.conf -jar -Xmx4G /opt/kpow/kpow-java11-latest.jar

Docker container startup

Start Docker container with the java.security.auth.login.config Java parameter set to the location of your JAAS configuration file.

Note: The JAAS configuration file must be made available to Kpow within the docker container.

The JVM provides an environment variable called JAVA_TOOL_OPTIONS that can be used in place of system properties. We use this the thread the JAAS config to Docker.

ENVIRONMENT_NAME=Trade Book (Staging)
BOOTSTRAP=kafka-1:19092,kafka-2:19093,kafka-3:19094
# more docker environment file parameters
AUTH_PROVIDER_TYPE=jetty
JAVA_TOOL_OPTIONS=-Djava.security.auth.login.config=/opt/kpow/jaas/ldap-jaas.conf

When starting the docker container you will see logging output similar to:

Picked up JAVA_TOOL_OPTIONS: -Djava.security.auth.login.config=/path/to/jaas.conf

Configure LDAPS

In your JAAS configuration file set useLdaps="true" and ensure port is set to the LDAPS port of your LDAP server.

Providing Custom Certificates for LDAPS SSL

Kpow uses certificates provided in the default JVM truststore to make SSL connections for LDAPS.

To use custom certificates for LDAPS, provide them in a truststore and override the JVM default truststore with the following JVM parameter on startup.

-Djavax.net.ssl.trustStore=/opt/kpow/jaas/ldaps/client.jks -Djavax.net.ssl.trustStorePassword=secret-password -Djavax.net.ssl.trustStoreType=JKS -Djava.security.auth.login.config=/opt/kpow/jaas/ldaps-jaas.conf

To alter JVM startup parameters on startup when using the Kpow Docker container, set the same using the JAVA_TOOL_OPTIONS environment variable.

Encrypt the trustStorePassword

Optionally encrypt the trustStorePassword Java parameter with Kpow Secure.

As with all Kpow Secure encryption, you will also need to set a corresponding KPOW_SECURE_KEY or KPOW_SECURE_KEY_LOCATION environment variable.

JAVA_TOOL_OPTIONS=-Djavax.net.ssl.trustStore=/opt/kpow/jaas/ldaps/client.jks -Djavax.net.ssl.trustStorePassword=AES:ARClD4Hz3A2VpdCGqZArl/OglnIawMHRzW0cVjraODxIeg== -Djavax.net.ssl.trustStoreType=JKS -Djava.security.auth.login.config=/opt/kpow/jaas/ldaps-jaas.conf

Debug Kpow LDAP

To enable debug logging of LdapLoginModule authentication you must:

  • Set debug=true in your JAAS configuration file
  • Turn on Kpow debug-level application logs with a custom logback configuration file
  • Enable Jetty IGNORE level logs to debug some LDAP connection errors

Enable JAAS Debug

To debug JAAS LDAP connections, first add debug="true" to your config:

kpow {
  io.kpow.jaas.spi.LdapLoginModule required
  debug="true"
  ...
  ...

Enable Kpow Application Debug Logs

Turn on Jetty JAAS debug-level logging, see Application logs for example configuration that contains Jetty JAAS debug settings.

Enable Jetty IGNORED logs

To debug LDAP connection errors, enable Jetty IGNORE level logs by starting Kpow with the following Java system variable:

-Dorg.eclipse.jetty.util.log.IGNORED=true

Debug Log Examples

Once configured you will find debug log lines in your application logs that provide insight into how the LdapLoginModule is operating.

Successful Login Debug Logs

03:37:47.106 DEBUG [qtp1108191595-67] o.e.j.s.a.FormAuthenticator – challenge node0fdklcoqpau3d142sjx5jkowtm0->/login
03:37:52.628 DEBUG [qtp1108191595-70] io.kpow.jaas.spi.LdapLoginModule – Searching for user jdoe with filter: '(&(objectClass={0})({1}={2}))' from base dn: OU=Users,DC=example,DC=com
03:37:52.645 DEBUG [qtp1108191595-70] io.kpow.jaas.spi.LdapLoginModule – Found user?: true
03:37:52.647 INFO  [qtp1108191595-70] io.kpow.jaas.spi.LdapLoginModule – Attempting authentication: cn=Jane Doe,ou=Users,dc=example,dc=com
03:37:52.658 DEBUG [qtp1108191595-70] io.kpow.jaas.spi.LdapLoginModule – Found user roles?: true
03:37:52.666 DEBUG [qtp1108191595-70] o.e.j.s.a.LoginAuthenticator – renew node0fdklcoqpau3d142sjx5jkowtm0->node019y3iaulf0v0o1ouj43dadrlbf1
03:37:52.669 DEBUG [qtp1108191595-70] o.e.j.s.a.FormAuthenticator – jsecuritycheck jdoe DefaultUserIdentity('jdoe')
03:37:52.672 DEBUG [qtp1108191595-70] o.e.j.s.a.FormAuthenticator – authenticated Form{User,FORM,DefaultUserIdentity('jdoe')}->http://localhost:3000/
03:37:52.683 DEBUG [qtp1108191595-69] o.e.j.s.a.FormAuthenticator – Restoring original method GET for http://localhost:3000/ with method GET
03:37:52.684 DEBUG [qtp1108191595-69] o.e.j.s.a.FormAuthenticator – auth retry SessionAuthentication@43aea01d{-,DefaultUserIdentity('jdoe')}->http://localhost:3000/
03:37:52.687 DEBUG [qtp1108191595-69] o.e.j.s.a.FormAuthenticator – auth SessionAuthentication@43aea01d{-,DefaultUserIdentity('jdoe')}
03:37:52.773 DEBUG [qtp1108191595-68] o.e.j.s.a.FormAuthenticator – auth SessionAuthentication@43aea01d{-,DefaultUserIdentity('jdoe')}
03:37:53.577 DEBUG [qtp1108191595-64] o.e.j.s.a.FormAuthenticator – auth SessionAuthentication@43aea01d{-,DefaultUserIdentity('jdoe')}
03:37:53.647 INFO  [pool-5-thread-1] operatr.server.query-handlers – New WS connection for client-id db99106b-937b-4775-8f40-2956fd7f5cf8
03:37:54.029 DEBUG [qtp1108191595-67] o.e.j.s.a.FormAuthenticator – auth SessionAuthentication@43aea01d{-,DefaultUserIdentity('jdoe')}

Invalid password debug logs

03:38:11.399 DEBUG [qtp1108191595-67] o.e.j.s.a.FormAuthenticator – challenge node017r30mvaf9l6ngu28a6rgqndd2->/login
03:38:16.377 DEBUG [qtp1108191595-67] io.kpow.jaas.spi.LdapLoginModule – Searching for user jdoe with filter: '(&(objectClass={0})({1}={2}))' from base dn: OU=Users,DC=example,DC=com
03:38:16.382 DEBUG [qtp1108191595-67] io.kpow.jaas.spi.LdapLoginModule – Found user?: true
03:38:16.382 INFO  [qtp1108191595-67] io.kpow.jaas.spi.LdapLoginModule – Attempting authentication: cn=Jane Doe,ou=Users,dc=example,dc=com
03:38:16.429 DEBUG [qtp1108191595-67] o.e.jetty.jaas.JAASLoginService – Login failed
javax.security.auth.login.FailedLoginException: [LDAP: error code 49 - INVALID_CREDENTIALS: Bind failed: ERR_229 Cannot authenticate user cn=Jane Doe,ou=Users,dc=example,dc=com]
	at io.kpow.jaas.spi.LdapLoginModule.bindingLogin(LdapLoginModule.java:543)
	at io.kpow.jaas.spi.LdapLoginModule.login(LdapLoginModule.java:433)
	at java.base/javax.security.auth.login.LoginContext.invoke(LoginContext.java:747)
<snip>
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:934)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1078)
	at java.base/java.lang.Thread.run(Thread.java:829)
03:38:16.429 DEBUG [qtp1108191595-67] o.e.j.s.a.FormAuthenticator – jsecuritycheck jdoe null
03:38:16.429 DEBUG [qtp1108191595-67] o.e.j.s.a.FormAuthenticator – Form authentication FAILED for jdoe

User not found debug logs

03:41:35.346 DEBUG [qtp437783899-69] o.e.j.s.a.FormAuthenticator – challenge node01oops3xzje0ha1s691bng8tnck0->/login
03:41:41.323 DEBUG [qtp437783899-68] io.kpow.jaas.spi.LdapLoginModule – Searching for user jdoe with filter: '(&(objectClass={0})({1}={2}))' from base dn: OU=User,DC=example,DC=com
03:41:41.337 DEBUG [qtp437783899-68] io.kpow.jaas.spi.LdapLoginModule – Found user?: false
03:41:41.342 DEBUG [qtp437783899-68] o.e.jetty.jaas.JAASLoginService – Login failed
javax.security.auth.login.FailedLoginException: User not found.
	at io.kpow.jaas.spi.LdapLoginModule.findUser(LdapLoginModule.java:587)
<snip>
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1078)
	at java.base/java.lang.Thread.run(Thread.java:829)
03:41:41.342 DEBUG [qtp437783899-68] o.e.j.s.a.FormAuthenticator – jsecuritycheck jdoe null
03:41:41.344 DEBUG [qtp437783899-68] o.e.j.s.a.FormAuthenticator – Form authentication FAILED for jdoe
03:41:41.345 DEBUG [qtp437783899-68] o.e.j.s.a.FormAuthenticator – auth failed jdoe->/login-retry

If you encounter unexpected 'User Not Found' errors, it is likely that you have the wrong user parameters in your JAAS configuration, check these:

userBaseDn="OU=Users,DC=example,DC=com"
userRdnAttribute="uid"
userIdAttribute="uid"
userPasswordAttribute="userPassword"

Those parameters depend on your LDAP structure and vary from organisation to organisation.

User experience

When configured your users will be prompted to authenticate on each new browser session.