Groovy

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
  }
}

g4

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 is 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.

Jonathan Tan

Jon is a professional software engineer currently working in financial trading systems. He has worked in a wide variety of projects that includes mobile games, 3D visualization, artificial intelligence, banking and trading systems. He loves to teach people and expresses his passion through blogging.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button