Creating an Elytron Security Realm for WildFly

Elytron is the new security subsytem of WildFly which will completely replace the combination of PicketBox and JAAS as the application server's client and server security system. In this tutorial we will have an overview of it and learn how to create a sample Elytron JDBC Realm to secure applications against the database

On of the main advantages of Elytron is that it will provide an unified security solution across the application server which is now fragmented into several parts of your configuration. Elytron will provide as well support of:

  • Secure server-side authentication mechanisms based on HTTP, SASL,and TLS, as well as supporting other authentication protocols in the future
  • Support for password credential types using the standard Java cryptography extension structure (such as DES, MD5, SHA, bcrypt, and so on)

The following picture shows Elytron building blocks:

elytron wildfly tutorial

An elytron Security Realm encapsulates and integrates the application server with an identity store or repository (such as an LDAP server or a database). Hence, they are mainly responsible for obtaining or verifying credentials, obtaining the attributes associated with a given identity and last, but also important, creating an internal representation based on this information that will be used by a security domain to authenticate and perform role and permission mappings for a given principal.

By default, elytron provides some built-in implementations of security realms that are capable of managing your identities. Here are some examples:

  • JDBCSecurity realm : The class org.wildfly.security.auth.realm.jdbc.JdbcSecurityRealm is a security realm implementation backed by a database
  • LDAP security realm : The class org.wildfly.security.auth.realm.ldap.LdapSecurityRealm is a security realm implementation backed by LDAP
  • Property security realm: The class org.wildfly.security.auth.realm.LegacyPropertiesSecurityRealm is an implementation that makes use of the legacy property files
  • Java KeyStores security realm: The class org.wildfly.security.auth.realm.KeyStoreBackedSecurityRealm is a Keystore-backed security realm
  • Token security realm: The class org.wildfly.security.auth.realm.token.TokenSecurityRealm is a security realm capable of building identities based on different security token formats based on a TokenValidator

The other key block of elytron is the security domain which is the entry point to all security operations available in your server infrastructure. It contains a high-level view of security policies and resources associated with your IT domain.

The term domain should not be confused with an Internet Protocol (IP) resource. An elytron domain can be composed of a single application or multiple applications which share the same security policies.

In terms of responsibilities, a security domain is in charge of:

  • Mapping a principal to its corresponding identity on a specific security realm
  • Permission mapping
  • Role mapping
  • Obtain the current and authorized identity and all information associated with it, such as roles, permissions, and attributes

Creating a JDBC Security realm

We will present here an example of JDBC Security Realm

At the time of writing, the elytron subsystem is still not included in WildFly 10 therefore we will use a snapshot build of wildfly-11.0.0.Alpha1-SNAPSHOT which includes the standalone-elytron.xml configuration file.

Start the server as follows:

$ ./standalone.sh -c standalone-elytron.xml

The prerequisite is that you have already configured a MySQLPool Datasource which in turn references a MySQL database where user names and password are stored in the USERS table

Start by creating a new JDBC realm that refers our MySQLPool. For the sake of simplicity, we will be using a clear text password strategy.

/subsystem=elytron/jdbc-realm=jdbcRealm:add(principal-query=[{sql="SELECT passwd from USERS where login = ? ",data-source=MySQLPool,clear-password-mapper={password-index="1"}}])

/subsystem=elytron/security-domain=jdbcdomain:add(default-realm=jdbcRealm,realms=[{realm="jdbcRealm"}])

Next, since this security domain will use HTTP Basic authentication, we will define a new HTTP Server Authentication policy based on the jdbcdomain security domain and named http-db-auth:

/subsystem=elytron/http-authentication-factory=http-db-auth:add(security-domain=jdbcdomain,mechanism-configurations=[{mechanism-name=BASIC,mechanism-realm-configurations=[realm-name="Secured by Elytron"]}],http-server-mechanism-factory=global)

In order to propagate the HTTP Authentication policy with Undertow, which governs your web applications, a component named HTTP Authenticating factory is needed. This will eventually trigger the HttpServerAuthenticationMechanism from within the Undertow web server. Here is the command needed to create an HTTP Authenticating factory:

/subsystem=undertow/application-security-domain=web-security-domain:add(http-authentication-factory=http-db-auth)

Reload your server configuration for the changes to take effect. In terms of configuration, the following XML section will be included in your elytron subsystem:

<subsystem xmlns="urn:wildfly:elytron:1.0">
    <security-domains>
        <security-domain name="ApplicationDomain" default-realm="ApplicationRealm" permission-mapper="login-permission-mapper">
            <realm name="ApplicationRealm" role-decoder="groups-to-roles"/>
        </security-domain>
        <security-domain name="ManagementDomain" default-realm="ManagementRealm" permission-mapper="login-permission-mapper">
            <realm name="ManagementRealm" role-decoder="groups-to-roles"/>
        </security-domain>
        <security-domain name="jdbcdomain" default-realm="jdbcRealm">
            <realm name="jdbcRealm"/>
        </security-domain>
    </security-domains>
    <security-realms>
        <jdbc-realm name="jdbcRealm">
            <principal-query sql="SELECT passwd from USERS where login = ? " data-source="MySQLPool">
                <clear-password-mapper password-index="1"/>
            </principal-query>
        </jdbc-realm>
        <properties-realm name="ApplicationRealm">
            <users-properties path="application-users.properties" relative-to="jboss.server.config.dir"/>
            <groups-properties path="application-roles.properties" relative-to="jboss.server.config.dir"/>
        </properties-realm>
        <properties-realm name="ManagementRealm">
            <users-properties path="mgmt-users.properties" relative-to="jboss.server.config.dir"/>
            <groups-properties path="mgmt-groups.properties" relative-to="jboss.server.config.dir"/>
        </properties-realm>
    </security-realms>
    <mappers>
        <constant-permission-mapper name="login-permission-mapper">
            <permission class-name="org.wildfly.security.auth.permission.LoginPermission"/>
        </constant-permission-mapper>
        <simple-role-decoder name="groups-to-roles" attribute="groups"/>
    </mappers>
    <http>
        <http-authentication-factory name="management-http-authentication" http-server-mechanism-factory="global" security-domain="ManagementDomain">
            <mechanism-configuration>
                <mechanism mechanism-name="BASIC">
                    <mechanism-realm realm-name="Management Realm"/>
                </mechanism>
            </mechanism-configuration>
        </http-authentication-factory>
        <http-authentication-factory name="application-http-authentication" http-server-mechanism-factory="global" security-domain="ApplicationDomain">
            <mechanism-configuration>
                <mechanism mechanism-name="BASIC">
                    <mechanism-realm realm-name="Application Realm"/>
                </mechanism>
                <mechanism mechanism-name="FORM"/>
            </mechanism-configuration>
        </http-authentication-factory>
        <http-authentication-factory name="http-db-auth" http-server-mechanism-factory="global" security-domain="jdbcdomain">
            <mechanism-configuration>
                <mechanism mechanism-name="BASIC">
                    <mechanism-realm realm-name="Secured by Elytron"/>
                </mechanism>
            </mechanism-configuration>
        </http-authentication-factory>
        <provider-http-server-mechanism-factory name="global"/>
    </http>
    <sasl>
        <sasl-authentication-factory name="management-sasl-authentication" sasl-server-factory="global" security-domain="ManagementDomain"/>
        <sasl-authentication-factory name="application-sasl-authentication" sasl-server-factory="global" security-domain="ApplicationDomain"/>
        <provider-sasl-server-factory name="global"/>
    </sasl>
</subsystem>

On the other hand, the Undertow configuration will include the following application-security-domains definition:

<subsystem xmlns="urn:jboss:domain:undertow:4.0">
    <buffer-cache name="default"/>
    <server name="default-server">
        <http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/>
        <https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/>
        <host name="default-host" alias="localhost">
            <location name="/" handler="welcome-content"/>
            <filter-ref name="server-header"/>
            <filter-ref name="x-powered-by-header"/>
        </host>
    </server>
    <servlet-container name="default">
        <jsp-config/>
        <websockets/>
    </servlet-container>
    <handlers>
        <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
    </handlers>
    <filters>
        <response-header name="server-header" header-name="Server" header-value="WildFly/10"/>
        <response-header name="x-powered-by-header" header-name="X-Powered-By" header-value="Undertow/1"/>
    </filters>
    <application-security-domains>
        <application-security-domain name="other" http-authentication-factory="application-http-authentication"/>
        <application-security-domain name="web-security-domain" http-authentication-factory="http-db-auth"/>
    </application-security-domains>
</subsystem>

Now if you try to deploy an application bound to the "web-security-domain" security domain:

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

As a result, you will receive a BASIC HTTP Authentication challenge:

elytron wildfly tutorial

That's all for now. In the next tutorial we will show some more examples of Elytron Security realms. Stay tuned!

Follow us on Twitter