diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/events.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/events.adoc new file mode 100644 index 0000000000..2448fdff6d --- /dev/null +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/events.adoc @@ -0,0 +1,89 @@ +[[servlet-events]] +== Authentication Events + +For each authentication that succeeds or fails, a `AuthenticationSuccessEvent` or `AuthenticationFailureEvent` is fired, respectively. + +To listen for these events, you must first publish an `AuthenticationEventPublisher`. +Spring Security's `DefaultAuthenticationEventPublisher` will probably do fine: + +[source,java] +---- +@Bean +public AuthenticationEventPublisher authenticationEventPublisher + (ApplicationEventPublisher applicationEventPublisher) { + return new DefaultAuthenticationEventPublisher(applicationEventPublisher); +} +---- + +Then, you can use Spring's `@EventListener` support: + +[source,java] +---- +@Component +public class AuthenticationEvents { + @EventListener + public void onSuccess(AuthenticationSuccessEvent success) { + // ... + } + + @EventListener + public void onFailure(AuthenticationFailureEvent failures) { + // ... + } +} +---- + +While similar to `AuthenticationSuccessHandler` and `AuthenticationFailureHandler`, these are nice in that they can be used independently from the servlet API. + +=== Adding Exception Mappings + +`DefaultAuthenticationEventPublisher` by default will publish 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 won't also produce events. + +To that end, you may want to supply additional mappings to the publisher via the `setAdditionalExceptionMappings` method: + +[source,java] +---- +@Bean +public AuthenticationEventPublisher authenticationEventPublisher + (ApplicationEventPublisher applicationEventPublisher) { + Map, + Class> mapping = + Collections.singletonMap(FooException.class, FooEvent.class); + AuthenticationEventPublisher authenticationEventPublisher = + new DefaultAuthenticationEventPublisher(applicationEventPublisher); + authenticationEventPublisher.setAdditionalExceptionMappings(mapping); + return authenticationEventPublisher; +} +---- + +=== Default Event + +And, you can supply a catch-all event to fire in the case of any `AuthenticationException`: + +[source,java] +---- +@Bean +public AuthenticationEventPublisher authenticationEventPublisher + (ApplicationEventPublisher applicationEventPublisher) { + AuthenticationEventPublisher authenticationEventPublisher = + new DefaultAuthenticationEventPublisher(applicationEventPublisher); + authenticationEventPublisher.setDefaultAuthenticationFailureEvent + (GenericAuthenticationFailureEvent.class); + return authenticationEventPublisher; +} +---- diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/index.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/index.adoc index d45bbeea52..9536e950e6 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/index.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/index.adoc @@ -63,3 +63,4 @@ include::runas.adoc[] include::logout.adoc[] +include::events.adoc[] diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/oauth2/oauth2-resourceserver.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/oauth2/oauth2-resourceserver.adoc index 17da165d64..ae338e60e0 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/oauth2/oauth2-resourceserver.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/oauth2/oauth2-resourceserver.adoc @@ -1996,3 +1996,32 @@ RestTemplate rest() { return rest; } ---- + +[[oauth2resourceserver-bearertoken-failure]] +=== Bearer Token Failure + +A bearer token may be invalid for a number of reasons. For example, the token may no longer be active. + +In these circumstances, Resource Server throws an `InvalidBearerTokenException`. +Like other exceptions, this results in an OAuth 2.0 Bearer Token error response: + +[source,http request] +---- +HTTP/1.1 401 Unauthorized +WWW-Authenticate: Bearer error_code="invalid_token", error_description="Unsupported algorithm of none", error_uri="https://tools.ietf.org/html/rfc6750#section-3.1" +---- + +Additionally, it is published as an `AuthenticationFailureBadCredentialsEvent`, which you can <> like so: + +[source,java] +---- +@Component +public class FailureEvents { + @EventListener + public void onFailure(AuthenticationFailureEvent failure) { + if (badCredentials.getAuthentication() instanceof BearerTokenAuthenticationToken) { + // ... handle + } + } +} +----