Wednesday 10 October 2012

Custom Glassfish Security Realm

Following on from the last post, our client required an user management console that delegated authentication to the container to leverage the SSO capabilities that were available.

Glassfish allows creating a JDBC realm that authenticates users and retrieves their roles from a database. 
The above screenshot shows how a new JDBC realm can be created from the Glassfish administrative console. This JDBC realm however specifies that there needs to be an User table with username and password columns, and a Group table with group name column with a foreign key to the user table as shown below:

T_USERS
USERNAME (PK)
PASSWORD
T_GROUPS
USERNAME (FK)
GROUPNAME
This is fine if the tables do not exist, but what if the database already exists or you require a mapping table for the many-to-many relationship between users and groups? For example, as our application was using Spring Security we already had a database schema as follows:
T_USERS
USERNAME (PK)
PASSWORD
....
T_USER_AUTHORITIES
USERNAME (FK)
ROLE_ID (FK)
T_ROLES
ROLE_ID (PK)
ROLENAME
In such a scenario, the Glassfish provided JDBCRealm is insufficient and a custom realm needs to be created. The custom jdbc realm will allow Glassfish to authenticate using the same database as the application is using to manage the users.

Creating a custom realm requires providing a custom JAAS login module class and custom realm class.
  • The custom login module must extend com.sun.appserv.security.AppservPasswordLoginModule.This class implements the javax.security.auth.spi.LoginModule.
  • The custom realm class must extend the abstract com.sun.appserv.security.AppservRealm class. You may find it easier to view the source code of the com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm class to provide a base from which to develop the custom realm class. Unfortunately, the JDBCRealm class is final and so cannot be extended. The realm class must also contain the HK2 @Service annotation to allow integration with the Glassfish OSGI module system.
  • Update the <GF_HOME>/domains/<DOMAIN-NAME>/config/login.conf to add an entry for the custom realm referring to the custom LoginModule.
  • Finally there should be a file named javax.security.auth.spi.LoginModule in the META-INF/services directory with the fully qualified name of the LoginModule class.
Once these classes have been written they need to be packaged as an OSGI bundle to be activated by Glassfish. For this purpose, we used the maven-bundle-plugin
 <dependencies>

<dependency>
            <groupId>org.glassfish.security</groupId>
            <artifactId>security</artifactId>
            <version>3.1.1-b11</version>
        </dependency>            
       
</dependencies>
<build>
       <plugins>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <Export-Package>                            ${project.groupId}.glassfish.auth;version=${project.version}
                        </Export-Package>
                        <Import-Package>
                            java.util,
                            javax.security.auth,
                            javax.security.auth.login,
                            javax.sql,                                                   
                            org.glassfish.security.common,
                            org.jvnet.hk2.annotations,
                            org.jvnet.hk2.component,
                            com.sun.appserv.connectors.internal.api,
                            com.sun.appserv.security,
                            com.sun.enterprise.security.common,
                            com.sun.enterprise.util,
                            com.sun.enterprise.util.i18n,                           
                            com.sun.enterprise.security.auth.realm,
                            com.sun.enterprise.security.auth.realm.jdbc,
                            com.sun.enterprise.security.auth.login.common,
                            com.sun.enterprise.security.auth.digest.api,
                            com.sun.enterprise.universal                           
                        </Import-Package>
                    </instructions>
                </configuration>
              </plugin>
</plugins>   
</build>
Note the export-package element should contain the name of the packages of the custom LoginModule class and custom AppservRealm classes.
Once the OSGI bundle has been created it can be loaded by copying it to <GF_HOME>/domains/<DOMAIN-NAME>/autodeploy/bundles.

The realm can now be created from the Glassfish administrative console. When an application that utilizes this realm is accessed the LoginModule will be initialized.




2 comments:

  1. this has nothing to do with a CUSTOM REALM, its actually about "how to use the glassfish JdbcRealm".

    ReplyDelete
  2. this has nothing to do with a CUSTOM REALM, its actually about "how to use the glassfish JdbcRealm".

    ReplyDelete