mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-05-30 16:52:13 +00:00
Provide Authentication to AuthenticationExceptions
Issue gh-16444
This commit is contained in:
parent
464e506429
commit
56e757a2a1
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -26,6 +26,7 @@ import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@ -58,6 +59,7 @@ public class DelegatingReactiveAuthenticationManager implements ReactiveAuthenti
|
||||
public Mono<Authentication> authenticate(Authentication authentication) {
|
||||
Flux<ReactiveAuthenticationManager> result = Flux.fromIterable(this.delegates);
|
||||
Function<ReactiveAuthenticationManager, Mono<Authentication>> logging = (m) -> m.authenticate(authentication)
|
||||
.doOnError(AuthenticationException.class, (ex) -> ex.setAuthenticationRequest(authentication))
|
||||
.doOnError(this.logger::debug);
|
||||
|
||||
return ((this.continueOnError) ? result.concatMapDelayError(logging) : result.concatMap(logging)).next();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -202,6 +202,7 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar
|
||||
throw ex;
|
||||
}
|
||||
catch (AuthenticationException ex) {
|
||||
ex.setAuthenticationRequest(authentication);
|
||||
logger.debug(LogMessage.format("Authentication failed with provider %s since %s",
|
||||
provider.getClass().getSimpleName(), ex.getMessage()));
|
||||
lastException = ex;
|
||||
@ -265,6 +266,7 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void prepareException(AuthenticationException ex, Authentication auth) {
|
||||
ex.setAuthenticationRequest(auth);
|
||||
this.eventPublisher.publishAuthenticationFailure(ex, auth);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -26,6 +26,7 @@ import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
@ -108,6 +109,15 @@ public class DelegatingReactiveAuthenticationManagerTests {
|
||||
assertThat(manager.authenticate(this.authentication).block()).isEqualTo(this.authentication);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenAccountStatusExceptionThenAuthenticationRequestIsIncluded() {
|
||||
AuthenticationException expected = new LockedException("");
|
||||
given(this.delegate1.authenticate(any())).willReturn(Mono.error(expected));
|
||||
ReactiveAuthenticationManager manager = new DelegatingReactiveAuthenticationManager(this.delegate1);
|
||||
StepVerifier.create(manager.authenticate(this.authentication)).expectError(LockedException.class).verify();
|
||||
assertThat(expected.getAuthenticationRequest()).isEqualTo(this.authentication);
|
||||
}
|
||||
|
||||
private DelegatingReactiveAuthenticationManager managerWithContinueOnError() {
|
||||
DelegatingReactiveAuthenticationManager manager = new DelegatingReactiveAuthenticationManager(this.delegate1,
|
||||
this.delegate2);
|
||||
|
@ -253,6 +253,34 @@ public class ProviderManagerTests {
|
||||
verify(publisher).publishAuthenticationFailure(expected, authReq);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenAccountStatusExceptionThenAuthenticationRequestIsIncluded() {
|
||||
AuthenticationException expected = new LockedException("");
|
||||
ProviderManager mgr = new ProviderManager(createProviderWhichThrows(expected));
|
||||
Authentication authReq = mock(Authentication.class);
|
||||
assertThatExceptionOfType(LockedException.class).isThrownBy(() -> mgr.authenticate(authReq));
|
||||
assertThat(expected.getAuthenticationRequest()).isEqualTo(authReq);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenInternalServiceAuthenticationExceptionThenAuthenticationRequestIsIncluded() {
|
||||
AuthenticationException expected = new InternalAuthenticationServiceException("");
|
||||
ProviderManager mgr = new ProviderManager(createProviderWhichThrows(expected));
|
||||
Authentication authReq = mock(Authentication.class);
|
||||
assertThatExceptionOfType(InternalAuthenticationServiceException.class)
|
||||
.isThrownBy(() -> mgr.authenticate(authReq));
|
||||
assertThat(expected.getAuthenticationRequest()).isEqualTo(authReq);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenAuthenticationExceptionThenAuthenticationRequestIsIncluded() {
|
||||
AuthenticationException expected = new BadCredentialsException("");
|
||||
ProviderManager mgr = new ProviderManager(createProviderWhichThrows(expected));
|
||||
Authentication authReq = mock(Authentication.class);
|
||||
assertThatExceptionOfType(BadCredentialsException.class).isThrownBy(() -> mgr.authenticate(authReq));
|
||||
assertThat(expected.getAuthenticationRequest()).isEqualTo(authReq);
|
||||
}
|
||||
|
||||
// SEC-2367
|
||||
@Test
|
||||
void providerThrowsInternalAuthenticationServiceException() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -176,9 +176,17 @@ public final class JwtIssuerAuthenticationManagerResolver implements Authenticat
|
||||
String issuer = this.issuerConverter.convert(token);
|
||||
AuthenticationManager authenticationManager = this.issuerAuthenticationManagerResolver.resolve(issuer);
|
||||
if (authenticationManager == null) {
|
||||
throw new InvalidBearerTokenException("Invalid issuer");
|
||||
AuthenticationException ex = new InvalidBearerTokenException("Invalid issuer");
|
||||
ex.setAuthenticationRequest(authentication);
|
||||
throw ex;
|
||||
}
|
||||
try {
|
||||
return authenticationManager.authenticate(authentication);
|
||||
}
|
||||
catch (AuthenticationException ex) {
|
||||
ex.setAuthenticationRequest(authentication);
|
||||
throw ex;
|
||||
}
|
||||
return authenticationManager.authenticate(authentication);
|
||||
}
|
||||
|
||||
}
|
||||
@ -194,10 +202,14 @@ public final class JwtIssuerAuthenticationManagerResolver implements Authenticat
|
||||
return issuer;
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new InvalidBearerTokenException(ex.getMessage(), ex);
|
||||
catch (Exception cause) {
|
||||
AuthenticationException ex = new InvalidBearerTokenException(cause.getMessage(), cause);
|
||||
ex.setAuthenticationRequest(authentication);
|
||||
throw ex;
|
||||
}
|
||||
throw new InvalidBearerTokenException("Missing issuer");
|
||||
AuthenticationException ex = new InvalidBearerTokenException("Missing issuer");
|
||||
ex.setAuthenticationRequest(authentication);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -36,6 +36,7 @@ import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.ReactiveAuthenticationManager;
|
||||
import org.springframework.security.authentication.ReactiveAuthenticationManagerResolver;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.jwt.ReactiveJwtDecoders;
|
||||
import org.springframework.security.oauth2.server.resource.InvalidBearerTokenException;
|
||||
@ -181,8 +182,13 @@ public final class JwtIssuerReactiveAuthenticationManagerResolver
|
||||
BearerTokenAuthenticationToken token = (BearerTokenAuthenticationToken) authentication;
|
||||
return this.issuerConverter.convert(token)
|
||||
.flatMap((issuer) -> this.issuerAuthenticationManagerResolver.resolve(issuer)
|
||||
.switchIfEmpty(Mono.error(() -> new InvalidBearerTokenException("Invalid issuer " + issuer))))
|
||||
.flatMap((manager) -> manager.authenticate(authentication));
|
||||
.switchIfEmpty(Mono.error(() -> {
|
||||
AuthenticationException ex = new InvalidBearerTokenException("Invalid issuer " + issuer);
|
||||
ex.setAuthenticationRequest(authentication);
|
||||
return ex;
|
||||
})))
|
||||
.flatMap((manager) -> manager.authenticate(authentication))
|
||||
.doOnError(AuthenticationException.class, (ex) -> ex.setAuthenticationRequest(authentication));
|
||||
}
|
||||
|
||||
}
|
||||
@ -194,12 +200,18 @@ public final class JwtIssuerReactiveAuthenticationManagerResolver
|
||||
try {
|
||||
String issuer = JWTParser.parse(token.getToken()).getJWTClaimsSet().getIssuer();
|
||||
if (issuer == null) {
|
||||
throw new InvalidBearerTokenException("Missing issuer");
|
||||
AuthenticationException ex = new InvalidBearerTokenException("Missing issuer");
|
||||
ex.setAuthenticationRequest(token);
|
||||
throw ex;
|
||||
}
|
||||
return Mono.just(issuer);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
return Mono.error(() -> new InvalidBearerTokenException(ex.getMessage(), ex));
|
||||
catch (Exception cause) {
|
||||
return Mono.error(() -> {
|
||||
AuthenticationException ex = new InvalidBearerTokenException(cause.getMessage(), cause);
|
||||
ex.setAuthenticationRequest(token);
|
||||
return ex;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -37,14 +37,18 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationManagerResolver;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.jose.TestKeys;
|
||||
import org.springframework.security.oauth2.jwt.JwtClaimNames;
|
||||
import org.springframework.security.oauth2.server.resource.InvalidBearerTokenException;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtIssuerAuthenticationManagerResolver.TrustedIssuerJwtAuthenticationManagerResolver;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.mock;
|
||||
import static org.mockito.BDDMockito.verify;
|
||||
|
||||
@ -263,6 +267,19 @@ public class JwtIssuerAuthenticationManagerResolverTests {
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveWhenAuthenticationExceptionThenAuthenticationRequestIsIncluded() {
|
||||
Authentication authentication = new BearerTokenAuthenticationToken(this.jwt);
|
||||
AuthenticationException ex = new InvalidBearerTokenException("");
|
||||
AuthenticationManager manager = mock(AuthenticationManager.class);
|
||||
given(manager.authenticate(any())).willThrow(ex);
|
||||
JwtIssuerAuthenticationManagerResolver resolver = new JwtIssuerAuthenticationManagerResolver(
|
||||
(issuer) -> manager);
|
||||
assertThatExceptionOfType(InvalidBearerTokenException.class)
|
||||
.isThrownBy(() -> resolver.resolve(null).authenticate(authentication));
|
||||
assertThat(ex.getAuthenticationRequest()).isEqualTo(authentication);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void factoryWhenNullOrEmptyIssuersThenException() {
|
||||
assertThatIllegalArgumentException()
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -34,13 +34,16 @@ import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.security.authentication.ReactiveAuthenticationManager;
|
||||
import org.springframework.security.authentication.ReactiveAuthenticationManagerResolver;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.jose.TestKeys;
|
||||
import org.springframework.security.oauth2.jwt.JwtClaimNames;
|
||||
import org.springframework.security.oauth2.server.resource.InvalidBearerTokenException;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtIssuerReactiveAuthenticationManagerResolver.TrustedIssuerJwtAuthenticationManagerResolver;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@ -262,6 +265,20 @@ public class JwtIssuerReactiveAuthenticationManagerResolverTests {
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveWhenAuthenticationExceptionThenAuthenticationRequestIsIncluded() {
|
||||
Authentication authentication = new BearerTokenAuthenticationToken(this.jwt);
|
||||
AuthenticationException ex = new InvalidBearerTokenException("");
|
||||
ReactiveAuthenticationManager manager = mock(ReactiveAuthenticationManager.class);
|
||||
given(manager.authenticate(any())).willReturn(Mono.error(ex));
|
||||
JwtIssuerReactiveAuthenticationManagerResolver resolver = new JwtIssuerReactiveAuthenticationManagerResolver(
|
||||
(issuer) -> Mono.just(manager));
|
||||
StepVerifier.create(resolver.resolve(null).block().authenticate(authentication))
|
||||
.expectError(InvalidBearerTokenException.class)
|
||||
.verify();
|
||||
assertThat(ex.getAuthenticationRequest()).isEqualTo(authentication);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void factoryWhenNullOrEmptyIssuersThenException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2004-2022 the original author or authors.
|
||||
* Copyright 2004-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -194,10 +194,11 @@ public class ExceptionTranslationFilter extends GenericFilterBean implements Mes
|
||||
logger.trace(LogMessage.format("Sending %s to authentication entry point since access is denied",
|
||||
authentication), exception);
|
||||
}
|
||||
sendStartAuthentication(request, response, chain,
|
||||
new InsufficientAuthenticationException(
|
||||
this.messages.getMessage("ExceptionTranslationFilter.insufficientAuthentication",
|
||||
"Full authentication is required to access this resource")));
|
||||
AuthenticationException ex = new InsufficientAuthenticationException(
|
||||
this.messages.getMessage("ExceptionTranslationFilter.insufficientAuthentication",
|
||||
"Full authentication is required to access this resource"));
|
||||
ex.setAuthenticationRequest(authentication);
|
||||
sendStartAuthentication(request, response, chain, ex);
|
||||
}
|
||||
else {
|
||||
if (logger.isTraceEnabled()) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -27,6 +27,7 @@ import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationManagerResolver;
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcherEntry;
|
||||
@ -46,7 +47,9 @@ public final class RequestMatcherDelegatingAuthenticationManagerResolver
|
||||
private final List<RequestMatcherEntry<AuthenticationManager>> authenticationManagers;
|
||||
|
||||
private AuthenticationManager defaultAuthenticationManager = (authentication) -> {
|
||||
throw new AuthenticationServiceException("Cannot authenticate " + authentication);
|
||||
AuthenticationException ex = new AuthenticationServiceException("Cannot authenticate " + authentication);
|
||||
ex.setAuthenticationRequest(authentication);
|
||||
throw ex;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -26,6 +26,7 @@ import reactor.core.publisher.Mono;
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.authentication.ReactiveAuthenticationManager;
|
||||
import org.springframework.security.authentication.ReactiveAuthenticationManagerResolver;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager;
|
||||
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
|
||||
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcherEntry;
|
||||
@ -46,8 +47,11 @@ public final class ServerWebExchangeDelegatingReactiveAuthenticationManagerResol
|
||||
|
||||
private final List<ServerWebExchangeMatcherEntry<ReactiveAuthenticationManager>> authenticationManagers;
|
||||
|
||||
private ReactiveAuthenticationManager defaultAuthenticationManager = (authentication) -> Mono
|
||||
.error(new AuthenticationServiceException("Cannot authenticate " + authentication));
|
||||
private ReactiveAuthenticationManager defaultAuthenticationManager = (authentication) -> {
|
||||
AuthenticationException ex = new AuthenticationServiceException("Cannot authenticate " + authentication);
|
||||
ex.setAuthenticationRequest(authentication);
|
||||
return Mono.error(ex);
|
||||
};
|
||||
|
||||
/**
|
||||
* Construct an
|
||||
|
@ -101,6 +101,9 @@ public class ExceptionTranslationWebFilter implements WebFilter {
|
||||
AuthenticationException cause = new InsufficientAuthenticationException(
|
||||
"Full authentication is required to access this resource");
|
||||
AuthenticationException ex = new AuthenticationCredentialsNotFoundException("Not Authenticated", cause);
|
||||
if (authentication != null) {
|
||||
ex.setAuthenticationRequest(authentication);
|
||||
}
|
||||
return this.authenticationEntryPoint.commence(exchange, ex).then(Mono.empty());
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2004-2024 the original author or authors.
|
||||
* Copyright 2004-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -27,6 +27,7 @@ import jakarta.servlet.http.HttpSession;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
@ -38,6 +39,7 @@ import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.RememberMeAuthenticationToken;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
@ -107,6 +109,23 @@ public class ExceptionTranslationFilterTests {
|
||||
assertThat(response.getRedirectedUrl()).isEqualTo("/mycontext/login.jsp");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccessDeniedWhenAnonymousThenIncludesAuthenticationRequest() throws Exception {
|
||||
// Setup our HTTP request
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
FilterChain fc = mockFilterChainWithException(new AccessDeniedException(""));
|
||||
AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("ignored", "ignored",
|
||||
AuthorityUtils.createAuthorityList("IGNORED"));
|
||||
SecurityContextHolder.getContext().setAuthentication(token);
|
||||
AuthenticationEntryPoint entryPoint = mock(AuthenticationEntryPoint.class);
|
||||
ExceptionTranslationFilter filter = new ExceptionTranslationFilter(entryPoint);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
filter.doFilter(request, response, fc);
|
||||
ArgumentCaptor<AuthenticationException> ex = ArgumentCaptor.forClass(AuthenticationException.class);
|
||||
verify(entryPoint).commence(any(), any(), ex.capture());
|
||||
assertThat(ex.getValue().getAuthenticationRequest()).isEqualTo(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccessDeniedWithRememberMe() throws Exception {
|
||||
// Setup our HTTP request
|
||||
|
@ -21,6 +21,7 @@ import java.security.Principal;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import reactor.core.publisher.Mono;
|
||||
@ -31,6 +32,7 @@ import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.http.server.reactive.MockServerHttpResponse;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
@ -39,6 +41,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
@ -146,6 +149,17 @@ public class ExceptionTranslationWebFilterTests {
|
||||
this.entryPointPublisher.assertWasSubscribed();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterWhenAccessDeniedExceptionAndAnonymousAuthenticatedThenIncludesAuthenticationRequest() {
|
||||
given(this.entryPoint.commence(any(), any())).willReturn(this.entryPointPublisher.mono());
|
||||
given(this.exchange.getPrincipal()).willReturn(Mono.just(this.anonymousPrincipal));
|
||||
given(this.chain.filter(this.exchange)).willReturn(Mono.error(new AccessDeniedException("Not Authorized")));
|
||||
StepVerifier.create(this.filter.filter(this.exchange, this.chain)).expectComplete().verify();
|
||||
ArgumentCaptor<AuthenticationException> ex = ArgumentCaptor.forClass(AuthenticationException.class);
|
||||
verify(this.entryPoint).commence(any(), ex.capture());
|
||||
assertThat(ex.getValue().getAuthenticationRequest()).isEqualTo(this.anonymousPrincipal);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAccessDeniedHandlerWhenNullThenException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.filter.setAccessDeniedHandler(null));
|
||||
|
Loading…
x
Reference in New Issue
Block a user