Using JDBC Security Domain in Wildfly

As I was going through this task, I ran into the whole “there’s so much documentation, but none of it is working or makes sense” problem that’s so common with the JBoss Application Server. So, this post is designed to help out!

Overview

First of all, Wildfly calls this a Database Login Module. There’s a few pieces we need to do to our app to use it:

  1. Define the Datasource the module will use.
  2. Define the security-domain.
  3. Modify our app to use it.

Define the Datasource

Depending on what database driver, you use, this may look a little different.

For our demo, we’ll use a MySQL database. The best writeup I’ve found for configuring MySQL is part of a post for migrating from Glassfish to Wildfly (post found here).

This goes in your standalone/configuration/standalone.xml file under the datasources element.

<datasource jndi-name="java:jboss/datasources/SampleDS" pool-name="SampleDS" enabled="true">
    <connection-url>jdbc:mysql://localhost:3306/sample</connection-url>
    <driver>com.mysql</driver>
    <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
    <pool>
        <min-pool-size>10</min-pool-size>
        <max-pool-size>100</max-pool-size>
        <prefill>true</prefill>
    </pool>
    <security>
        <user-name>user</user-name>
        <password>passw0rd</password>
    </security>
    <statement>
        <prepared-statement-cache-size>32</prepared-statement-cache-size>
        <share-prepared-statements>true</share-prepared-statements>
    </statement>
</datasource>

Define the Security Domain

Also in your standalone.xml, in the security-domains configuration, place this:

<security-domain name="test-policy" cache-type="default">
    <authentication>
        <login-module code="Database" flag="required">
            <module-option name="dsJndiName" value="java:jboss/datasources/SampleDS"/>
            <module-option name="principalsQuery" value="SELECT password FROM users WHERE username=?"/>
            <module-option name="rolesQuery" value="SELECT role, 'Roles' FROM user_roles WHERE username=?"/>
            <module-option name="hashAlgorithm" value="SHA-512"/>
            <module-option name="hashEncoding" value="hex"/>
            <module-option name="unauthenticatedIdentity" value="guest"/>
        </login-module>
    </authentication>
</security-domain>

So, some things to note here:

  • The dsJndiName must match the JNDI name setup for your datasource.
  • The principalsQuery must return the password for the username, uuid, or whatever you are using to identify a user
  • The rolesQuery returns a query that will identify all of the roles for a user.
  • The hashAlgorithm supports anything supported by java.security.MessageDigest, based on the installation of the machine. Of course, you want to use an algorithm that is strong enough for passwords, so SHA-256 or SHA-512.
  • The hashEncoding supports hex or base64. If you use hex, the password must be lower-cased. Trust me… personal experience found this out.
  • The unauthenticatedIdentity is a defines the principal (username) of a user if log in fails (source).

Modify the app

The final piece is to update our app to tell it which security-domain to use. In your WEB-INF folder, create (if one doesn’t already exist) a jboss-web.xml. In it, place the following:

<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
  <security-domain>test-policy</security-domain>
</jboss-web>

The only thing to note here is that the value MUST MATCH the name of the security-domain you put in your standalone.xml.

Beyond that, define your security constraints, login-config, and security-roles in your web.xml and you’re good to go!