|
@@ -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");
|
|
|
* you may not use this file except in compliance with the License.
|
|
@@ -15,33 +15,23 @@
|
|
|
*/
|
|
|
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.http.HttpServletRequest;
|
|
|
import jakarta.servlet.http.HttpServletResponse;
|
|
|
import org.junit.jupiter.api.AfterEach;
|
|
|
import org.junit.jupiter.api.BeforeEach;
|
|
|
import org.junit.jupiter.api.Test;
|
|
|
-
|
|
|
import org.springframework.http.HttpStatus;
|
|
|
import org.springframework.http.converter.HttpMessageConverter;
|
|
|
import org.springframework.mock.http.client.MockClientHttpResponse;
|
|
|
import org.springframework.mock.web.MockHttpServletRequest;
|
|
|
import org.springframework.mock.web.MockHttpServletResponse;
|
|
|
+import org.springframework.security.authentication.AuthenticationDetailsSource;
|
|
|
import org.springframework.security.authentication.AuthenticationManager;
|
|
|
import org.springframework.security.core.Authentication;
|
|
|
import org.springframework.security.core.context.SecurityContext;
|
|
|
import org.springframework.security.core.context.SecurityContextHolder;
|
|
|
-import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
|
|
|
-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.*;
|
|
|
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
|
|
import org.springframework.security.oauth2.core.http.converter.OAuth2ErrorHttpMessageConverter;
|
|
|
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.AuthenticationFailureHandler;
|
|
|
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.assertThatThrownBy;
|
|
|
import static org.mockito.ArgumentMatchers.any;
|
|
|
import static org.mockito.BDDMockito.given;
|
|
|
-import static org.mockito.Mockito.mock;
|
|
|
-import static org.mockito.Mockito.verify;
|
|
|
-import static org.mockito.Mockito.verifyNoInteractions;
|
|
|
+import static org.mockito.Mockito.*;
|
|
|
|
|
|
/**
|
|
|
* Tests for {@link OAuth2TokenRevocationEndpointFilter}.
|
|
@@ -102,6 +97,13 @@ public class OAuth2TokenRevocationEndpointFilterTests {
|
|
|
.hasMessage("tokenRevocationEndpointUri cannot be empty");
|
|
|
}
|
|
|
|
|
|
+ @Test
|
|
|
+ public void setAuthenticationDetailsSourceWhenNullThenThrowIllegalArgumentException() {
|
|
|
+ assertThatThrownBy(() -> this.filter.setAuthenticationDetailsSource(null))
|
|
|
+ .isInstanceOf(IllegalArgumentException.class)
|
|
|
+ .hasMessage("authenticationDetailsSource cannot be null");
|
|
|
+ }
|
|
|
+
|
|
|
@Test
|
|
|
public void setAuthenticationConverterWhenNullThenThrowIllegalArgumentException() {
|
|
|
assertThatThrownBy(() -> this.filter.setAuthenticationConverter(null))
|
|
@@ -198,6 +200,40 @@ public class OAuth2TokenRevocationEndpointFilterTests {
|
|
|
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
|
|
|
public void doFilterWhenCustomAuthenticationConverterThenUsed() throws Exception {
|
|
|
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|