|
16 | 16 | package org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization; |
17 | 17 |
|
18 | 18 | import java.net.URI; |
19 | | -import java.util.ArrayList; |
20 | 19 | import java.util.LinkedHashMap; |
21 | | -import java.util.List; |
22 | 20 | import java.util.Map; |
23 | 21 |
|
24 | | -import javax.servlet.AsyncContext; |
25 | | -import javax.servlet.ServletRequest; |
26 | | -import javax.servlet.ServletResponse; |
27 | | -import javax.servlet.http.HttpServletRequest; |
28 | | -import javax.servlet.http.HttpServletRequestWrapper; |
29 | | -import javax.servlet.http.HttpServletResponse; |
30 | | - |
31 | 22 | import com.nimbusds.jose.jwk.source.JWKSource; |
32 | 23 |
|
33 | | -import org.springframework.core.annotation.AnnotationUtils; |
34 | 24 | import org.springframework.http.HttpMethod; |
35 | 25 | import org.springframework.http.HttpStatus; |
36 | 26 | import org.springframework.security.config.Customizer; |
37 | 27 | import org.springframework.security.config.annotation.web.HttpSecurityBuilder; |
38 | 28 | import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; |
39 | 29 | import org.springframework.security.config.annotation.web.configurers.ExceptionHandlingConfigurer; |
40 | | -import org.springframework.security.core.Authentication; |
41 | | -import org.springframework.security.core.Transient; |
42 | | -import org.springframework.security.core.context.SecurityContext; |
43 | 30 | import org.springframework.security.oauth2.core.OAuth2Token; |
44 | 31 | import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService; |
45 | 32 | import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService; |
|
51 | 38 | import org.springframework.security.oauth2.server.authorization.web.ProviderContextFilter; |
52 | 39 | import org.springframework.security.web.authentication.HttpStatusEntryPoint; |
53 | 40 | import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; |
54 | | -import org.springframework.security.web.context.HttpRequestResponseHolder; |
55 | | -import org.springframework.security.web.context.HttpSessionSecurityContextRepository; |
56 | | -import org.springframework.security.web.context.SaveContextOnUpdateOrErrorResponseWrapper; |
57 | 41 | import org.springframework.security.web.context.SecurityContextPersistenceFilter; |
58 | | -import org.springframework.security.web.context.SecurityContextRepository; |
59 | 42 | import org.springframework.security.web.util.matcher.AntPathRequestMatcher; |
60 | 43 | import org.springframework.security.web.util.matcher.OrRequestMatcher; |
61 | 44 | import org.springframework.security.web.util.matcher.RequestMatcher; |
@@ -254,127 +237,6 @@ public void init(B builder) { |
254 | 237 | getRequestMatcher(OAuth2TokenRevocationEndpointConfigurer.class)) |
255 | 238 | ); |
256 | 239 | } |
257 | | - |
258 | | - // gh-482 |
259 | | - initSecurityContextRepository(builder); |
260 | | - } |
261 | | - |
262 | | - private void initSecurityContextRepository(B builder) { |
263 | | - // TODO This is a temporary fix and should be removed after upgrading to Spring Security 5.7.0 GA. |
264 | | - // |
265 | | - // See: |
266 | | - // Prevent Save @Transient Authentication with existing HttpSession |
267 | | - // https://github.com/spring-projects/spring-security/pull/9993 |
268 | | - |
269 | | - final SecurityContextRepository securityContextRepository = builder.getSharedObject(SecurityContextRepository.class); |
270 | | - if (!(securityContextRepository instanceof HttpSessionSecurityContextRepository)) { |
271 | | - return; |
272 | | - } |
273 | | - |
274 | | - SecurityContextRepository securityContextRepositoryTransientNotSaved = new SecurityContextRepository() { |
275 | | - |
276 | | - private final RequestMatcher clientAuthenticationRequestMatcher = initClientAuthenticationRequestMatcher(); |
277 | | - private final RequestMatcher jwtAuthenticationRequestMatcher = initJwtAuthenticationRequestMatcher(); |
278 | | - |
279 | | - @Override |
280 | | - public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) { |
281 | | - final HttpServletRequest unwrappedRequest = requestResponseHolder.getRequest(); |
282 | | - final HttpServletResponse unwrappedResponse = requestResponseHolder.getResponse(); |
283 | | - |
284 | | - SecurityContext securityContext = securityContextRepository.loadContext(requestResponseHolder); |
285 | | - |
286 | | - if (this.clientAuthenticationRequestMatcher.matches(unwrappedRequest) || |
287 | | - this.jwtAuthenticationRequestMatcher.matches(unwrappedRequest)) { |
288 | | - |
289 | | - final SaveContextOnUpdateOrErrorResponseWrapper transientAuthenticationResponseWrapper = |
290 | | - new SaveContextOnUpdateOrErrorResponseWrapper(unwrappedResponse, false) { |
291 | | - |
292 | | - @Override |
293 | | - protected void saveContext(SecurityContext context) { |
294 | | - // @Transient Authentication should not be saved |
295 | | - if (context.getAuthentication() != null) { |
296 | | - Assert.state(isTransientAuthentication(context.getAuthentication()), "Expected @Transient Authentication"); |
297 | | - } |
298 | | - } |
299 | | - |
300 | | - }; |
301 | | - // Override the default HttpSessionSecurityContextRepository.SaveToSessionResponseWrapper |
302 | | - requestResponseHolder.setResponse(transientAuthenticationResponseWrapper); |
303 | | - |
304 | | - final HttpServletRequestWrapper transientAuthenticationRequestWrapper = |
305 | | - new HttpServletRequestWrapper(unwrappedRequest) { |
306 | | - |
307 | | - @Override |
308 | | - public AsyncContext startAsync() { |
309 | | - transientAuthenticationResponseWrapper.disableSaveOnResponseCommitted(); |
310 | | - return super.startAsync(); |
311 | | - } |
312 | | - |
313 | | - @Override |
314 | | - public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) |
315 | | - throws IllegalStateException { |
316 | | - transientAuthenticationResponseWrapper.disableSaveOnResponseCommitted(); |
317 | | - return super.startAsync(servletRequest, servletResponse); |
318 | | - } |
319 | | - |
320 | | - }; |
321 | | - // Override the default HttpSessionSecurityContextRepository.SaveToSessionRequestWrapper |
322 | | - requestResponseHolder.setRequest(transientAuthenticationRequestWrapper); |
323 | | - } |
324 | | - |
325 | | - return securityContext; |
326 | | - } |
327 | | - |
328 | | - @Override |
329 | | - public void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response) { |
330 | | - Authentication authentication = context.getAuthentication(); |
331 | | - if (authentication == null || isTransientAuthentication(authentication)) { |
332 | | - return; |
333 | | - } |
334 | | - securityContextRepository.saveContext(context, request, response); |
335 | | - } |
336 | | - |
337 | | - @Override |
338 | | - public boolean containsContext(HttpServletRequest request) { |
339 | | - return securityContextRepository.containsContext(request); |
340 | | - } |
341 | | - |
342 | | - private boolean isTransientAuthentication(Authentication authentication) { |
343 | | - return AnnotationUtils.getAnnotation(authentication.getClass(), Transient.class) != null; |
344 | | - } |
345 | | - |
346 | | - private RequestMatcher initClientAuthenticationRequestMatcher() { |
347 | | - // OAuth2ClientAuthenticationToken is @Transient and is accepted by |
348 | | - // OAuth2TokenEndpointFilter, OAuth2TokenIntrospectionEndpointFilter and OAuth2TokenRevocationEndpointFilter |
349 | | - |
350 | | - List<RequestMatcher> requestMatchers = new ArrayList<>(); |
351 | | - requestMatchers.add(getRequestMatcher(OAuth2TokenEndpointConfigurer.class)); |
352 | | - requestMatchers.add(getRequestMatcher(OAuth2TokenIntrospectionEndpointConfigurer.class)); |
353 | | - requestMatchers.add(getRequestMatcher(OAuth2TokenRevocationEndpointConfigurer.class)); |
354 | | - return new OrRequestMatcher(requestMatchers); |
355 | | - } |
356 | | - |
357 | | - private RequestMatcher initJwtAuthenticationRequestMatcher() { |
358 | | - // JwtAuthenticationToken is @Transient and is accepted by |
359 | | - // OidcUserInfoEndpointFilter and OidcClientRegistrationEndpointFilter |
360 | | - |
361 | | - List<RequestMatcher> requestMatchers = new ArrayList<>(); |
362 | | - requestMatchers.add( |
363 | | - getConfigurer(OidcConfigurer.class) |
364 | | - .getConfigurer(OidcUserInfoEndpointConfigurer.class).getRequestMatcher() |
365 | | - ); |
366 | | - OidcClientRegistrationEndpointConfigurer clientRegistrationEndpointConfigurer = |
367 | | - getConfigurer(OidcConfigurer.class) |
368 | | - .getConfigurer(OidcClientRegistrationEndpointConfigurer.class); |
369 | | - if (clientRegistrationEndpointConfigurer != null) { |
370 | | - requestMatchers.add(clientRegistrationEndpointConfigurer.getRequestMatcher()); |
371 | | - } |
372 | | - return new OrRequestMatcher(requestMatchers); |
373 | | - } |
374 | | - |
375 | | - }; |
376 | | - |
377 | | - builder.setSharedObject(SecurityContextRepository.class, securityContextRepositoryTransientNotSaved); |
378 | 240 | } |
379 | 241 |
|
380 | 242 | @Override |
|
0 commit comments