Tuesday, May 6, 2014

Grails Spring Security Plugin - Creating your own custom authorization and authentication

Grails Spring Security plugin works nicely out of the box - creating your User and Role domain classes, and appropriate mapping between them, as well (optionally) request map domain, where you can configure access to specific url through database, rather than hard-coding it, either via annotations or providing simple predefined map to Grails application.

But if you want to customize authorization and authentication process, like for in instance working with legacy systems, or, for an example, if you want to store salt for password on completely other server or in has file (or any way you want), your Grails application needs bit more configuration.

Below are 3 simple steps to achieve this behaviour

1. Create your own Authentication Provider - implementing AuthenticationProvider interface

class MyAuthenticationProvider implements AuthenticationProvider {
 
 @Override
 public Authentication authenticate(Authentication arg0)
    throws AuthenticationException {
        def userName = (arg0 as UsernamePasswordAuthenticationToken).getPrincipal(),
        password = (arg0 as UsernamePasswordAuthenticationToken).getCredentials(),    
        user = getUserByUserName(userName),    
        providedPassword = encodePassword(password, user),   
        realPassword = getUserPassword(user)   
        if(!providedPassword.equals(realPassword)){
          throw new BadCredentialsException("Bad login credentials!")
         }    
        def authorities = getUserAuthorities(user)   
        return new UsernamePasswordAuthenticationToken(user, arg0.credentials, authorities)
 } 
 
 private def getUserByUserName = { username ->
  //TODO your application code here
  //TODO retrieve user by username, and return
 }
 
 private def encodePassword = {  password ->
  //TODO your application code here
  //TODO encode password
 }
 
 private def getUserPassword = { user ->
  //TODO your application code here
  //TODO return  user password
  //e.g. return user.getPassword()
 }
 
 private def getUserAuthorities = { user ->
  //TODO your application code here
  //TODO return  user password
  //e.g. return user.getUserRoles()
 }
 
 @Override
 public boolean supports(Class<?> arg0) {
  return true;
 }
}

2. Create a bean named 'myApplicationAuthenticationProvider', in resources.groovy


beans = { 
 myAuthenticationProvider(com.myproductname.MyAuthenticationProvider)
}

3. Reference created bean in Config.groovy


grails.plugin.springsecurity.providerNames = ['myAuthenticationProvider']


Note that above example is tested on Grails version 2.3.5. Just stick your logic in authenticate() method of your authentication provider, above example has TODO comments, but you can organize your code any way you wish (advanced example would be reading password salt from storage other than relational database, e.g. hashfile)