You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
166 lines
5.0 KiB
166 lines
5.0 KiB
[[servlet-events]] |
|
= Authentication Events |
|
|
|
For each authentication that succeeds or fails, a `AuthenticationSuccessEvent` or `AuthenticationFailureEvent`, respectively, is fired. |
|
|
|
To listen for these events, you must first publish an `AuthenticationEventPublisher`. |
|
Spring Security's `DefaultAuthenticationEventPublisher` works fine for this purpose: |
|
|
|
[tabs] |
|
====== |
|
Java:: |
|
+ |
|
[source,java,role="primary"] |
|
---- |
|
@Bean |
|
public AuthenticationEventPublisher authenticationEventPublisher |
|
(ApplicationEventPublisher applicationEventPublisher) { |
|
return new DefaultAuthenticationEventPublisher(applicationEventPublisher); |
|
} |
|
---- |
|
|
|
Kotlin:: |
|
+ |
|
[source,kotlin,role="secondary"] |
|
---- |
|
@Bean |
|
fun authenticationEventPublisher |
|
(applicationEventPublisher: ApplicationEventPublisher?): AuthenticationEventPublisher { |
|
return DefaultAuthenticationEventPublisher(applicationEventPublisher) |
|
} |
|
---- |
|
====== |
|
|
|
Then you can use Spring's `@EventListener` support: |
|
|
|
[tabs] |
|
====== |
|
Java:: |
|
+ |
|
[source,java,role="primary"] |
|
---- |
|
@Component |
|
public class AuthenticationEvents { |
|
@EventListener |
|
public void onSuccess(AuthenticationSuccessEvent success) { |
|
// ... |
|
} |
|
|
|
@EventListener |
|
public void onFailure(AbstractAuthenticationFailureEvent failures) { |
|
// ... |
|
} |
|
} |
|
---- |
|
|
|
Kotlin:: |
|
+ |
|
[source,kotlin,role="secondary"] |
|
---- |
|
@Component |
|
class AuthenticationEvents { |
|
@EventListener |
|
fun onSuccess(success: AuthenticationSuccessEvent?) { |
|
// ... |
|
} |
|
|
|
@EventListener |
|
fun onFailure(failures: AbstractAuthenticationFailureEvent?) { |
|
// ... |
|
} |
|
} |
|
---- |
|
====== |
|
|
|
While similar to `AuthenticationSuccessHandler` and `AuthenticationFailureHandler`, these are nice in that they can be used independently from the servlet API. |
|
|
|
== Adding Exception Mappings |
|
|
|
By default, `DefaultAuthenticationEventPublisher` publishes an `AuthenticationFailureEvent` for the following events: |
|
|
|
|============ |
|
| Exception | Event |
|
| `BadCredentialsException` | `AuthenticationFailureBadCredentialsEvent` |
|
| `UsernameNotFoundException` | `AuthenticationFailureBadCredentialsEvent` |
|
| `AccountExpiredException` | `AuthenticationFailureExpiredEvent` |
|
| `ProviderNotFoundException` | `AuthenticationFailureProviderNotFoundEvent` |
|
| `DisabledException` | `AuthenticationFailureDisabledEvent` |
|
| `LockedException` | `AuthenticationFailureLockedEvent` |
|
| `AuthenticationServiceException` | `AuthenticationFailureServiceExceptionEvent` |
|
| `CredentialsExpiredException` | `AuthenticationFailureCredentialsExpiredEvent` |
|
| `InvalidBearerTokenException` | `AuthenticationFailureBadCredentialsEvent` |
|
|============ |
|
|
|
The publisher does an exact `Exception` match, which means that sub-classes of these exceptions do not also produce events. |
|
|
|
To that end, you may want to supply additional mappings to the publisher through the `setAdditionalExceptionMappings` method: |
|
|
|
[tabs] |
|
====== |
|
Java:: |
|
+ |
|
[source,java,role="primary"] |
|
---- |
|
@Bean |
|
public AuthenticationEventPublisher authenticationEventPublisher |
|
(ApplicationEventPublisher applicationEventPublisher) { |
|
Map<Class<? extends AuthenticationException>, |
|
Class<? extends AbstractAuthenticationFailureEvent>> mapping = |
|
Collections.singletonMap(FooException.class, FooEvent.class); |
|
DefaultAuthenticationEventPublisher authenticationEventPublisher = |
|
new DefaultAuthenticationEventPublisher(applicationEventPublisher); |
|
authenticationEventPublisher.setAdditionalExceptionMappings(mapping); |
|
return authenticationEventPublisher; |
|
} |
|
---- |
|
|
|
Kotlin:: |
|
+ |
|
[source,kotlin,role="secondary"] |
|
---- |
|
@Bean |
|
fun authenticationEventPublisher |
|
(applicationEventPublisher: ApplicationEventPublisher?): AuthenticationEventPublisher { |
|
val mapping: Map<Class<out AuthenticationException>, Class<out AbstractAuthenticationFailureEvent>> = |
|
mapOf(Pair(FooException::class.java, FooEvent::class.java)) |
|
val authenticationEventPublisher = DefaultAuthenticationEventPublisher(applicationEventPublisher) |
|
authenticationEventPublisher.setAdditionalExceptionMappings(mapping) |
|
return authenticationEventPublisher |
|
} |
|
---- |
|
====== |
|
|
|
== Default Event |
|
|
|
You can also supply a catch-all event to fire in the case of any `AuthenticationException`: |
|
|
|
[tabs] |
|
====== |
|
Java:: |
|
+ |
|
[source,java,role="primary"] |
|
---- |
|
@Bean |
|
public AuthenticationEventPublisher authenticationEventPublisher |
|
(ApplicationEventPublisher applicationEventPublisher) { |
|
DefaultAuthenticationEventPublisher authenticationEventPublisher = |
|
new DefaultAuthenticationEventPublisher(applicationEventPublisher); |
|
authenticationEventPublisher.setDefaultAuthenticationFailureEvent |
|
(AbstractAuthenticationFailureEvent.class); |
|
return authenticationEventPublisher; |
|
} |
|
---- |
|
|
|
Kotlin:: |
|
+ |
|
[source,kotlin,role="secondary"] |
|
---- |
|
@Bean |
|
fun authenticationEventPublisher |
|
(applicationEventPublisher: ApplicationEventPublisher?): AuthenticationEventPublisher { |
|
val authenticationEventPublisher = DefaultAuthenticationEventPublisher(applicationEventPublisher) |
|
authenticationEventPublisher.setDefaultAuthenticationFailureEvent(AbstractAuthenticationFailureEvent::class.java) |
|
return authenticationEventPublisher |
|
} |
|
---- |
|
======
|
|
|