Configuring HTTP Basic Authentication with WildFly

In this tutorial we will learn how to configure HTTP basic authentication with WildFly.

Basic authentication is a simple authentication policy built into the HTTP protocol. The client sends an HTTP request with the Authorization header that contains the word Basic word followed by a space and a base64-encoded string username:password.

wildfly basic authentication wildfly basic authentication

As an example, in order to authorize as demo / p@55w0rd the client would send

    Authorization: Basic ZGVtbzpwQDU1dzByZA==

Note: Because base64 is easily decoded, Basic authentication should only be used together with other security mechanisms such as HTTPS/SSL.

Example: enabling HTTP Basic Authentication in WildFly

In order to enable HTTP Basic Authentication in WildFly we will define a Security Realm with Elytron. The most basic example of a security realm is the FileSystem Realm, which stores the identity information on a filesystem, by paging each identity in an XML file containing credentials and Roles. Start the application server and connect to it from a CLI (jboss-cli.sh). Then execute the following commands:

# add a Simple Role Decoder which maps the application Roles from the attribute Roles in the File system.

if (outcome != success) of /subsystem=elytron/simple-role-decoder=from-roles-attribute:read-resource
     /subsystem=elytron/simple-role-decoder=from-roles-attribute:add(attribute=Roles)
end-if

batch

# Let’s define a new filesystem-realm named fsRealm and its respective path on the file system:
/subsystem=elytron/filesystem-realm=demoFsRealm:add(path=demofs-realm-users,relative-to=jboss.server.config.dir)

# Next, we add some identities to the Realm:
/subsystem=elytron/filesystem-realm=demoFsRealm:add-identity(identity=frank)
/subsystem=elytron/filesystem-realm=demoFsRealm:set-password(identity=frank,clear={password="password123"})
/subsystem=elytron/filesystem-realm=demoFsRealm:add-identity-attribute(identity=frank,name=Roles, value=["Admin","Guest"])

# Create a new Security Domain which maps our Realm:
/subsystem=elytron/security-domain=fsSD:add(realms=[{realm=demoFsRealm,role-decoder=from-roles-attribute}],default-realm=demoFsRealm,permission-mapper=default-permission-mapper)

# We need an Http Authentication Factory which references our Security Domain:
/subsystem=elytron/http-authentication-factory=example-fs-http-auth:add(http-server-mechanism-factory=global,security-domain=fsSD,mechanism-configurations=[{mechanism-name=BASIC,mechanism-realm-configurations=[{realm-name=RealmUsersRoles}]}])

# Finally, a Security Domain in the undertow’s subsystem will be associated with our Http Authentication Factory:
/subsystem=undertow/application-security-domain=FSSecurityDomain:add(http-authentication-factory=example-fs-http-auth)

run-batch

reload

Then set the security domain in “jboss-web.xml“:

<jboss-web xmlns="http://www.jboss.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.jboss.org/schema/jbossas
    http://www.jboss.org/schema/jbossas/jboss-web_7_2.xsd">
   <security-domain>FSSecurityDomain</security-domain>
</jboss-web>

And configure th auth-method in your 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>

Our application defines a single endpoint, which has an HttpConstraint allowing access only to “Admin” users:

@WebServlet("/secure")
@ServletSecurity(@HttpConstraint(rolesAllowed = { "Admin" }))
public class SecuredServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();
        Principal principal = null;
        String authType = null;
        String remoteUser = null;

        principal = req.getUserPrincipal();

        remoteUser = req.getRemoteUser();

        authType = req.getAuthType();

        writer.println("servlet-security");
        writer.println("Successfully called Secured Servlet");
        writer.println("Principal : " + principal.getName() + ");
        writer.println("Remote User : " + remoteUser + ");
        writer.println("Authentication Type : " + authType + ");
        writer.println("");
        writer.close();
    }

}

Let’s send a request to the secured endpoint:

curl -u frank:password123 http://localhost:8080/http-basic/secure
Successfully called Secured Servlet 
Principal  : frank
Remote User : frank
Authentication Type : BASIC

You can find the souce code for this example here: https://github.com/fmarchioni/mastertheboss/tree/master/security/http-basic

Setting HTTP Basic authentication for Web Services

In case you are using EJB-based Web Services the configuration is slightly different; because the security domain is not specified into the web descriptors, we have to provide it by means of annotations:

@Stateless
@WebService(targetNamespace = "https://www.mastertheboss.com/",
serviceName = "SecureService")
@WebContext(authMethod = "BASIC",
secureWSDLAccess = false)
@SecurityDomain(value = "other")
public class SecureEJB { }

As you can see, the @WebContext annotation basically reflects the same configuration options of POJO-based Web Services, with BASIC authentication and unrestricted WSDL access.

Basic authentication using Database

If you want to learn how to configure authentication using a Database instead of a property file, check this tutorial: Configure an Elytron JDBC Realm on WildFly

Found the article helpful? if so please follow us on Socials