How to configure an Elytron LDAP Realm on WildFly

This tutorial guides you through setting up an LDAP realm using the WildFly Elytron security subsystem for user authentication. We will learn how to bootstrap a sample LDAP Server with docker and create an LDAP Realm on WildFly

Hard requirements

  • WildFly application server
  • A LDAP Server or a Docker deamon to start an LDAP Server in a Container

For the sake of simplicity, we will start a Containerised version of OpenLdap, which is available in the DockerHub, using as BASE DN wildfly.org:

$ docker run  -p 389:389 --env LDAP_ORGANISATION="wildfly" --env LDAP_DOMAIN="wildfly.org" --env LDAP_ADMIN_PASSWORD="admin"  osixia/openldap:1.5.0

As an alternative, you can set the BASE DN in your slapf.conf and set the default admin password.

The LDAP Server will start and bind to all available IP Addresses:

$ docker ps
7403a4730be6   osixia/openldap:1.5.0   "/container/tool/run"   8 seconds ago   Up 7 seconds   0.0.0.0:389->389/tcp, :::389->389/tcp, 636/tcp   hopeful_archimedes

You can verify the connectivity through any LDAP Browser. For example, to connect with the default Docker IP Address (172.17.0.2):

Authentication with an Elytron LDAP-Based Identity Store.

Since the LDAP Server binds on all IP Addresses, you should be able to connect through the localhost loopback address as well.

Then, we will upload a sample ldif file which will contain one user named “frank” which is granted the Role “Admin”:

dn: ou=Users,dc=wildfly,dc=org
objectclass: top
objectclass: organizationalUnit
ou: Users

dn: ou=Roles,dc=wildfly,dc=org
objectclass: top
objectclass: organizationalUnit
ou: Roles

dn: uid=frank,ou=Users,dc=wildfly,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: frank
cn: Frank
sn: White
mail: [email protected]
postalCode: 88441
userPassword: secret123

dn: cn=Admin,ou=Roles,dc=wildfly,dc=org
objectclass: top
objectclass: groupOfNames
cn: Admin
member: uid=frank,ou=Users,dc=wildfly,dc=org

You can upload the LDIF file with the ldapadd command. For example:

ldapadd -x -D "cn=admin,dc=wildfly,dc=org" -w admin -H ldap://localhost:389 -f example.ldif

Then, you should be able to see the updated Directory from your LDAP Browser:

Authentication with an Elytron LDAP-Based Identity Store.

Configuring the Elytron LDAP Realm

Firstly, start WildFly and connect to the Command Line Interface.

The first thing we will need to do is configuring a Directory Context with the URL of the LDAP Server and the information related to the Principal:

/subsystem=elytron/dir-context=exampleDC:add(url="ldap://localhost:389",principal="cn=admin,dc=wildfly,dc=org",credential-reference={clear-text="admin"})

Next, it’s time to create an LDAP Realm which references the Directory Context, specifying the Search Base DN, how and Users are mapped:

/subsystem=elytron/ldap-realm=demoLdapRealm:add(dir-context=exampleDC,identity-mapping={search-base-dn="ou=Users,dc=wildfly,dc=org",rdn-identifier="uid",user-password-mapper={from="userPassword"},attribute-mapping=[{filter-base-dn="ou=Roles,dc=wildfly,dc=org",filter="(&(objectClass=groupOfNames)(member={1}))",from="cn",to="Roles"}]})

Next, you will need creating a Role Decoder which, in its simplest form, takes a single attribute and maps it directly to roles.

/subsystem=elytron/simple-role-decoder=from-roles-attribute:add(attribute=Roles)

Ok, we have the LDAP Realm, the Role Decoder so we will create a Security Domain which uses this information:

/subsystem=elytron/security-domain=ldapSD:add(realms=[{realm=demoLdapRealm,role-decoder=from-roles-attribute}],default-realm=demoLdapRealm,permission-mapper=default-permission-mapper)

As the Security Domain will be used to authenticate users through HTTP, we will need to add an Http Authentication Factory which is configured to use the above defined Security Domain and LDAP Realm:

/subsystem=elytron/http-authentication-factory=example-ldap-http-auth:add(http-server-mechanism-factory=global,security-domain=ldapSD,mechanism-configurations=[{mechanism-name=BASIC,mechanism-realm-configurations=[{realm-name=RealmUsersRoles}]}])

We are finished with Elytron. The last piece of the puzzle will be the Http Authentication Factory into Undertow, so that incoming request will be handled by the Security Domain:

/subsystem=undertow/application-security-domain=httpLdapSD:add(http-authentication-factory=example-ldap-http-auth)

LDAP Configuration updates

The CLI commands should reflect in the following elytron configuration:

<subsystem xmlns="urn:wildfly:elytron:community:18.0" final-providers="combined-providers" disallowed-providers="OracleUcrypto">
  <!-- ....... -->
  <security-domains>
 
	<security-domain name="ldapSD" default-realm="demoLdapRealm" permission-mapper="default-permission-mapper">
	    <realm name="demoLdapRealm" role-decoder="from-roles-attribute"/>
	</security-domain>
	
  </security-domains>
<!-- ....... -->
  <security-realms>

	<ldap-realm name="demoLdapRealm" dir-context="exampleDC">
	    <identity-mapping rdn-identifier="uid" search-base-dn="ou=Users,dc=wildfly,dc=org">
		<attribute-mapping>
		    <attribute from="cn" to="Roles" filter="(&amp;(objectClass=groupOfNames)(member={1}))" filter-base-dn="ou=Roles,dc=wildfly,dc=org"/>
		</attribute-mapping>
		<user-password-mapper from="userPassword"/>
	    </identity-mapping>
	</ldap-realm>

  </security-realms>

<!-- ....... -->
  <http>

	<http-authentication-factory name="example-ldap-http-auth" security-domain="ldapSD" http-server-mechanism-factory="global">
	    <mechanism-configuration>
		<mechanism mechanism-name="BASIC">
		    <mechanism-realm realm-name="RealmUsersRoles"/>
		</mechanism>
	    </mechanism-configuration>
	</http-authentication-factory>

  </http>
<!-- ....... -->
 <dir-contexts>
                <dir-context name="exampleDC" url="ldap://localhost:389" principal="cn=admin,dc=wildfly,dc=org">
                    <credential-reference clear-text="admin"/>
                </dir-context>
 </dir-contexts>

</subsystem>

Application Configuration

In order to test your application, include the Security bindings in your jboss-web.xml and web.xml.

Here is the jboss-web.xml :

<jboss-web>
        <security-domain>httpLdapSD</security-domain>
</jboss-web>

And this is a sample web.xml:

<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
 
   <login-config>
      <auth-method>BASIC</auth-method>
      <realm-name>RealmUsersRoles</realm-name>
   </login-config>
</web-app>

You should be able to login to your application using the above configuration with the LDAP user id available:

curl http://localhost:8080/demo-security/secure -u "frank:secret123"

Conclusion

This tutorial provided a step-by-step guide to configuring an LDAP realm using WildFly’s Elytron subsystem. By following these steps and customizing the connection details and attribute mapping to match your specific LDAP server configuration, you can establish a secure authentication mechanism for your WildFly applications.

Was this article helpful? We need your support to keep MasterTheBoss alive!