Monday, May 9, 2011

Grails Plugin Spring Security Kerberos Sample

This blog is about a simple sample application that demonstrates usage of Grails Spring Security Kerberos Plugin. It is assumed that the reader is familiar with Kerberos Authentication, Grails, Spring Security and Grails Plugin system.

The above plugin is just a wrapper on top of Spring Security Kerberos Extension. All it is doing is to handle the Spring beans assembly and integrate with the Spring Core Security Plugin.

Start with reading the documentation on Kerberos Grails Plugin and the blog on Spring Kerberos Extension. As you can see there isn't much configuration to do in Grails Kerberos Plugin. Just the Keytab file path and Service Principal Name are required.

Read the blog on Kerberos Extension carefully and create the Keytab file for the Service Principal (Your AD administrator would do it). The bulleted check list found towards the end of the Kerberos Extension blog is very helpful to make sure that everything is done properly.

What is the Grails Plugin is all about?
There is a section "Configuring Spring Security" in the above blog. The plugin has all those configurations taken care of except the URL mapping. So you don't have to do it in your Grails application

How do I do the URL mapping?
Just use one of the options provided by Spring Security Core Plugin (@Secured, Requestmap etc.)

What are the other catches?
Typically when Kerberos SSO authentication is used, no user details would be stored in the application database. In Spring Security the user details are loaded into the security context by the "userDetailsService" bean. This is demonstrated by the usage of "dummyUserDetailsService" in the Kerberos Extension sample.
So in the Grails application the following bean should be present in conf/spring/resources.groovy. Otherwise Security domain objects (User, Role etc.) should be in use

beans = {
userDetailsService(com.mycompany.myapp.MyUserDetailsService)
}

Now about the sample application.
This is how I had created the application
> grails create-app grails-spring-security-kerberos-sample
> grails install-plugin spring-security-kerberos
And added is main.gsp and index.gsp.

** Consider "mymachine" as the CNAME/Hostname of the machine being used deploy the application and "mydomain" is the domain controller
So the Service Principal should be "HTTP/mymachine.mydomain.com@MYDOMAIN.COM"
The name of the keytab file could be anything.

Let's start Config.groovy configuration.

// Kerberos related
grails.plugins.springsecurity.kerberos.ticketValidator.servicePrincipal='HTTP/mymachine.mydomain.com@MYDOMAIN.COM'
grails.plugins.springsecurity.kerberos.ticketValidator.keyTabLocation='file://D:/keytabs/myapp.keytab'   //put the keytab file in a secure location


// Spring Security Core related (You may use other options too)
grails.plugins.springsecurity.securityConfigType = SecurityConfigType.InterceptUrlMap
grails.plugins.springsecurity.interceptUrlMap = ['/**': ['IS_AUTHENTICATED_FULLY']]

What about KDC configuration?
Create a krb5.conf file and point to it using -Djava.security.krb5.conf JVM option. A sample can be found in the root folder of the source.
In Windows a krb5.ini file (exact name only) can be placed in C:/Windows folder

That's it.
Now run the application
Access it from another machine in the same domain using the fully qualified name of machine where application is running (localhost will not work, also using IP address from another machine).
If the authentication is successful, the NT user name will be displayed in home page.

Download the source (Eclipse/STS)

Just unzip it, create the Keytab file for the Service Principal and change the Config.groovy entries. You are ready to go.

My Environment Details
  • app.grails.version=1.3.7
  • plugins.spring-security-kerberos=0.1
  • JDK 1.6.0_23
  • Windows XP
  • Sample worked with embedded server (run-app) and apache-tomcat-7.0.10
  • Windows 2003 Server (Used a local domain controller setup [i.e. two XP and one 2003])
  • IE 6 & 7, FF 4.0 and Chrome 11
  • STS 2.5.2 (Springsource Tool Suite)
Error when "userDetailsService" bean is not Present
ERROR [/grails-spring-security-kerberos-sample].[default]  - Servlet.service() for servlet default threw exception
java.lang.NullPointerException: Cannot get property 'clazz' on null object
at org.codehaus.groovy.runtime.NullObject.getProperty(NullObject.java:56)
at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:156)
at org.codehaus.groovy.runtime.callsite.NullCallSite.getProperty(NullCallSite.java:44)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:235)
at org.codehaus.groovy.grails.plugins.springsecurity.GormUserDetailsService.loadUserByUsername(GormUserDetailsService.groovy:50)

Hope this blog helps you implement Keberos based security in your Grails application.