11/*
2- * Copyright 2002-2023 the original author or authors.
2+ * Copyright 2002-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.
4141import org .springframework .security .oauth2 .jwt .Jwt ;
4242import org .springframework .security .oauth2 .jwt .JwtDecoder ;
4343import org .springframework .security .oauth2 .jwt .NimbusJwtDecoder ;
44+ import org .springframework .security .oauth2 .server .resource .authentication .BearerTokenAuthenticationConverter ;
4445import org .springframework .security .oauth2 .server .resource .authentication .JwtAuthenticationConverter ;
4546import org .springframework .security .oauth2 .server .resource .authentication .JwtAuthenticationProvider ;
4647import org .springframework .security .oauth2 .server .resource .authentication .OpaqueTokenAuthenticationProvider ;
4950import org .springframework .security .oauth2 .server .resource .introspection .SpringOpaqueTokenIntrospector ;
5051import org .springframework .security .oauth2 .server .resource .web .BearerTokenAuthenticationEntryPoint ;
5152import org .springframework .security .oauth2 .server .resource .web .BearerTokenResolver ;
52- import org .springframework .security .oauth2 .server .resource .web .DefaultBearerTokenResolver ;
5353import org .springframework .security .oauth2 .server .resource .web .access .BearerTokenAccessDeniedHandler ;
5454import org .springframework .security .oauth2 .server .resource .web .authentication .BearerTokenAuthenticationFilter ;
5555import org .springframework .security .web .AuthenticationEntryPoint ;
5656import org .springframework .security .web .access .AccessDeniedHandler ;
5757import org .springframework .security .web .access .AccessDeniedHandlerImpl ;
5858import org .springframework .security .web .access .DelegatingAccessDeniedHandler ;
59+ import org .springframework .security .web .authentication .AuthenticationConverter ;
5960import org .springframework .security .web .csrf .CsrfException ;
6061import org .springframework .security .web .util .matcher .AndRequestMatcher ;
6162import org .springframework .security .web .util .matcher .MediaTypeRequestMatcher ;
6869import org .springframework .web .accept .HeaderContentNegotiationStrategy ;
6970
7071/**
71- *
7272 * An {@link AbstractHttpConfigurer} for OAuth 2.0 Resource Server Support.
73- *
73+ * <p>
7474 * By default, this wires a {@link BearerTokenAuthenticationFilter}, which can be used to
7575 * parse the request for bearer tokens and make an authentication attempt.
7676 *
8484 * authentication failures are handled
8585 * <li>{@link #bearerTokenResolver(BearerTokenResolver)} - customizes how to resolve a
8686 * bearer token from the request</li>
87+ * <li>{@link #authenticationConverter(AuthenticationConverter)} - customizes how to
88+ * convert a request to authentication</li>
8789 * <li>{@link #jwt(Customizer)} - enables Jwt-encoded bearer token support</li>
8890 * <li>{@link #opaqueToken(Customizer)} - enables opaque bearer token support</li>
8991 * </ul>
9698 * <li>supply a {@link JwtDecoder} instance via {@link JwtConfigurer#decoder}, or</li>
9799 * <li>expose a {@link JwtDecoder} bean</li>
98100 * </ul>
99- *
101+ * <p>
100102 * Also with {@link #jwt(Customizer)} consider
101103 *
102104 * <ul>
111113 * </p>
112114 *
113115 * <h2>Security Filters</h2>
114- *
116+ * <p>
115117 * The following {@code Filter}s are populated when {@link #jwt(Customizer)} is
116118 * configured:
117119 *
120122 * </ul>
121123 *
122124 * <h2>Shared Objects Created</h2>
123- *
125+ * <p>
124126 * The following shared objects are populated:
125127 *
126128 * <ul>
127129 * <li>{@link SessionCreationPolicy} (optional)</li>
128130 * </ul>
129131 *
130132 * <h2>Shared Objects Used</h2>
131- *
133+ * <p>
132134 * The following shared objects are used:
133135 *
134136 * <ul>
@@ -156,6 +158,8 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
156158
157159 private BearerTokenResolver bearerTokenResolver ;
158160
161+ private AuthenticationConverter authenticationConverter ;
162+
159163 private JwtConfigurer jwtConfigurer ;
160164
161165 private OpaqueTokenConfigurer opaqueTokenConfigurer ;
@@ -198,6 +202,12 @@ public OAuth2ResourceServerConfigurer<H> bearerTokenResolver(BearerTokenResolver
198202 return this ;
199203 }
200204
205+ public OAuth2ResourceServerConfigurer <H > authenticationConverter (AuthenticationConverter authenticationConverter ) {
206+ Assert .notNull (authenticationConverter , "authenticationConverter cannot be null" );
207+ this .authenticationConverter = authenticationConverter ;
208+ return this ;
209+ }
210+
201211 /**
202212 * @deprecated For removal in 7.0. Use {@link #jwt(Customizer)} or
203213 * {@code jwt(Customizer.withDefaults())} to stick with defaults. See the <a href=
@@ -269,16 +279,25 @@ public void init(H http) {
269279
270280 @ Override
271281 public void configure (H http ) {
272- BearerTokenResolver bearerTokenResolver = getBearerTokenResolver ();
273- this .requestMatcher .setBearerTokenResolver (bearerTokenResolver );
274282 AuthenticationManagerResolver resolver = this .authenticationManagerResolver ;
275283 if (resolver == null ) {
276284 AuthenticationManager authenticationManager = getAuthenticationManager (http );
277285 resolver = (request ) -> authenticationManager ;
278286 }
279-
280287 BearerTokenAuthenticationFilter filter = new BearerTokenAuthenticationFilter (resolver );
281- filter .setBearerTokenResolver (bearerTokenResolver );
288+
289+ BearerTokenResolver bearerTokenResolver = getBearerTokenResolver ();
290+ if (bearerTokenResolver != null ) {
291+ this .requestMatcher .setBearerTokenResolver (bearerTokenResolver );
292+ filter .setBearerTokenResolver (bearerTokenResolver );
293+ }
294+ else {
295+ AuthenticationConverter converter = getAuthenticationConverter ();
296+ this .requestMatcher .setAuthenticationConverter (converter );
297+ filter .setAuthenticationConverter (converter );
298+ }
299+
300+ filter .setAuthenticationConverter (getAuthenticationConverter ());
282301 filter .setAuthenticationEntryPoint (this .authenticationEntryPoint );
283302 filter .setSecurityContextHolderStrategy (getSecurityContextHolderStrategy ());
284303 filter = postProcess (filter );
@@ -366,11 +385,20 @@ BearerTokenResolver getBearerTokenResolver() {
366385 if (this .context .getBeanNamesForType (BearerTokenResolver .class ).length > 0 ) {
367386 this .bearerTokenResolver = this .context .getBean (BearerTokenResolver .class );
368387 }
388+ }
389+ return this .bearerTokenResolver ;
390+ }
391+
392+ AuthenticationConverter getAuthenticationConverter () {
393+ if (this .authenticationConverter == null ) {
394+ if (this .context .getBeanNamesForType (AuthenticationConverter .class ).length > 0 ) {
395+ this .authenticationConverter = this .context .getBean (AuthenticationConverter .class );
396+ }
369397 else {
370- this .bearerTokenResolver = new DefaultBearerTokenResolver ();
398+ this .authenticationConverter = new BearerTokenAuthenticationConverter ();
371399 }
372400 }
373- return this .bearerTokenResolver ;
401+ return this .authenticationConverter ;
374402 }
375403
376404 public class JwtConfigurer {
@@ -560,10 +588,15 @@ private static final class BearerTokenRequestMatcher implements RequestMatcher {
560588
561589 private BearerTokenResolver bearerTokenResolver ;
562590
591+ private AuthenticationConverter authenticationConverter ;
592+
563593 @ Override
564594 public boolean matches (HttpServletRequest request ) {
565595 try {
566- return this .bearerTokenResolver .resolve (request ) != null ;
596+ if (this .bearerTokenResolver != null ) {
597+ return this .bearerTokenResolver .resolve (request ) != null ;
598+ }
599+ return this .authenticationConverter .convert (request ) != null ;
567600 }
568601 catch (OAuth2AuthenticationException ex ) {
569602 return false ;
@@ -575,6 +608,11 @@ void setBearerTokenResolver(BearerTokenResolver tokenResolver) {
575608 this .bearerTokenResolver = tokenResolver ;
576609 }
577610
611+ void setAuthenticationConverter (AuthenticationConverter authenticationConverter ) {
612+ Assert .notNull (authenticationConverter , "authenticationConverter cannot be null" );
613+ this .authenticationConverter = authenticationConverter ;
614+ }
615+
578616 }
579617
580618}
0 commit comments