This article will be in two parts, first explaining the high-level view, and the second part will focus on implementing the same with code snippets.
The main reason behind writing this article is, you may find a lot of articles on RBAC for JBoss or any other AS, but we also want to hold important context values from a single query instead of firing a lot of repeated queries. In my case, I need to do two things:
Authentic a user.
Fetch other data, such as username, actual name, last login time, etc.
So, to summarize:
What we want to do is secure all the resources on JBoss AS, and allow only authorized users to access them. This security check can be applied to web resources, web services, and EJBs.
The users should be authenticated from database tables and have their roles fetched from the relational tables, once they are authenticated.
Since we also need to attach other important information related to the user to the application context, we need a Custom formed based authentication and authorization mechanism. This mechanism when developed should be deployed as a JBoss module.
This authentication mechanism can also encrypt and decrypt the password from database tables.
To begin, we first need an implementation of the AbstractServiceLoginModule. The following methods need to be implemented:
getRoleSets() to return at least one group named “Roles” that contains 0+ roles assigned to the user.
Write another implementation
ofPrincipal, but extend SimplePrincipal, because JBoss uses the PicketBox framework for JAAS, and thus JBoss expects each Principal to be of the type,
SimplePrincipal . We can store extra information picked from Database tables in our implementation of Principal.
So we can create a few private String fields according to our requirement. Create as many fields you want.
Package this application as a Java archive (.jar) and make sure you have the PicketBox jars on the classpath. To simplify, create a Maven project and add the following dependencies:
<dependency> <groupId>org.picketbox</groupId> <artifactId>picketbox</artifactId> <version>4.0.17.Final-redhat-1</version> <scope>provided</scope> </dependency>
Installing the New Security Domain Module on JBoss
<module xmlns="urn:jboss:module:1.1" name="CustomDatabaseLoginModule"> <resources> <resource-root path="LoginModule.jar"/> </resources> <dependencies> <module name="org.picketbox"/> <module name="javax.api"/> </dependencies> </module>
The next step will be to instruct JBoss AS to use the security domain. Make the following changes in the standalone/domain.xml:
<security-domain name="customdbdomain" cache-type="default"> <authentication> <login-module code="com.cts.controller.CustomLoginModule" flag="required"> <module-option name="dsJndiName" value="java:jboss/datasources/ExampleDS"/> <module-option name="principalsQuery" value="select USERS.passwd,USERNAME.NAME from USERS,USERNAME where USERS.LOGIN = USERNAME.LOGIN AND USERS.login=?"/> <module-option name="rolesQuery" value="select role, 'Roles' from USER_ROLES WHERE LOGIN=?"/> </login-module> </authentication> </security-domain>
Make sure you have datasource configured and added to the datasource subsystem, and the JNDI name of the datasource is correct and the same at both the places.
Usually, if you look at the standalone/domain.xml, you will find a lot of security domain in the security realm. We have to make sure that our application uses our new security domain, in order to do that, open up
jboss-web.xml located at
WEB-INF/jboss-web.xml. Change the security domain name to match the name of our new domain.
Access Control Configuration From the App
web.xml , or
ejb-jar.xml, we have to map the resource to roles. If the authentic client has a role defined for the particular resource it will be able to consume it.
Since we want form based authentication, we need to create a few additional HTML/JSP pages as well:
login.html – Where the client can enter their username and password.
error.html – When the authentication fails due to a wrong username and password being submitted.
403.html – When an authentic client tries to access a resource for which he has no privilege, the JBoss will re-direct them to this page.
Note: These pages are simple and are valid for web resources only. For web services and EJB, the authentication and error handling is different.
Encrypting the Password
It is not safe to store the password in the plain string format in the database table. We should use some kind of message digest system. JBoss allows you to handle this while validating a password. To enable the message digest system and hashing, make changes in the security domain and two new module options:
<module-option name=“hashAlgorithm” value=“SHA-256”/>
<module-option name=“hashEncoding” value=“BASE64”/>
Then override the method
convertRawPassword() to write decryption logic which will convert the hash value of the password to correct values.
If you follow these correctly and precisely you’ll be able to implement custom JAAS in your application.