Sunday, March 15. 2020
JASPI authentication in elytron
Today's entry is dedicated to Java Authentication Service Provider Interface for Containers (JASPIC or just JASPI) in the wildfly server. Since version 15 the new elytron security provider allows JASPI configuration for applications. This post is going to explain how to move from the old security configuration (which also provided JASPI) to the new one.
JASPI or JASPIC is a standard JavaEE API to authenticate users into the container. In general a ServerAuthModule should be implemented and the method validateRequest gets the user data from the request and validates it against the users and roles repository (LDAP, database,...). For the entry I am going to use a silly example. My module is just a BASIC authentication, it reads the header Authorization to retrieve the username and password, and validates the data against a pre-configured list of users. In JASPI the initialize method receives a map of options, and that map will be used to pass the list of usernames, passwords and roles managed by my sample. Each map entry will have the following format:
"username" => "password[###role1,role2,...]"
It is just a toy module but enough to exemplify how to use it in the old and the new security system. Here you can download the jaspi-module maven project which generates the final library (jaspi-module-1.0.jar). Let's start the configuration in wildfly 18.
The first step is adding the module into the server.
module add --name=es.rickyepoderi.jaspi --resources=/path/to/jaspi-module-1.0.jar --dependencies=javax.servlet.api,javax.security.auth.message.api
Now configure the JASPI in a security domain.
/subsystem=security/security-domain=jaspi-module:add /subsystem=security/security-domain=jaspi-module/authentication=jaspi:add(auth-modules=[{code=es.rickyepoderi.jaspi.ExampleServerAuthModule, module=es.rickyepoderi.jaspi, flag=required, module-options={"user1" => "password1###user,role1", "user2" => "password2###user", "user3" => "password3"}}])
The security domain called jaspi-module adds my ServerAuthModule and initializes it with three users (user1, user2 and user3), and the first two are assigned to the role user while the third one is not.
Now it is the time to deploy an application. A hello-world-jaxrs app was developed that is just a hello world but secured with the previous module. The hello endpoint says hello to the logged user. For that, the standard web.xml is used.
<?xml version="1.0" encoding="UTF-8"?> <web-app 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" version="3.1"> <security-constraint> <web-resource-collection> <web-resource-name>All resources</web-resource-name> <description>Protects all resources</description> <url-pattern>/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>user</role-name> </auth-constraint> <user-data-constraint> <transport-guarantee>NONE</transport-guarantee> </user-data-constraint> </security-constraint> <security-role> <description>Role required to log in to the Application</description> <role-name>user</role-name> </security-role> <login-config> <auth-method>BASIC</auth-method> </login-config> </web-app>
All the pages are protected and requires the user role (the one assigned to the first two users but not to user3). And finally the custom jboss-web.xml uses the jaspi-module security domain configured in the previous point.
<jboss-web> <security-domain>jaspi-module</security-domain> </jboss-web>
The application is deployed inside wildfly and can be tested using curl: the hello endpoint is not allowed for anonymous users; user1 can access and receives the hello; but user3 is forbidden (this user lacks the valid role).
curl http://localhost:8080/hello-world-jaxrs/api/hello <html><head><title>Error</title></head><body>Unauthorized</body></html> curl --anyauth --user user1:password1 http://localhost:8080/hello-world-jaxrs/api/hello Hello user1! curl --anyauth --user user3:password3 http://localhost:8080/hello-world-jaxrs/api/hello <html><head><title>Error</title></head><body>Forbidden</body></html>
So it is working. The old configuration for JASPI in wildfly is simple. A security domain was the only way of using this standard until wildfly 15.
Time to use the new JASPI elytron way. The old security domain is removed and a new jaspi-configuration is needed inside the elytron section.
/subsystem=security/security-domain=jaspi-module:remove /subsystem=elytron/jaspi-configuration=simple-configuration:add(layer=HttpServlet, application-context="default-host /hello-world-jaxrs", server-auth-modules=[{class-name=es.rickyepoderi.jaspi.ExampleServerAuthModule, flag=REQUIRED, module=es.rickyepoderi.jaspi, options={"user1" => "password1###user,role1", "user2" => "password2###user", "user3" => "password3"}}])
The new elytron configuration assigns JASPI to the application context, but the rest is more or less the same than in the old way (class and module, and the same configuration to define our three users).
Then JASPI needs a security domain to be created for the web layer undertow.
/subsystem=undertow/application-security-domain=jaspi-module:add(security-domain=ApplicationDomain, enable-jaspi=true, integrated-jaspi=false)
The domain uses the default ApplicationDomain, but please note that the option integrated-jaspi is set to false. This means that the JASPI module is enough, an ad hoc identity will be created independently of the domain realm. The default value true uses the realm in the ApplicationDomain to locate user and roles, so, besides the JASPI authentication, it also requires the user to be present in the realm.
Finally the same curl commands of step 4 can be executed. They should return the same output.
That is all for today. The new elytron security provides the old fashioned JASPI authentication since wildfly 15. The idea is more or less the same than in the old sub-system and, in general, the steps to configure it are very similar. Both configurations work, so, if you are using JASPI for your applications, better start using the new elytron way. The two little projects used in the entry (the JASPI module and the hello application) can be downloaded using the links provided before.
Best regards!
Comments