Wednesday, March 5, 2008

Glassfish login module : a simple example

In this tutorial we will see how to write a very simple custom login module for the Glassfish application server.
Even if Glassfish ships with some useful login modules, there are not adapted to every situations, most notably with custom LDAP directories or strange authentication methods.
Chapter 5 of the Glassfish developer documentation is a must read on this subject, and reading it is recommended before trying to write your own custom login module.

Our custom authentication scheme
In this example we want to implement a very simple authentication method : a user is authenticated if is username start with a specific string. For example, if the string is "z", then the users zed and zorro can login.

A configurable login module
The login module must be fully configurable. The application server administrator can configure the string used in our authentication scheme.

The custom realm
A custom login module in glassfish is composed by two classes :
- a custom realm, which handle realm configuration
- a custom login module, which handle authentication based on the informations given by the custom realm
A custom realm must extends AppservRealm :
public class MyRealm extends AppservRealm {
  private String jaasCtxName;
  private String startWith;

@Override protected void init(Properties props) throws BadRealmException, NoSuchRealmException { _
  logger.info("X-TECH MyRealm: init()");
  jaasCtxName = props.getProperty("jaas-context""xtechMyRealm");
  startWith = props.getProperty("startWith""z");
}

@Override public String getJAASContext() { return jaasCtxName; }

public Enumeration getGroupNames(String string) throws InvalidOperationException, NoSuchUserException {
  List groupNames = new LinkedList(); 

  return (Enumeration) groupNames;
}

public String getAuthType() { 

  return "X-TECH MyRealm"; 
}


public String getStartWith() { 
  return startWith; 
}

}


The custom login module
A custom login must extends AppservPasswordLoginModule and override authenticateUser():
public class MyLoginModule extends AppservPasswordLoginModule {

protected void authenticateUser() throws LoginException {
  _logger.info("X-TECH MyLoginModule : authenticateUser for " +
    _username);
  MyRealm realm = (MyRealm) _currentRealm;

  if (!_username.startsWith(realm.getStartWith())) {
    _logger.info("Invalid credentials.");
    throw new LoginException ("Invalid credentials.");
  }

  _logger.info("User authenticated");
  Set principals = _subject.getPrincipals();
  principals.add(new PrincipalImpl(_username));

  String grpList[] = new String[1];
  grpList[0] = "User";
  this.commitUserAuthentication(grpList);
}

}




Installing the custom login module
Installing and activating the customs realm and login module involve three steps :
- Configuring a realm using the glassfish administration console
- Linking the custom realm with the custom login module
- Make the classes avaible to glassfish
The first step is illustrated in the screenshot below :
The second step is done by editing the login.conf file located in the config directory of the domain. Add a line like this one to the end of the login.conf file:
xtechMyRealm { org.xtech.examples.gfloginmodule.MyLoginModule required; };
For the last step just copy the .jar file containing the customs realm and login module classes in the lib directory of glassfish (you must restart glassfish).

Writing an example application
To try the new login module create a web application with only a index.jsp page. Put this line to display the authenticated user name :
Welcome ${pageContext.request.userPrincipal.name}
Add security to the web.xml file:


and link the web application security roles with the group name used in the custom login module by adding the folowing lines to the sun-web.xml file:

Deploy your application and give it a try !
A Ki Ki L'Est Le Numéro ? Annuaire téléphone et adresse inverse et pas inverse

4 comments:

John Yeary said...

This is very nicely done.

The only thing that I came across that I thought was incorrect was order. You need to place the jar file in the ../domains/{domain}/lib directory for GlassFish 3.1.1.

ASHISH RAMESH AGRE said...

Awesome man thanks A LooooOOOOOoOOOtttTtttT...!!!!!

Constantine said...

Where in MyRealm said to use MyLogin?

HM said...

@Constantine : in the login.conf file: "The second step is done by editing the login.conf file located in the config directory of the domain. Add a line like this one to the end of the login.conf file:
xtechMyRealm { org.xtech.examples.gfloginmodule.MyLoginModule required; };"