Skip to content


Customizing authentication in your grails app

I’ve been working on a small proof on concept application to test out the Grails Spring Security Core Plugin and the things I can do with it.
If you haven’t used the plugin before, I highly recommend reading the introductory blog post and the companion screen-casts which you will find on the plugin page.

Anyway, following the blog post got me up an running in no time with the basics, but I wanted to go a bit further and implement the following:

  • Add an email address property to the user domain
  • Allow the user to authenticate using his/her user name or using the email address (I find this a very handy option; with all the different usernames you would have for different sites, it’s nice to be able to use your email to login when you can’t remember the username)

Thanks to the very well written documentation I was able to implement this in no time. Here are the steps I followed to do this.

Create a skeleton test application and install the spring security core plugin

I’ll go over these real quick, for more details check the introductory blog post

Create the test application

grails create-app custom-auth

cd to the custom-auth directory and install the spring security plugin

grails install-plugin spring-security-core

Use the plugin helper command line to create the user and role domain objects, along with the controllers and other goodies

grails s2-quickstart org.customauth CustomUser CustomRole

And finally, add the url mapping to the controllers that the s2-quickstart automatically created (Not really needed.)
This should be enough to get you up and running. (You need to create a test user in the Bootstarp, but I’ll do that later)

Implement the first requirement – Add an email address property to the user domain

This is really simple, just add the property to the domain class :)

package org.customauth

class CustomUser {

	String username
	String password
	String email
	boolean enabled
	boolean accountExpired
	
	// *******
	// the rest of the generated class contents
	// *******
}

Implement the second requirement – Authenticate using the username or the email

In order to implement this requirement, I will have to implement a new UserDetailsService (according to the documentation)

I could also extend the UserDetails class and add the email property so that it is cached instead of hitting the database everytime I need it, but I don’t really care about this right now.

So, extending the UserDetailsService involves adding the extra logic to the loadUserByUsername method. (Not sure if this is the best way to do it since the name is a bit misleading, but it worked).
Here is how the new service looks like

package org.customauth

import org.codehaus.groovy.grails.plugins.springsecurity.GrailsUser 
import org.codehaus.groovy.grails.plugins.springsecurity.GrailsUserDetailsService 
import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils 
import org.springframework.security.core.authority.GrantedAuthorityImpl 
import org.springframework.security.core.userdetails.UserDetails 
import org.springframework.security.core.userdetails.UsernameNotFoundException

class CustomUserDetailsService implements GrailsUserDetailsService {

	static final List NO_ROLES = [new GrantedAuthorityImpl(SpringSecurityUtils.NO_ROLE)]

	UserDetails loadUserByUsername(String username, boolean loadRoles) throws UsernameNotFoundException { 
		return loadUserByUsername(username) 
	}

	UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
	
		CustomUser.withTransaction { status ->
			CustomUser user = CustomUser.findByUsernameOrEmail(username, username) 
			if (!user) 
				throw new UsernameNotFoundException('User not found', username)
				
			def authorities = user.authorities.collect {new GrantedAuthorityImpl(it.authority)}
			
			return new GrailsUser(user.username, user.password, user.enabled, !user.accountExpired, 
				!user.passwordExpired, !user.accountLocked, 
				authorities ?: NO_ROLES, user.id) 
		} 
	} 
}

So basically instead of checking the user in the database using the username through CustomUser.findByUserName(username), I query to find the user by the username or by the email given the username string that will be passed to this method from the login form.

With the custom service in place, I need to register it in grails-app/conf/spring/resources.groovy by adding

 
beans = {
	userDetailsService(org.customauth.CustomUserDetailsService)
}

That’s it, if you add a test user in your Bootstrap.groovy, (make sure to assign an email address), you should be able to login with either the username or the email address, just access the login page and try it.

Disclaimer: Not sure if this is the correct way to implement this since I am not very familiar with spring security, but it works. Update: Looks like that is the way it is done :)

Posted in Programming.

Tagged with , , .


9 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

  1. Burt Beckwith says

    That’s pretty much how it’s done. A couple of minor tweaks though. HQL queries only need full package and class name when you have two domain classes with the same name, so your HQL could be “from CustomUser as usr where …”. But I’d just use a dynamic finder – CustomUser user = CustomUser.findByUsernameOrEmail(username, username)

    Also – why are the url mappings for LoginController and LogoutController necessary? Those should resolve fine without the mappings.

  2. omarji says

    Cool, thanx Burt. I’ve updated the post.
    As for the mappings, You are correct there is no need for them. I just assumed they will be needed since this was mentioned in the introductory blog post, but I tried to remove them and everything worked out fine.

  3. ballistic_realm says

    Hi Nice tutorial

    i have another question. If i am to use 2 password in the login screen, let say

    username : ________________
    password1 : _______________
    password2 : _______________

    is this possible and how to access the second password in the userdetailservice class?

    • omarji says

      Thanks.
      Hmm, not sure how to do this, couldn’t you combine them into 1 password when setting the user password from 2 passwords, and doing the same when the user tries to login? I’m not quite sure if that works with your use case but it’s just a though.
      Maybe Burt could be of assitance here or you could maybe ask this on the user list, I’d be interested to know the answer.

  4. jadmmagi.posterous.com says

    I for all time emailed this website post page to all my associates, because if like to read it then my friends will too.

Continuing the Discussion

  1. Blog bookmarks 09/28/2010 « My Diigo bookmarks linked to this post on September 28, 2010

    [...] Customizing authentication in your grails app – train of thought [...]

  2. Customizing authentication in your grails app - Grails Tutorial linked to this post on October 15, 2010

    [...] Check out the original for detail   [...]

  3. grailstutorial.org linked to this post on January 13, 2011

    Customizing authentication in your grails app…

    I’ve been working on a small proof on concept application to test out the Grails Spring Security Core Plugin and the things I can do with it. If you haven’t used the plugin before, I highly recommend reading the introductory blog post and the companion…



Some HTML is OK

or, reply to this post via trackback.