Extend CertificateRealm with LoginModule (Glassfish v3.1)
By Sudarsan Sridhar on Mar 04, 2010
Glassfish allows the creation of only one CertificateRealm, which doesn't perform any authentication. Some users may require a method to perform authentication on the certificates received from the client.
With v3.1 of glassfish, a method to do this is available. Now CertificateRealm allows one to specify an optional JAAS LoginModule to perform authentication. One can use this feature by downloading the nightly build after 03-04-2010.
Implementation and Configuration
Users of this facility must create an implementation of
javax.security.auth.spi.LoginModule interface. For details about the requirements for your LoginModule implementation, click here.
This LoginModule must be plugged into a
jaas-context and this must be specified as a parameter to the Realm '
certificate' in glassfish. The following steps have to be followed.
- For glassfish, a new
jaas-contextmust be specified into the file,
<domain-dir>/config/login.conf. To know more about the syntax of this file, click here.
To specify this
jaas-contextas a parameter, issue the following commands:
# <install-dir>/bin/asadmin set configs.config.server-config.security-service.auth-realm.certificate.property.jaas-context=<jaas-context-name>
This feature will be soon added to the admin GUI as well.
Accessing the client certificates
The client certificates are provided to the LoginModule as a public credential in the subject. This can be accessed as follows.
Set<List> creds = subject.getPublicCredentials(List.class);
certs = (X509Certificate) certCred.toArray(new X509Certificate[certCred.size()]);
Communicating with the container
The server passes a CallbackHandler to the LoginModule, during its initialize method. This CallbackHandler can be used to request various kinds of information from the server.
Currently, there are only two operations that can be done with the passed CallbackHandler.
- One can pass a
com.sun.enterprise.security.auth.realm.certificate. CertificateRealm.AppContextCallbackin order to infer the name of the application for which authentication is to be done. This information can be used for deciding the authentication strategy based on the application name.
- To add group principals to the subject, one can use the
javax.security.auth.message.callback.GroupPrincipalCallback. Group principal must be committed only by this method, otherwise they might not be recognized by the container during authorization.
Convenient abstract base class for certificate LoginModule
In order to make it convenient for the user to create a LoginModule for CertificateRealm, a new abstract base class has been introduced. This user's LoginModule can now extend
com.sun.appserv.security.AppservCertificateLoginModule. The user now has to implement only the
authenticateUser method and call the
commitUserAuthentication method to signify success.
The class provides some convenience methods for accessing the certificates, the application name, etc and for adding the group principals to the subject.
getAppName(): Returns the name of the application to be authenticated.
getCerts(): Returns the certificate chain as an array of
getX500Principal(): Returns the Distinguished principal from the first certificate in the chain.
getSubject(): Returns the subject that is being authenticated.
commitUserAuthentication(final String groups): This method can be used to commit the group principals for authorization. Only when this method is called with a non-null parameter, the authentication would be considered as to have succeeded.
Further, one can access the following protected fields.
_options: A map containing options configured for this LoginModule.
_sharedState: A map containing the state shared by LoginModule(s) in the
_logger: A logger that can be used to log messages to the server log.
You can check out the attached sample project and the corresponding
login.conf. This is built as a netbeans project. One would require to add, to the project,
modules directory of glassfish v3.1 installation. The web test case can be found here.
One would have to import the file
abc.jks into the glassfish truststore(
friend.p12 into the browser. The former can be done as follows:
# keytool -importkeystore -srckeystore abc.jks -destkeystore <domain-dir>/config/cacerts.jks -srcstorepass changeit
Once this is done, the certificate with
CN=Alice will pass authorization and
CN=Chuck will fail.