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

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.
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.
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?
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.
Hi omarji
I managed to achieve this by overriding the authenticationProcessing filter bean definition to my custom implementation and process both password
However when i do thism the reuquest object that i try to access in the onSuccessLoginEvent becomes null which is not if i dont override
i have posted my query in the forum but so far no luck
this is my post
http://grails-plugins.847840.n3.nabble.com/Overriding-UsernamePasswordAUthenticationFilter-for-second-password-tt2934069.html#none
rgds
I for all time emailed this website post page to all my associates, because if like to read it then my friends will too.