(Quick Reference)

6 Events - Reference Documentation

Authors: Burt Beckwith, Beverley Talbott

Version: 2.0.0

6 Events

Spring Security fires application events after various security-related actions such as successful login, unsuccessful login, and so on. Spring Security uses two main event classes, AbstractAuthenticationEvent and AbstractAuthorizationEvent.

6.1 Event Notification

You can set up event notifications in two ways. The sections that follow describe each approach in more detail.
  • Register an event listener, ignoring events that do not interest you. Spring allows only partial event subscription; you use generics to register the class of events that interest you, and you are notified of that class and all subclasses.
  • Register one or more callback closures in grails-app/conf/Config.groovy that take advantage of the plugin's grails.plugin.springsecurity. SecurityEventListener. The listener does the filtering for you.

AuthenticationEventPublisher

Spring Security publishes events using an AuthenticationEventPublisher which in turn fire events using the ApplicationEventPublisher. By default no events are fired since the AuthenticationEventPublisher instance registered is a grails.plugin.springsecurity.authentication. NullAuthenticationEventPublisher. But you can enable event publishing by setting grails.plugin.springsecurity.useSecurityEventListener = true in grails-app/conf/Config.groovy.

You can use the useSecurityEventListener setting to temporarily disable and enable the callbacks, or enable them per-environment.

UsernameNotFoundException

Most authentication exceptions trigger an event with a similar name as described in this table:

ExceptionEvent
AccountExpiredExceptionAuthenticationFailureExpiredEvent
AuthenticationServiceExceptionAuthenticationFailureServiceExceptionEvent
LockedExceptionAuthenticationFailureLockedEvent
CredentialsExpiredExceptionAuthenticationFailureCredentialsExpiredEvent
DisabledExceptionAuthenticationFailureDisabledEvent
BadCredentialsExceptionAuthenticationFailureBadCredentialsEvent
UsernameNotFoundExceptionAuthenticationFailureBadCredentialsEvent
ProviderNotFoundExceptionAuthenticationFailureProviderNotFoundEvent

This holds for all exceptions except UsernameNotFoundException which triggers an AuthenticationFailureBadCredentialsEvent just like a BadCredentialsException. This is a good idea since it doesn't expose extra information - there's no differentiation between a bad password and a missing user. In addition, by default a missing user will trigger a BadCredentialsException for the same reasons. You can configure Spring Security to re-throw the original UsernameNotFoundException instead of converting it to a BadCredentialsException by setting grails.plugin.springsecurity.dao. hideUserNotFoundExceptions = false in grails-app/conf/Config.groovy.

Fortunately all subclasses of AbstractAuthenticationFailureEvent have a getException() method that gives you access to the exception that triggered the event, so you can use that to differentiate between a bad password and a missing user (if hideUserNotFoundExceptions=false).

6.2 Registering an Event Listener

Enable events with grails.plugin.springsecurity.useSecurityEventListener = true and create one or more Groovy or Java classes, for example:

package com.foo.bar

import org.springframework.context.ApplicationListener import org.springframework.security.authentication.event. AuthenticationSuccessEvent

class MySecurityEventListener implements ApplicationListener<AuthenticationSuccessEvent> {

void onApplicationEvent(AuthenticationSuccessEvent event) { // handle the event } }

Register the class in grails-app/conf/spring/resources.groovy:

import com.foo.bar.MySecurityEventListener

beans = { mySecurityEventListener(MySecurityEventListener) }

6.3 Registering Callback Closures

Alternatively, enable events with grails.plugin.springsecurity.useSecurityEventListener = true and register one or more callback closure(s) in grails-app/conf/Config.groovy and let SecurityEventListener do the filtering.

Implement the event handlers that you need, for example:

grails {
  plugin {
    springsecurity {
      useSecurityEventListener = true

onInteractiveAuthenticationSuccessEvent = { e, appCtx -> // handle InteractiveAuthenticationSuccessEvent }

onAbstractAuthenticationFailureEvent = { e, appCtx -> // handle AbstractAuthenticationFailureEvent }

onAuthenticationSuccessEvent = { e, appCtx -> // handle AuthenticationSuccessEvent }

onAuthenticationSwitchUserEvent = { e, appCtx -> // handle AuthenticationSwitchUserEvent }

onAuthorizationEvent = { e, appCtx -> // handle AuthorizationEvent } } } }

None of these closures are required; if none are configured, nothing will be called. Just implement the event handlers that you need.

Note: When a user authenticates, Spring Security initially fires an AuthenticationSuccessEvent. 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, and when this happens the SecurityContextHolder will have the Authentication. Depending on your needs, you can implement a callback for either or both events.