Home > Articles > Security > Software Security

Building a Custom JBoss Login Module

  • Print
  • + Share This
JBoss comes with very useful modules to define how to log in, but they're designed in a generic fashion to be examples or used in a very simple application. Marcus Zarra walks you through extending one of these modules to fit a custom requirement.
Like this article? We recommend

Like this article? We recommend

One of the most commonly used login modules for JBoss is the DatabaseLoginModule, which is designed to allow an application running in JBoss to utilize virtually any table to handle the management of users. With the parameters defined properly it is relatively easy to connect JBoss to your existing user table and allow for single sign-on. But what if you need other steps taken during the sign-in process that go beyond simple username/password verification?

Fortunately, the login modules that are included with JBoss are designed to be extended. In a recent project of mine, I was tasked with modifying the DatabaseLoginModule and extending its functionality to do the following:

  • Count the number of failed login attempts
  • Lock out a user who exceeded a certain threshold
  • Track all failed login attempts
  • Record when a user successfully logged in
  • Allow a user to be logged in only once
  • Reset the login attempts on a successful login

This is a fairly extensive list, and this functionality logically belongs in the login module. To accomplish this goal, I needed to extend the DatabaseLoginModule. This module itself extends the functionality of UsernamePasswordLoginModule, which extends AbstractServerLoginModule. So there are a lot of extensions going on here. First, let us look at the methods that are being used by this string of objects:


















Login Method

Fortunately, I will need to extend only a small subset of these methods. To begin the extension, the first method I need to look at is login, which is handled in the UsernamePasswordLoginModule class. The original code for this module from the JBoss 3.2.6 source code is fairly involved, and—based on the way it is designed—does not allow me to interject code into it without modifying the original. The cleanest way to handle this is to copy the code from the UsernamePasswordLoginModule into my extended class and then inject my changes from there. Here is the original login method code:

 public boolean login() throws LoginException {
  // See if shared credentials exist
  if (super.login() == true) {
   // Setup our view of the user
   Object username = sharedState.get("javax.security.auth.login.name");

   if (username instanceof Principal) {
    identity = (Principal) username;
   } else {
    String name = username.toString();

    try {
     identity = createIdentity(name);
    } catch (Exception e) {
     log.debug("Failed to create principal", e);
     throw new LoginException("Failed to create principal: " +

   Object password = sharedState.get("javax.security.auth.login.password");

   if (password instanceof char[]) {
    credential = (char[]) password;
   } else if (password != null) {
    String tmp = password.toString();
    credential = tmp.toCharArray();

   return true;

  super.loginOk = false;

  String[] info = getUsernameAndPassword();
  String username = info[0];
  String password = info[1];

  if ((username == null) && (password == null)) {
   identity = unauthenticatedIdentity;
   super.log.trace("Authenticating as unauthenticatedIdentity=" + identity);

  if (identity == null) {
   try {
    identity = createIdentity(username);
   } catch (Exception e) {
    log.debug("Failed to create principal", e);
    throw new LoginException("Failed to create principal: " +

   // Hash the user entered password if password hashing is in use
   if (hashAlgorithm != null) {
    password = createPasswordHash(username, password);

   // Validate the password supplied by the subclass
   String expectedPassword = getUsersPassword();

   if (validatePassword(password, expectedPassword) == false) {
    super.log.debug("Bad password for username=" + username);
    throw new FailedLoginException("Password Incorrect/Password Required");

  // Add the username and password to the shared state map
  if (getUseFirstPass() == true) { 
   sharedState.put("javax.security.auth.login.name", username);
   sharedState.put("javax.security.auth.login.password", credential);

  super.loginOk = true;
  super.log.trace("User '" + identity + "' authenticated, loginOk=" +

  return true;
  • + Share This
  • 🔖 Save To Your Account