How to configure an Elytron LDAP Realm on WildFly

In this tutorial we will learn how to configure Authentication with an Elytron LDAP-Based Identity Store on the top of WildFly application Server

Hard requirements

  • WildFly 11 or newer
  • 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 --env LDAP_ORGANISATION="wildfly" --env LDAP_DOMAIN="wildfly.org" --env LDAP_ADMIN_PASSWORD="admin" --detach osixia/openldap

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

Check your IP Address from your container:

$ docker inspect --format '{{ .NetworkSettings.IPAddress }}' $(docker ps -q)
172.17.0.2

Now verify the connection with any LDAP Browser:

Authentication with an Elytron LDAP-Based Identity Store.

Ok, the connection worked so now 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: organizationalUnit
objectClass: top
ou: Users

dn: uid=frank,ou=Users,dc=wildfly,dc=org
objectClass: top
objectClass: person
objectClass: inetOrgPerson
cn: Franky
sn: frank
uid: frank
userPassword: secret123

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

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 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://172.17.0.2:389",principal="cn=admin,dc=wildfly,dc=org",credential-reference={clear-text="secret"})

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=exampleLR: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=exampleLdapSD:add(realms=[{realm=exampleLR,role-decoder=from-roles-attribute}],default-realm=exampleLR,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=exampleLdapSD,mechanism-configurations=[{mechanism-name=BASIC,mechanism-realm-configurations=[{realm-name=myApplicationDomain}]}])

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=myApplicationDomain:add(http-authentication-factory=example-ldap-http-auth)

We are done! The above CLI command should reflect in the following server configuration:

<?xml version="1.0" encoding="UTF-8"?>
<subsystem xmlns="urn:wildfly:elytron:1.2" final-providers="combined-providers" disallowed-providers="OracleUcrypto">
  
   <security-domains>
      . . .
      <security-domain name="exampleLdapSD" default-realm="exampleLR" permission-mapper="default-permission-mapper">
         <realm name="exampleLR" role-decoder="from-roles-attribute" />
      </security-domain>
   </security-domains>
   <security-realms>
       . . . . .
      <ldap-realm name="exampleLR" 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="(&(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>
   <mappers>
        . . . .
      <simple-role-decoder name="from-roles-attribute" attribute="Roles" />
   </mappers>
   <http>
      <http-authentication-factory name="management-http-authentication" http-server-mechanism-factory="global" security-domain="ManagementDomain">
       . . . .
      <http-authentication-factory name="example-ldap-http-auth" http-server-mechanism-factory="global" security-domain="exampleLdapSD">
         <mechanism-configuration>
            <mechanism mechanism-name="BASIC">
               <mechanism-realm realm-name="exampleApplicationDomain" />
            </mechanism>
         </mechanism-configuration>
      </http-authentication-factory>
      <provider-http-server-mechanism-factory name="global" />
   </http>
   <sasl>
      . . . .
   </sasl>
   <dir-contexts>
      <dir-context name="exampleDC" url="ldap://172.17.0.2: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 bit:

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

And this is a sample web.xml:

<web-app>
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>secure</web-resource-name>
      <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
      <role-name>Admin</role-name>
    </auth-constraint>
  </security-constraint>
  <security-role>
    <description>Ldap Secured</description>
    <role-name>Admin</role-name>
  </security-role>
  <login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>myApplicationDomain</realm-name>
  </login-config>
</web-app>
Found the article helpful? if so please follow us on Socials