Skip to content

Commit 1906075

Browse files
committed
OAuth2DeviceVerificationEndpointFilter is applied after AuthorizationFilter
Closes gh-18873
1 parent e8e0da1 commit 1906075

6 files changed

Lines changed: 18 additions & 39 deletions

File tree

config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2DeviceVerificationEndpointConfigurer.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@
4040
import org.springframework.security.oauth2.server.authorization.web.OAuth2DeviceVerificationEndpointFilter;
4141
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2DeviceAuthorizationConsentAuthenticationConverter;
4242
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2DeviceVerificationAuthenticationConverter;
43+
import org.springframework.security.web.access.intercept.AuthorizationFilter;
4344
import org.springframework.security.web.authentication.AuthenticationConverter;
4445
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
4546
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
4647
import org.springframework.security.web.authentication.DelegatingAuthenticationConverter;
47-
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
4848
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
4949
import org.springframework.security.web.util.matcher.OrRequestMatcher;
5050
import org.springframework.security.web.util.matcher.RequestMatcher;
@@ -279,8 +279,7 @@ public void configure(HttpSecurity builder) {
279279
if (StringUtils.hasText(this.consentPage)) {
280280
deviceVerificationEndpointFilter.setConsentPage(this.consentPage);
281281
}
282-
builder.addFilterBefore(postProcess(deviceVerificationEndpointFilter),
283-
AbstractPreAuthenticatedProcessingFilter.class);
282+
builder.addFilterAfter(postProcess(deviceVerificationEndpointFilter), AuthorizationFilter.class);
284283
}
285284

286285
@Override

config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2DeviceCodeGrantTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ public void requestWhenDeviceVerificationRequestValidThenDisplaysConsentPage() t
359359
}
360360

361361
@Test
362-
public void requestWhenDeviceAuthorizationConsentRequestUnauthenticatedThenBadRequest() throws Exception {
362+
public void requestWhenDeviceAuthorizationConsentRequestUnauthenticatedThenUnauthorized() throws Exception {
363363
this.spring.register(AuthorizationServerConfiguration.class).autowire();
364364

365365
// @formatter:off
@@ -392,7 +392,7 @@ public void requestWhenDeviceAuthorizationConsentRequestUnauthenticatedThenBadRe
392392
// @formatter:off
393393
this.mvc.perform(post(DEFAULT_DEVICE_VERIFICATION_ENDPOINT_URI)
394394
.params(parameters))
395-
.andExpect(status().isBadRequest());
395+
.andExpect(status().isUnauthorized());
396396
// @formatter:on
397397
}
398398

oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2DeviceVerificationAuthenticationProvider.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,7 @@ public Authentication authenticate(Authentication authentication) throws Authent
132132
if (this.logger.isTraceEnabled()) {
133133
this.logger.trace("Did not authenticate device verification request since principal not authenticated");
134134
}
135-
// Return the device verification request as-is where isAuthenticated() is
136-
// false
137-
return deviceVerificationAuthentication;
135+
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_REQUEST);
138136
}
139137

140138
RegisteredClient registeredClient = this.registeredClientRepository

oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2DeviceVerificationEndpointFilter.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -161,15 +161,6 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
161161
}
162162

163163
Authentication authenticationResult = this.authenticationManager.authenticate(authentication);
164-
if (!authenticationResult.isAuthenticated()) {
165-
// If the Principal (Resource Owner) is not authenticated then pass
166-
// through the chain
167-
// with the expectation that the authentication process will commence via
168-
// AuthenticationEntryPoint
169-
filterChain.doFilter(request, response);
170-
return;
171-
}
172-
173164
if (authenticationResult instanceof OAuth2DeviceAuthorizationConsentAuthenticationToken) {
174165
if (this.logger.isTraceEnabled()) {
175166
this.logger.trace("Device authorization consent is required");

oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2DeviceVerificationAuthenticationProviderTests.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ public void authenticateWhenUserCodeIsExpiredAndNotInvalidatedThenThrowOAuth2Aut
227227
}
228228

229229
@Test
230-
public void authenticateWhenPrincipalNotAuthenticatedThenReturnUnauthenticated() {
230+
public void authenticateWhenPrincipalNotAuthenticatedThenThrowOAuth2AuthenticationException() {
231231
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
232232
// @formatter:off
233233
OAuth2Authorization authorization = TestOAuth2Authorizations
@@ -237,15 +237,21 @@ public void authenticateWhenPrincipalNotAuthenticatedThenReturnUnauthenticated()
237237
.attribute(OAuth2ParameterNames.SCOPE, registeredClient.getScopes())
238238
.build();
239239
// @formatter:on
240-
TestingAuthenticationToken principal = new TestingAuthenticationToken("user", null);
240+
TestingAuthenticationToken principal = new TestingAuthenticationToken("anonymous", null);
241+
principal.setAuthenticated(false);
241242
Authentication authentication = new OAuth2DeviceVerificationAuthenticationToken(principal, USER_CODE,
242243
Collections.emptyMap());
243-
given(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).willReturn(authorization);
244+
given(this.authorizationService.findByToken(eq(USER_CODE),
245+
eq(OAuth2DeviceVerificationAuthenticationProvider.USER_CODE_TOKEN_TYPE)))
246+
.willReturn(authorization);
244247

245-
OAuth2DeviceVerificationAuthenticationToken authenticationResult = (OAuth2DeviceVerificationAuthenticationToken) this.authenticationProvider
246-
.authenticate(authentication);
247-
assertThat(authenticationResult).isEqualTo(authentication);
248-
assertThat(authenticationResult.isAuthenticated()).isFalse();
248+
// @formatter:off
249+
assertThatExceptionOfType(OAuth2AuthenticationException.class)
250+
.isThrownBy(() -> this.authenticationProvider.authenticate(authentication))
251+
.extracting(OAuth2AuthenticationException::getError)
252+
.extracting(OAuth2Error::getErrorCode)
253+
.isEqualTo(OAuth2ErrorCodes.INVALID_REQUEST);
254+
// @formatter:on
249255

250256
verify(this.authorizationService).findByToken(USER_CODE,
251257
OAuth2DeviceVerificationAuthenticationProvider.USER_CODE_TOKEN_TYPE);

oauth2/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/OAuth2DeviceVerificationEndpointFilterTests.java

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -166,21 +166,6 @@ public void doFilterWhenNotDeviceVerificationRequestThenNotProcessed() throws Ex
166166
verifyNoInteractions(this.authenticationManager);
167167
}
168168

169-
@Test
170-
public void doFilterWhenUnauthenticatedThenPassThrough() throws Exception {
171-
TestingAuthenticationToken unauthenticatedResult = new TestingAuthenticationToken("user", null);
172-
given(this.authenticationManager.authenticate(any(Authentication.class))).willReturn(unauthenticatedResult);
173-
174-
MockHttpServletRequest request = createRequest();
175-
request.addParameter(OAuth2ParameterNames.USER_CODE, USER_CODE);
176-
updateQueryString(request);
177-
MockHttpServletResponse response = new MockHttpServletResponse();
178-
FilterChain filterChain = mock(FilterChain.class);
179-
this.filter.doFilter(request, response, filterChain);
180-
verify(this.authenticationManager).authenticate(any(Authentication.class));
181-
verify(filterChain).doFilter(request, response);
182-
}
183-
184169
@Test
185170
public void doFilterWhenDeviceAuthorizationConsentRequestThenSuccess() throws Exception {
186171
Authentication authenticationResult = createDeviceVerificationAuthentication();

0 commit comments

Comments
 (0)