Merge branch '7.0.x'

This commit is contained in:
Joe Grandja 2026-03-10 15:59:29 -04:00
commit 703ffaf143
6 changed files with 18 additions and 39 deletions

View File

@ -40,11 +40,11 @@ import org.springframework.security.oauth2.server.authorization.settings.Authori
import org.springframework.security.oauth2.server.authorization.web.OAuth2DeviceVerificationEndpointFilter;
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2DeviceAuthorizationConsentAuthenticationConverter;
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2DeviceVerificationAuthenticationConverter;
import org.springframework.security.web.access.intercept.AuthorizationFilter;
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.DelegatingAuthenticationConverter;
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
@ -279,8 +279,7 @@ public final class OAuth2DeviceVerificationEndpointConfigurer extends AbstractOA
if (StringUtils.hasText(this.consentPage)) {
deviceVerificationEndpointFilter.setConsentPage(this.consentPage);
}
builder.addFilterBefore(postProcess(deviceVerificationEndpointFilter),
AbstractPreAuthenticatedProcessingFilter.class);
builder.addFilterAfter(postProcess(deviceVerificationEndpointFilter), AuthorizationFilter.class);
}
@Override

View File

@ -359,7 +359,7 @@ public class OAuth2DeviceCodeGrantTests {
}
@Test
public void requestWhenDeviceAuthorizationConsentRequestUnauthenticatedThenBadRequest() throws Exception {
public void requestWhenDeviceAuthorizationConsentRequestUnauthenticatedThenUnauthorized() throws Exception {
this.spring.register(AuthorizationServerConfiguration.class).autowire();
// @formatter:off
@ -392,7 +392,7 @@ public class OAuth2DeviceCodeGrantTests {
// @formatter:off
this.mvc.perform(post(DEFAULT_DEVICE_VERIFICATION_ENDPOINT_URI)
.params(parameters))
.andExpect(status().isBadRequest());
.andExpect(status().isUnauthorized());
// @formatter:on
}

View File

@ -132,9 +132,7 @@ public final class OAuth2DeviceVerificationAuthenticationProvider implements Aut
if (this.logger.isTraceEnabled()) {
this.logger.trace("Did not authenticate device verification request since principal not authenticated");
}
// Return the device verification request as-is where isAuthenticated() is
// false
return deviceVerificationAuthentication;
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_REQUEST);
}
RegisteredClient registeredClient = this.registeredClientRepository

View File

@ -161,15 +161,6 @@ public final class OAuth2DeviceVerificationEndpointFilter extends OncePerRequest
}
Authentication authenticationResult = this.authenticationManager.authenticate(authentication);
if (!authenticationResult.isAuthenticated()) {
// If the Principal (Resource Owner) is not authenticated then pass
// through the chain
// with the expectation that the authentication process will commence via
// AuthenticationEntryPoint
filterChain.doFilter(request, response);
return;
}
if (authenticationResult instanceof OAuth2DeviceAuthorizationConsentAuthenticationToken) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Device authorization consent is required");

View File

@ -227,7 +227,7 @@ public class OAuth2DeviceVerificationAuthenticationProviderTests {
}
@Test
public void authenticateWhenPrincipalNotAuthenticatedThenReturnUnauthenticated() {
public void authenticateWhenPrincipalNotAuthenticatedThenThrowOAuth2AuthenticationException() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
// @formatter:off
OAuth2Authorization authorization = TestOAuth2Authorizations
@ -237,15 +237,21 @@ public class OAuth2DeviceVerificationAuthenticationProviderTests {
.attribute(OAuth2ParameterNames.SCOPE, registeredClient.getScopes())
.build();
// @formatter:on
TestingAuthenticationToken principal = new TestingAuthenticationToken("user", null);
TestingAuthenticationToken principal = new TestingAuthenticationToken("anonymous", null);
principal.setAuthenticated(false);
Authentication authentication = new OAuth2DeviceVerificationAuthenticationToken(principal, USER_CODE,
Collections.emptyMap());
given(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).willReturn(authorization);
given(this.authorizationService.findByToken(eq(USER_CODE),
eq(OAuth2DeviceVerificationAuthenticationProvider.USER_CODE_TOKEN_TYPE)))
.willReturn(authorization);
OAuth2DeviceVerificationAuthenticationToken authenticationResult = (OAuth2DeviceVerificationAuthenticationToken) this.authenticationProvider
.authenticate(authentication);
assertThat(authenticationResult).isEqualTo(authentication);
assertThat(authenticationResult.isAuthenticated()).isFalse();
// @formatter:off
assertThatExceptionOfType(OAuth2AuthenticationException.class)
.isThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.extracting(OAuth2AuthenticationException::getError)
.extracting(OAuth2Error::getErrorCode)
.isEqualTo(OAuth2ErrorCodes.INVALID_REQUEST);
// @formatter:on
verify(this.authorizationService).findByToken(USER_CODE,
OAuth2DeviceVerificationAuthenticationProvider.USER_CODE_TOKEN_TYPE);

View File

@ -166,21 +166,6 @@ public class OAuth2DeviceVerificationEndpointFilterTests {
verifyNoInteractions(this.authenticationManager);
}
@Test
public void doFilterWhenUnauthenticatedThenPassThrough() throws Exception {
TestingAuthenticationToken unauthenticatedResult = new TestingAuthenticationToken("user", null);
given(this.authenticationManager.authenticate(any(Authentication.class))).willReturn(unauthenticatedResult);
MockHttpServletRequest request = createRequest();
request.addParameter(OAuth2ParameterNames.USER_CODE, USER_CODE);
updateQueryString(request);
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain filterChain = mock(FilterChain.class);
this.filter.doFilter(request, response, filterChain);
verify(this.authenticationManager).authenticate(any(Authentication.class));
verify(filterChain).doFilter(request, response);
}
@Test
public void doFilterWhenDeviceAuthorizationConsentRequestThenSuccess() throws Exception {
Authentication authenticationResult = createDeviceVerificationAuthentication();