Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 9dd5e28

Browse files
committedApr 22, 2025·
Merge branch '1.4.x'
2 parents 7e41e87 + f43dce3 commit 9dd5e28

File tree

3 files changed

+34
-62
lines changed

3 files changed

+34
-62
lines changed
 

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

Lines changed: 15 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2025 the original author or authors.
2+
* Copyright 2020-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -34,7 +34,6 @@
3434
import org.springframework.security.core.AuthenticationException;
3535
import org.springframework.security.core.context.SecurityContext;
3636
import org.springframework.security.core.context.SecurityContextHolder;
37-
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
3837
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
3938
import org.springframework.security.oauth2.core.OAuth2Error;
4039
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
@@ -54,7 +53,6 @@
5453
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
5554
import org.springframework.security.web.authentication.DelegatingAuthenticationConverter;
5655
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
57-
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
5856
import org.springframework.security.web.util.matcher.RequestMatcher;
5957
import org.springframework.util.Assert;
6058
import org.springframework.web.filter.OncePerRequestFilter;
@@ -92,8 +90,6 @@ public final class OAuth2ClientAuthenticationFilter extends OncePerRequestFilter
9290

9391
private final AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
9492

95-
private final BasicAuthenticationEntryPoint basicAuthenticationEntryPoint = new BasicAuthenticationEntryPoint();
96-
9793
private AuthenticationConverter authenticationConverter;
9894

9995
private AuthenticationSuccessHandler authenticationSuccessHandler = this::onAuthenticationSuccess;
@@ -114,7 +110,6 @@ public OAuth2ClientAuthenticationFilter(AuthenticationManager authenticationMana
114110
Assert.notNull(requestMatcher, "requestMatcher cannot be null");
115111
this.authenticationManager = authenticationManager;
116112
this.requestMatcher = requestMatcher;
117-
this.basicAuthenticationEntryPoint.setRealmName("default");
118113
// @formatter:off
119114
this.authenticationConverter = new DelegatingAuthenticationConverter(
120115
Arrays.asList(
@@ -135,9 +130,8 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
135130
return;
136131
}
137132

138-
Authentication authenticationRequest = null;
139133
try {
140-
authenticationRequest = this.authenticationConverter.convert(request);
134+
Authentication authenticationRequest = this.authenticationConverter.convert(request);
141135
if (authenticationRequest instanceof AbstractAuthenticationToken authenticationToken) {
142136
authenticationToken.setDetails(this.authenticationDetailsSource.buildDetails(request));
143137
}
@@ -153,14 +147,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
153147
if (this.logger.isTraceEnabled()) {
154148
this.logger.trace(LogMessage.format("Client authentication failed: %s", ex.getError()), ex);
155149
}
156-
if (authenticationRequest instanceof OAuth2ClientAuthenticationToken clientAuthentication) {
157-
this.authenticationFailureHandler.onAuthenticationFailure(request, response,
158-
new OAuth2ClientAuthenticationException(ex.getError(), ex, clientAuthentication));
159-
}
160-
else {
161-
this.authenticationFailureHandler.onAuthenticationFailure(request, response, ex);
162-
}
163-
150+
this.authenticationFailureHandler.onAuthenticationFailure(request, response, ex);
164151
}
165152
}
166153

@@ -212,21 +199,21 @@ private void onAuthenticationSuccess(HttpServletRequest request, HttpServletResp
212199
}
213200

214201
private void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
215-
AuthenticationException authenticationException) throws IOException {
202+
AuthenticationException exception) throws IOException {
216203

217204
SecurityContextHolder.clearContext();
218205

219-
if (authenticationException instanceof OAuth2ClientAuthenticationException clientAuthenticationException) {
220-
OAuth2ClientAuthenticationToken clientAuthentication = clientAuthenticationException
221-
.getClientAuthentication();
222-
if (ClientAuthenticationMethod.CLIENT_SECRET_BASIC
223-
.equals(clientAuthentication.getClientAuthenticationMethod())) {
224-
this.basicAuthenticationEntryPoint.commence(request, response, authenticationException);
225-
return;
226-
}
227-
}
228-
229-
OAuth2Error error = ((OAuth2AuthenticationException) authenticationException).getError();
206+
// TODO
207+
// The authorization server MAY return an HTTP 401 (Unauthorized) status code
208+
// to indicate which HTTP authentication schemes are supported.
209+
// If the client attempted to authenticate via the "Authorization" request header
210+
// field,
211+
// the authorization server MUST respond with an HTTP 401 (Unauthorized) status
212+
// code and
213+
// include the "WWW-Authenticate" response header field
214+
// matching the authentication scheme used by the client.
215+
216+
OAuth2Error error = ((OAuth2AuthenticationException) exception).getError();
230217
ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response);
231218
if (OAuth2ErrorCodes.INVALID_CLIENT.equals(error.getErrorCode())) {
232219
httpResponse.setStatusCode(HttpStatus.UNAUTHORIZED);
@@ -261,21 +248,4 @@ private static void validateClientIdentifier(Authentication authentication) {
261248
}
262249
}
263250

264-
private static final class OAuth2ClientAuthenticationException extends OAuth2AuthenticationException {
265-
266-
private final OAuth2ClientAuthenticationToken clientAuthentication;
267-
268-
private OAuth2ClientAuthenticationException(OAuth2Error error, Throwable cause,
269-
OAuth2ClientAuthenticationToken clientAuthentication) {
270-
super(error, cause);
271-
Assert.notNull(clientAuthentication, "clientAuthentication cannot be null");
272-
this.clientAuthentication = clientAuthentication;
273-
}
274-
275-
private OAuth2ClientAuthenticationToken getClientAuthentication() {
276-
return this.clientAuthentication;
277-
}
278-
279-
}
280-
281251
}

‎oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationCodeGrantTests.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2025 the original author or authors.
2+
* Copyright 2020-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -550,7 +550,7 @@ public void requestWhenPublicClientWithPkceAndEmptyCodeThenBadRequest() throws E
550550
}
551551

552552
@Test
553-
public void requestWhenConfidentialClientWithPkceAndMissingCodeVerifierThenUnauthorized() throws Exception {
553+
public void requestWhenConfidentialClientWithPkceAndMissingCodeVerifierThenBadRequest() throws Exception {
554554
this.spring.register(AuthorizationServerConfiguration.class).autowire();
555555

556556
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
@@ -581,7 +581,7 @@ public void requestWhenConfidentialClientWithPkceAndMissingCodeVerifierThenUnaut
581581
.params(getTokenRequestParameters(registeredClient, authorizationCodeAuthorization))
582582
.param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId())
583583
.header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(registeredClient)))
584-
.andExpect(status().isUnauthorized());
584+
.andExpect(status().isBadRequest());
585585
}
586586

587587
// gh-1011
@@ -613,7 +613,7 @@ public void requestWhenConfidentialClientWithPkceAndMissingCodeChallengeThenErro
613613
}
614614

615615
@Test
616-
public void requestWhenConfidentialClientWithPkceAndMissingCodeChallengeButCodeVerifierProvidedThenUnauthorized()
616+
public void requestWhenConfidentialClientWithPkceAndMissingCodeChallengeButCodeVerifierProvidedThenBadRequest()
617617
throws Exception {
618618
this.spring.register(AuthorizationServerConfiguration.class).autowire();
619619

@@ -643,7 +643,7 @@ public void requestWhenConfidentialClientWithPkceAndMissingCodeChallengeButCodeV
643643
.params(getTokenRequestParameters(registeredClient, authorizationCodeAuthorization))
644644
.param(PkceParameterNames.CODE_VERIFIER, S256_CODE_VERIFIER)
645645
.header(HttpHeaders.AUTHORIZATION, getAuthorizationHeader(registeredClient)))
646-
.andExpect(status().isUnauthorized());
646+
.andExpect(status().isBadRequest());
647647
}
648648

649649
@Test

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

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2025 the original author or authors.
2+
* Copyright 2020-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -26,7 +26,6 @@
2626
import org.junit.jupiter.api.Test;
2727
import org.mockito.ArgumentCaptor;
2828

29-
import org.springframework.http.HttpHeaders;
3029
import org.springframework.http.HttpMethod;
3130
import org.springframework.http.HttpStatus;
3231
import org.springframework.http.converter.HttpMessageConverter;
@@ -176,25 +175,26 @@ public void doFilterWhenRequestMatchesAndInvalidCredentialsThenInvalidRequestErr
176175

177176
// gh-889
178177
@Test
179-
public void doFilterWhenRequestMatchesAndClientIdContainsNonPrintableASCIIThenReturnChallenge() throws Exception {
178+
public void doFilterWhenRequestMatchesAndClientIdContainsNonPrintableASCIIThenInvalidRequestError()
179+
throws Exception {
180180
// Hex 00 -> null
181181
String clientId = new String(Hex.decode("00"), StandardCharsets.UTF_8);
182-
assertWhenInvalidClientIdThenReturnChallenge(clientId);
182+
assertWhenInvalidClientIdThenInvalidRequestError(clientId);
183183

184184
// Hex 0a61 -> line feed + a
185185
clientId = new String(Hex.decode("0a61"), StandardCharsets.UTF_8);
186-
assertWhenInvalidClientIdThenReturnChallenge(clientId);
186+
assertWhenInvalidClientIdThenInvalidRequestError(clientId);
187187

188188
// Hex 1b -> escape
189189
clientId = new String(Hex.decode("1b"), StandardCharsets.UTF_8);
190-
assertWhenInvalidClientIdThenReturnChallenge(clientId);
190+
assertWhenInvalidClientIdThenInvalidRequestError(clientId);
191191

192192
// Hex 1b61 -> escape + a
193193
clientId = new String(Hex.decode("1b61"), StandardCharsets.UTF_8);
194-
assertWhenInvalidClientIdThenReturnChallenge(clientId);
194+
assertWhenInvalidClientIdThenInvalidRequestError(clientId);
195195
}
196196

197-
private void assertWhenInvalidClientIdThenReturnChallenge(String clientId) throws Exception {
197+
private void assertWhenInvalidClientIdThenInvalidRequestError(String clientId) throws Exception {
198198
given(this.authenticationConverter.convert(any(HttpServletRequest.class)))
199199
.willReturn(new OAuth2ClientAuthenticationToken(clientId, ClientAuthenticationMethod.CLIENT_SECRET_BASIC,
200200
"secret", null));
@@ -210,12 +210,13 @@ private void assertWhenInvalidClientIdThenReturnChallenge(String clientId) throw
210210
verifyNoInteractions(this.authenticationManager);
211211

212212
assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull();
213-
assertThat(response.getStatus()).isEqualTo(HttpStatus.UNAUTHORIZED.value());
214-
assertThat(response.getHeader(HttpHeaders.WWW_AUTHENTICATE)).isEqualTo("Basic realm=\"default\"");
213+
assertThat(response.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST.value());
214+
OAuth2Error error = readError(response);
215+
assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_REQUEST);
215216
}
216217

217218
@Test
218-
public void doFilterWhenRequestMatchesAndBadCredentialsThenReturnChallenge() throws Exception {
219+
public void doFilterWhenRequestMatchesAndBadCredentialsThenInvalidClientError() throws Exception {
219220
given(this.authenticationConverter.convert(any(HttpServletRequest.class)))
220221
.willReturn(new OAuth2ClientAuthenticationToken("clientId", ClientAuthenticationMethod.CLIENT_SECRET_BASIC,
221222
"invalid-secret", null));
@@ -234,7 +235,8 @@ public void doFilterWhenRequestMatchesAndBadCredentialsThenReturnChallenge() thr
234235

235236
assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull();
236237
assertThat(response.getStatus()).isEqualTo(HttpStatus.UNAUTHORIZED.value());
237-
assertThat(response.getHeader(HttpHeaders.WWW_AUTHENTICATE)).isEqualTo("Basic realm=\"default\"");
238+
OAuth2Error error = readError(response);
239+
assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT);
238240
}
239241

240242
@Test

0 commit comments

Comments
 (0)
Please sign in to comment.