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>
@@ -158,6 +160,8 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
158160
159161 private BearerTokenResolver bearerTokenResolver ;
160162
163+ private AuthenticationConverter authenticationConverter ;
164+
161165 private JwtConfigurer jwtConfigurer ;
162166
163167 private OpaqueTokenConfigurer opaqueTokenConfigurer ;
@@ -200,6 +204,12 @@ public OAuth2ResourceServerConfigurer<H> bearerTokenResolver(BearerTokenResolver
200204 return this ;
201205 }
202206
207+ public OAuth2ResourceServerConfigurer <H > authenticationConverter (AuthenticationConverter authenticationConverter ) {
208+ Assert .notNull (authenticationConverter , "authenticationConverter cannot be null" );
209+ this .authenticationConverter = authenticationConverter ;
210+ return this ;
211+ }
212+
203213 /**
204214 * @deprecated For removal in 7.0. Use {@link #jwt(Customizer)} or
205215 * {@code jwt(Customizer.withDefaults())} to stick with defaults. See the <a href=
@@ -271,16 +281,25 @@ public void init(H http) {
271281
272282 @ Override
273283 public void configure (H http ) {
274- BearerTokenResolver bearerTokenResolver = getBearerTokenResolver ();
275- this .requestMatcher .setBearerTokenResolver (bearerTokenResolver );
276284 AuthenticationManagerResolver resolver = this .authenticationManagerResolver ;
277285 if (resolver == null ) {
278286 AuthenticationManager authenticationManager = getAuthenticationManager (http );
279287 resolver = (request ) -> authenticationManager ;
280288 }
281-
282289 BearerTokenAuthenticationFilter filter = new BearerTokenAuthenticationFilter (resolver );
283- filter .setBearerTokenResolver (bearerTokenResolver );
290+
291+ BearerTokenResolver bearerTokenResolver = getBearerTokenResolver ();
292+ if (bearerTokenResolver != null ) {
293+ this .requestMatcher .setBearerTokenResolver (bearerTokenResolver );
294+ filter .setBearerTokenResolver (bearerTokenResolver );
295+ }
296+ else {
297+ AuthenticationConverter converter = getAuthenticationConverter ();
298+ this .requestMatcher .setAuthenticationConverter (converter );
299+ filter .setAuthenticationConverter (converter );
300+ }
301+
302+ filter .setAuthenticationConverter (getAuthenticationConverter ());
284303 filter .setAuthenticationEntryPoint (this .authenticationEntryPoint );
285304 filter .setSecurityContextHolderStrategy (getSecurityContextHolderStrategy ());
286305 filter = postProcess (filter );
@@ -368,11 +387,20 @@ BearerTokenResolver getBearerTokenResolver() {
368387 if (this .context .getBeanNamesForType (BearerTokenResolver .class ).length > 0 ) {
369388 this .bearerTokenResolver = this .context .getBean (BearerTokenResolver .class );
370389 }
390+ }
391+ return this .bearerTokenResolver ;
392+ }
393+
394+ AuthenticationConverter getAuthenticationConverter () {
395+ if (this .authenticationConverter == null ) {
396+ if (this .context .getBeanNamesForType (AuthenticationConverter .class ).length > 0 ) {
397+ this .authenticationConverter = this .context .getBean (AuthenticationConverter .class );
398+ }
371399 else {
372- this .bearerTokenResolver = new DefaultBearerTokenResolver ();
400+ this .authenticationConverter = new BearerTokenAuthenticationConverter ();
373401 }
374402 }
375- return this .bearerTokenResolver ;
403+ return this .authenticationConverter ;
376404 }
377405
378406 public class JwtConfigurer {
@@ -562,10 +590,15 @@ private static final class BearerTokenRequestMatcher implements RequestMatcher {
562590
563591 private BearerTokenResolver bearerTokenResolver ;
564592
593+ private AuthenticationConverter authenticationConverter ;
594+
565595 @ Override
566596 public boolean matches (HttpServletRequest request ) {
567597 try {
568- return this .bearerTokenResolver .resolve (request ) != null ;
598+ if (this .bearerTokenResolver != null ) {
599+ return this .bearerTokenResolver .resolve (request ) != null ;
600+ }
601+ return this .authenticationConverter .convert (request ) != null ;
569602 }
570603 catch (OAuth2AuthenticationException ex ) {
571604 return false ;
@@ -577,6 +610,11 @@ void setBearerTokenResolver(BearerTokenResolver tokenResolver) {
577610 this .bearerTokenResolver = tokenResolver ;
578611 }
579612
613+ void setAuthenticationConverter (AuthenticationConverter authenticationConverter ) {
614+ Assert .notNull (authenticationConverter , "authenticationConverter cannot be null" );
615+ this .authenticationConverter = authenticationConverter ;
616+ }
617+
580618 }
581619
582620}
0 commit comments