With version 11 Wildfly introduced a complete new security concept named ‘Elytron’. This security concept is a little bit confusing on the first look if you have worked with previous versions of Wildfly. To be honest I personally recognized the Elytron framework with version Wildfly 24. Even it it is well documented it took me a while until I get things working. Initially I came across the configuration concept during migrating the Imixs-Workflow project form Jakarta EE8 to Jakarta EE9. As we are using docker images to run our applications we are configuring the Wildfly server by the standalone.xml
file and not via the CLI provided by Wildfly. In the following I will show what is important to get a Jakarta EE9 application work with Elytron.
The Elytron Subsystem
Wildfly is separated in its core into subsystems. Each subsystem has its own configuration section in the standalone.xml
file. For the Elytron subsystem this is urn:wildfly:elytron:14.0
.
If you look into the subsystem configuration you can see that a security domain is split now into the domain and the realm section. A simple FileBased security realm with the realm name ‘imixsrealm’ will look like this:
<subsystem xmlns="urn:wildfly:elytron:14.0" final-providers="combined-providers" disallowed-providers="OracleUcrypto">
.....
<security-domains>
.....
<!-- imixsrealm filerealm configuration -->
<security-domain name="imixsrealm" default-realm="imixsrealm" permission-mapper="default-permission-mapper">
<realm name="imixsrealm"/>
</security-domain>
</security-domains>
<security-realms>
....
<!-- imixsrealm filerealm property files -->
<properties-realm name="imixsrealm" groups-attribute="Roles">
<users-properties path="sampleapp-users.properties" relative-to="jboss.server.config.dir" digest-realm-name="Application Security" plain-text="true"/>
<groups-properties path="sampleapp-roles.properties" relative-to="jboss.server.config.dir"/>
</properties-realm>
</security-realms>
.....
</subsystem>
I added a security-domain with the name ‘imixsrealm’ and also a properties-realm section with the same name where I define the users and roles property files. The attribute plain-text="true"
indicates that you store the password in plaintext, which makes testing much easier. Place the sample-app-roles and users property files into the standalone/config/ directory. Do not modify the other sections of the Elytron subsystem!
The content of the sampleapp-users.properties looks like this (with plain text passwords)
admin=adminadmin
manfred=password
anna=password
In the file sampleapp-roles.properties you can assign users to application specific roles:
admin=MANAGERACCESS
manfred=MANAGERACCESS
anna=AUTHORACCESS
So far everything seems to look similar to the old security-domain configuration. But at this moment you new security domain wont work. There are additional steps needed.
The EJB and Web Subsystems
To get the security domain working with your application you need to add the security domain also to the undertow web subsystem. In this subsystem you will find a section ‘application-security-domains’. And in this section you need to add your new security domain as well:
<subsystem xmlns="urn:jboss:domain:undertow:12.0" default-server="default-server" default-virtual-host="default-host" default-servlet-container="default" default-security-domain="other" statistics-enabled="${wildfly.undertow.statistics-enabled:${wildfly.statistics-enabled:false}}">
....
<application-security-domains>
<application-security-domain name="imixsrealm" security-domain="imixsrealm"/>
<application-security-domain name="other" security-domain="ApplicationDomain"/>
</application-security-domains>
</subsystem>
There is also a subsystem for EJBs “ejb3:9.0” and it becomes important that you add your security domain also there if you have EJBs with the annotations @RolesAllowed
or @RunAs
<subsystem xmlns="urn:jboss:domain:ejb3:9.0">
...
<default-security-domain value="other"/>
<application-security-domains>
<application-security-domain name="imixsrealm" security-domain="imixsrealm"/>
<application-security-domain name="other" security-domain="ApplicationDomain"/>
</application-security-domains>
...
</subsystem>
Now you have completed your configuration in the standalone.xml file
The jboss-web.xml and jboss-ejb3.xml
There are still 2 application specific files which need to be part of your web application.
In the jboss-web.xml you define you custom security domain:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<context-root>/</context-root>
<security-domain>imixsrealm</security-domain>
</jboss-web>
and in the jboss-ejb3.xml file:
<?xml version="1.1" encoding="UTF-8"?>
<jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:s="urn:security:1.1"
xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd"
version="3.1" impl-version="2.0">
<assembly-descriptor>
<s:security>
<ejb-name>*</ejb-name>
<s:security-domain>imixsrealm</s:security-domain>
<!-- This configuration is necessary to enable @runAs for the AdminPService -->
<s:missing-method-permissions-deny-access>false</s:missing-method-permissions-deny-access>
</s:security>
</assembly-descriptor>
</jboss:ejb-jar>
So finally your Jakarta EE9 application should now deploy and run within Wilfly 24 using the new Elytron Security Framework.
Database Realm / jdbc-realm
It is also easy to use jdbc-realm configuration. You can find general information about Database realms here. The following shows an example how to configure a jdbc-realm with two tables storing an encrypted password and user roles.
<jdbc-realm name="imixsrealm">
<principal-query sql="select PASSWORD from USERID where ID=?" data-source="office">
<simple-digest-mapper algorithm="simple-digest-sha-256" password-index="1" hash-encoding="hex"/>
</principal-query>
<principal-query sql="select GROUP_ID from USERID_USERGROUP where ID=?" data-source="office">
<attribute-mapping>
<attribute to="Roles" index="1"/>
</attribute-mapping>
</principal-query>
</jdbc-realm>
Note: I am using two queries here as my role definitions are stored in a separate table (USERID_USERGROUP). The password is stored in hex format encrypted with a SHA-256 algorithm.