Grails Cookbook - A collection of tutorials and examples

Grails Spring Security Core Plugin - Registering Callback Closures

I was searching for a way to hook business logic after successful user login while using Spring Security Core plugin. The simplest way to do this is to register callback closures. It let's you hook your custom code inside Config.groovy after certain Spring Security events.

If you are unfamiliar with this plugin, visit the previous tutorial on Spring Security Core Plugin.

Registering Callback Closures

When you want to hook business logic on certain Spring Security Core events, you can edit grails-app/conf/Config.groovy and add something like the following:
grails.plugins.springsecurity.useSecurityEventListener = true
grails.plugins.springsecurity. onInteractiveAuthenticationSuccessEvent = { e, appCtx -> 
  // add custom code here
}
grails.plugins.springsecurity. onAbstractAuthenticationFailureEvent = { e, appCtx -> 
  // add custom code here
}
grails.plugins.springsecurity. onAuthenticationSuccessEvent = { e, appCtx -> 
  // add custom code here
}
grails.plugins.springsecurity. onAuthenticationSwitchUserEvent = { e, appCtx -> 
  // add custom code here
}
grails.plugins.springsecurity. onAuthorizationEvent = { e, appCtx ->
  // add custom code here
}
When using this, it is important to set grails.plugins.springsecurity.useSecurityEventListener to true as shown in the first line above.
As per the documentation in the plugin docs:
  • When a user authenticates, Spring Security initially fires an AuthenticationSuccessEvent (onAuthenticationSuccessEvent callback). This event fires before the Authentication is registered in the SecurityContextHolder, which means that the springSecurityService methods that access the logged-in user will not work.
  • Later in the processing a second event is fired, an InteractiveAuthenticationSuccessEvent (onInteractiveAuthenticationSuccessEvent callback), and when this happens the SecurityContextHolder will have the Authentication.
  • This means if you don't need to retrieve the logged in user, you can hook to onAuthenticationSuccessEvent. Otherwise, hook with onInteractiveAuthenticationSuccessEvent.

Example

This example will log all successful logins to a database table.
Model
I assume that the model for the user is SecUser as discussed here.
The logs will be saved in SecUserLog data model.
class SecUserLog {
  String username
  String action
  static constraints = {
    username blank: false, nullable: false
    action blank: false, nullable: false
  }
}

Service

I created a service to wrap all business logic to the SecUserLog domain. I used a service to show later how to access this inside Config.groovy.

class SecUserLogService {
  static transactional = true
  def securityService
  def addUserLog(String action) {
    SysUser user = securityService.getLoggedUser()
    SysUserActionLog log = new SysUserActionLog(username:user.username, action:action)
    log.save()
  }
}

Note that the service securityService is from the Spring Security Core Plugin.
Config.groovy entries

This are the code I added in Config.groovy

grails.plugins.springsecurity.useSecurityEventListener = true
grails.plugins.springsecurity.onInteractiveAuthenticationSuccessEvent = { e, appCtx ->
  def secUserLogService = appCtx.getBean('secUserLogService')
  secUserLogService.addUserLog("login")
}

The appCtx object is the application context, which can be used to look up Spring managed beans - that includes the services. After that, you can use the service as you please.

Other Grails Plugins Tutorials


Tags: acegi, callback, login, logout, Plugin, security, spring security