|
|
|
@ -1,5 +1,5 @@ |
|
|
|
/* |
|
|
|
/* |
|
|
|
* Copyright 2020-2022 the original author or authors. |
|
|
|
* Copyright 2020-2024 the original author or authors. |
|
|
|
* |
|
|
|
* |
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
@ -15,33 +15,23 @@ |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
package org.springframework.security.oauth2.server.authorization.web; |
|
|
|
package org.springframework.security.oauth2.server.authorization.web; |
|
|
|
|
|
|
|
|
|
|
|
import java.time.Duration; |
|
|
|
|
|
|
|
import java.time.Instant; |
|
|
|
|
|
|
|
import java.util.Arrays; |
|
|
|
|
|
|
|
import java.util.HashSet; |
|
|
|
|
|
|
|
import java.util.function.Consumer; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import jakarta.servlet.FilterChain; |
|
|
|
import jakarta.servlet.FilterChain; |
|
|
|
import jakarta.servlet.http.HttpServletRequest; |
|
|
|
import jakarta.servlet.http.HttpServletRequest; |
|
|
|
import jakarta.servlet.http.HttpServletResponse; |
|
|
|
import jakarta.servlet.http.HttpServletResponse; |
|
|
|
import org.junit.jupiter.api.AfterEach; |
|
|
|
import org.junit.jupiter.api.AfterEach; |
|
|
|
import org.junit.jupiter.api.BeforeEach; |
|
|
|
import org.junit.jupiter.api.BeforeEach; |
|
|
|
import org.junit.jupiter.api.Test; |
|
|
|
import org.junit.jupiter.api.Test; |
|
|
|
|
|
|
|
|
|
|
|
import org.springframework.http.HttpStatus; |
|
|
|
import org.springframework.http.HttpStatus; |
|
|
|
import org.springframework.http.converter.HttpMessageConverter; |
|
|
|
import org.springframework.http.converter.HttpMessageConverter; |
|
|
|
import org.springframework.mock.http.client.MockClientHttpResponse; |
|
|
|
import org.springframework.mock.http.client.MockClientHttpResponse; |
|
|
|
import org.springframework.mock.web.MockHttpServletRequest; |
|
|
|
import org.springframework.mock.web.MockHttpServletRequest; |
|
|
|
import org.springframework.mock.web.MockHttpServletResponse; |
|
|
|
import org.springframework.mock.web.MockHttpServletResponse; |
|
|
|
|
|
|
|
import org.springframework.security.authentication.AuthenticationDetailsSource; |
|
|
|
import org.springframework.security.authentication.AuthenticationManager; |
|
|
|
import org.springframework.security.authentication.AuthenticationManager; |
|
|
|
import org.springframework.security.core.Authentication; |
|
|
|
import org.springframework.security.core.Authentication; |
|
|
|
import org.springframework.security.core.context.SecurityContext; |
|
|
|
import org.springframework.security.core.context.SecurityContext; |
|
|
|
import org.springframework.security.core.context.SecurityContextHolder; |
|
|
|
import org.springframework.security.core.context.SecurityContextHolder; |
|
|
|
import org.springframework.security.oauth2.core.ClientAuthenticationMethod; |
|
|
|
import org.springframework.security.oauth2.core.*; |
|
|
|
import org.springframework.security.oauth2.core.OAuth2AccessToken; |
|
|
|
|
|
|
|
import org.springframework.security.oauth2.core.OAuth2AuthenticationException; |
|
|
|
|
|
|
|
import org.springframework.security.oauth2.core.OAuth2Error; |
|
|
|
|
|
|
|
import org.springframework.security.oauth2.core.OAuth2ErrorCodes; |
|
|
|
|
|
|
|
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; |
|
|
|
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; |
|
|
|
import org.springframework.security.oauth2.core.http.converter.OAuth2ErrorHttpMessageConverter; |
|
|
|
import org.springframework.security.oauth2.core.http.converter.OAuth2ErrorHttpMessageConverter; |
|
|
|
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType; |
|
|
|
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType; |
|
|
|
@ -52,14 +42,19 @@ import org.springframework.security.oauth2.server.authorization.client.TestRegis |
|
|
|
import org.springframework.security.web.authentication.AuthenticationConverter; |
|
|
|
import org.springframework.security.web.authentication.AuthenticationConverter; |
|
|
|
import org.springframework.security.web.authentication.AuthenticationFailureHandler; |
|
|
|
import org.springframework.security.web.authentication.AuthenticationFailureHandler; |
|
|
|
import org.springframework.security.web.authentication.AuthenticationSuccessHandler; |
|
|
|
import org.springframework.security.web.authentication.AuthenticationSuccessHandler; |
|
|
|
|
|
|
|
import org.springframework.security.web.authentication.WebAuthenticationDetails; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import java.time.Duration; |
|
|
|
|
|
|
|
import java.time.Instant; |
|
|
|
|
|
|
|
import java.util.Arrays; |
|
|
|
|
|
|
|
import java.util.HashSet; |
|
|
|
|
|
|
|
import java.util.function.Consumer; |
|
|
|
|
|
|
|
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat; |
|
|
|
import static org.assertj.core.api.Assertions.assertThat; |
|
|
|
import static org.assertj.core.api.Assertions.assertThatThrownBy; |
|
|
|
import static org.assertj.core.api.Assertions.assertThatThrownBy; |
|
|
|
import static org.mockito.ArgumentMatchers.any; |
|
|
|
import static org.mockito.ArgumentMatchers.any; |
|
|
|
import static org.mockito.BDDMockito.given; |
|
|
|
import static org.mockito.BDDMockito.given; |
|
|
|
import static org.mockito.Mockito.mock; |
|
|
|
import static org.mockito.Mockito.*; |
|
|
|
import static org.mockito.Mockito.verify; |
|
|
|
|
|
|
|
import static org.mockito.Mockito.verifyNoInteractions; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Tests for {@link OAuth2TokenRevocationEndpointFilter}. |
|
|
|
* Tests for {@link OAuth2TokenRevocationEndpointFilter}. |
|
|
|
@ -102,6 +97,13 @@ public class OAuth2TokenRevocationEndpointFilterTests { |
|
|
|
.hasMessage("tokenRevocationEndpointUri cannot be empty"); |
|
|
|
.hasMessage("tokenRevocationEndpointUri cannot be empty"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
|
|
|
public void setAuthenticationDetailsSourceWhenNullThenThrowIllegalArgumentException() { |
|
|
|
|
|
|
|
assertThatThrownBy(() -> this.filter.setAuthenticationDetailsSource(null)) |
|
|
|
|
|
|
|
.isInstanceOf(IllegalArgumentException.class) |
|
|
|
|
|
|
|
.hasMessage("authenticationDetailsSource cannot be null"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void setAuthenticationConverterWhenNullThenThrowIllegalArgumentException() { |
|
|
|
public void setAuthenticationConverterWhenNullThenThrowIllegalArgumentException() { |
|
|
|
assertThatThrownBy(() -> this.filter.setAuthenticationConverter(null)) |
|
|
|
assertThatThrownBy(() -> this.filter.setAuthenticationConverter(null)) |
|
|
|
@ -198,6 +200,40 @@ public class OAuth2TokenRevocationEndpointFilterTests { |
|
|
|
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value()); |
|
|
|
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
|
|
|
public void doFilterWhenCustomAuthenticationDetailsSourceThenUsed() throws Exception { |
|
|
|
|
|
|
|
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build(); |
|
|
|
|
|
|
|
Authentication clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient, |
|
|
|
|
|
|
|
ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MockHttpServletRequest request = createTokenRevocationRequest(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> authenticationDetailsSource = mock( |
|
|
|
|
|
|
|
AuthenticationDetailsSource.class); |
|
|
|
|
|
|
|
WebAuthenticationDetails webAuthenticationDetails = new WebAuthenticationDetails(request); |
|
|
|
|
|
|
|
given(authenticationDetailsSource.buildDetails(any())).willReturn(webAuthenticationDetails); |
|
|
|
|
|
|
|
this.filter.setAuthenticationDetailsSource(authenticationDetailsSource); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "token", |
|
|
|
|
|
|
|
Instant.now(), Instant.now().plus(Duration.ofHours(1)), |
|
|
|
|
|
|
|
new HashSet<>(Arrays.asList("scope1", "scope2"))); |
|
|
|
|
|
|
|
OAuth2TokenRevocationAuthenticationToken tokenRevocationAuthentication = new OAuth2TokenRevocationAuthenticationToken( |
|
|
|
|
|
|
|
accessToken, clientPrincipal); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
given(this.authenticationManager.authenticate(any())).willReturn(tokenRevocationAuthentication); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SecurityContext securityContext = SecurityContextHolder.createEmptyContext(); |
|
|
|
|
|
|
|
securityContext.setAuthentication(clientPrincipal); |
|
|
|
|
|
|
|
SecurityContextHolder.setContext(securityContext); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MockHttpServletResponse response = new MockHttpServletResponse(); |
|
|
|
|
|
|
|
FilterChain filterChain = mock(FilterChain.class); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.filter.doFilter(request, response, filterChain); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
verify(authenticationDetailsSource).buildDetails(any()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void doFilterWhenCustomAuthenticationConverterThenUsed() throws Exception { |
|
|
|
public void doFilterWhenCustomAuthenticationConverterThenUsed() throws Exception { |
|
|
|
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build(); |
|
|
|
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build(); |
|
|
|
|