Logging Spring Security Events in Grails

The grails spring-security-core plugin is great way to get full featured authentication in a web application with minimal effort. It mostly just works out of the box, and in combination with the spring-security-ui plugin, you can have fully functional login, self-registration (with email confirmation), and administration console with almost no code.

The underlying spring security library uses spring application events to inform the app when interesting stuff happens.

It’s sometimes nice to keep track of when users login — or fail to — and logout. A grails app can hook into spring security events by creating an ApplicationListener class in src/groovy.

Note that spring security doesn’t send events for logouts. Those can be captured by setting up a custom logout handler. Keep in mind you’ll only get logout events if the user logs out directly, rather than the session expiring.

This example handles both regular security events and logouts by logging them.

package ca.redtoad.security

import javax.servlet.http.*
import org.apache.commons.logging.LogFactory
import org.springframework.context.ApplicationListener
import org.springframework.security.authentication.event.AbstractAuthenticationEvent
import org.springframework.security.core.Authentication
import org.springframework.security.web.authentication.logout.LogoutHandler

class LoggingSecurityEventListener implements 
    ApplicationListener<AbstractAuthenticationEvent>, LogoutHandler {

    private static final log = LogFactory.getLog(this)

    void onApplicationEvent(AbstractAuthenticationEvent event) {
        event.authentication.with {
            def username = principal.hasProperty('username')?.getProperty(principal) ?: principal
            log.info "event=${event.class.simpleName} username=${username} " +
                "remoteAddress=${details.remoteAddress} sessionId=${details.sessionId}"

    void logout(HttpServletRequest request, HttpServletResponse response, 
        Authentication authentication) {
        authentication.with {
            def username = principal.hasProperty('username')?.getProperty(principal) ?: principal
            log.info "event=Logout username=${username} " +
                "remoteAddress=${details.remoteAddress} sessionId=${details.sessionId}"

Next the security event listener has to be registered as a spring bean in grails-app/conf/spring/resources.groovy.

import ca.redtoad.security.LoggingSecurityEventListener

beans = {

Finally, we need make two additions to grails-app/conf/Config.groovy: turn on the grails security event listener, and override the logout handlers to include ours.

grails.plugins.springsecurity.useSecurityEventListener = true
grails.plugins.springsecurity.logout.handlerNames = 
  1. This is great, thanks you for solving my problem debugging what was happening when adding Spring Security plugin to my Grails 1.3.7 webapp, in order to interface with the Spring Security managed tables from another webapp.

  1. There are no trackbacks for this post yet.