50
50
import reactor .core .publisher .Hooks ;
51
51
import reactor .core .publisher .Mono ;
52
52
import reactor .core .publisher .Operators ;
53
+ import reactor .core .scheduler .Schedulers ;
53
54
import reactor .util .context .Context ;
54
55
55
56
import javax .servlet .http .HttpServletRequest ;
@@ -258,7 +259,6 @@ public Consumer<WebClient.RequestHeadersSpec<?>> defaultRequest() {
258
259
spec .attributes (attrs -> {
259
260
populateDefaultRequestResponse (attrs );
260
261
populateDefaultAuthentication (attrs );
261
- populateDefaultOAuth2AuthorizedClient (attrs );
262
262
});
263
263
};
264
264
}
@@ -349,20 +349,33 @@ public void setAccessTokenExpiresSkew(Duration accessTokenExpiresSkew) {
349
349
350
350
@ Override
351
351
public Mono <ClientResponse > filter (ClientRequest request , ExchangeFunction next ) {
352
- return Mono .just (request )
353
- .filter (req -> req .attribute (OAUTH2_AUTHORIZED_CLIENT_ATTR_NAME ).isPresent ())
354
- .switchIfEmpty (mergeRequestAttributesFromContext (request ))
352
+ return mergeRequestAttributesIfNecessary (request )
355
353
.filter (req -> req .attribute (OAUTH2_AUTHORIZED_CLIENT_ATTR_NAME ).isPresent ())
356
354
.flatMap (req -> authorizedClient (getOAuth2AuthorizedClient (req .attributes ()), req ))
355
+ .switchIfEmpty (Mono .defer (() ->
356
+ mergeRequestAttributesIfNecessary (request )
357
+ .filter (req -> resolveClientRegistrationId (req ) != null )
358
+ .flatMap (req -> authorizeClient (resolveClientRegistrationId (req ), req ))
359
+ ))
357
360
.map (authorizedClient -> bearer (request , authorizedClient ))
358
361
.flatMap (next ::exchange )
359
- .switchIfEmpty (next .exchange (request ));
362
+ .switchIfEmpty (Mono .defer (() -> next .exchange (request )));
363
+ }
364
+
365
+ private Mono <ClientRequest > mergeRequestAttributesIfNecessary (ClientRequest request ) {
366
+ if (!request .attribute (HTTP_SERVLET_REQUEST_ATTR_NAME ).isPresent () ||
367
+ !request .attribute (HTTP_SERVLET_RESPONSE_ATTR_NAME ).isPresent () ||
368
+ !request .attribute (AUTHENTICATION_ATTR_NAME ).isPresent ()) {
369
+ return mergeRequestAttributesFromContext (request );
370
+ } else {
371
+ return Mono .just (request );
372
+ }
360
373
}
361
374
362
375
private Mono <ClientRequest > mergeRequestAttributesFromContext (ClientRequest request ) {
363
- return Mono . just ( ClientRequest .from (request ))
364
- . flatMap ( builder -> Mono .subscriberContext ()
365
- .map (ctx -> builder .attributes (attrs -> populateRequestAttributes (attrs , ctx ) )))
376
+ ClientRequest . Builder builder = ClientRequest .from (request );
377
+ return Mono .subscriberContext ()
378
+ .map (ctx -> builder .attributes (attrs -> populateRequestAttributes (attrs , ctx )))
366
379
.map (ClientRequest .Builder ::build );
367
380
}
368
381
@@ -376,7 +389,6 @@ private void populateRequestAttributes(Map<String, Object> attrs, Context ctx) {
376
389
if (ctx .hasKey (AUTHENTICATION_ATTR_NAME )) {
377
390
attrs .putIfAbsent (AUTHENTICATION_ATTR_NAME , ctx .get (AUTHENTICATION_ATTR_NAME ));
378
391
}
379
- populateDefaultOAuth2AuthorizedClient (attrs );
380
392
}
381
393
382
394
private void populateDefaultRequestResponse (Map <String , Object > attrs ) {
@@ -403,32 +415,38 @@ private void populateDefaultAuthentication(Map<String, Object> attrs) {
403
415
attrs .putIfAbsent (AUTHENTICATION_ATTR_NAME , authentication );
404
416
}
405
417
406
- private void populateDefaultOAuth2AuthorizedClient (Map <String , Object > attrs ) {
407
- if (this .authorizedClientManager == null ||
408
- attrs .containsKey (OAUTH2_AUTHORIZED_CLIENT_ATTR_NAME )) {
409
- return ;
410
- }
411
-
412
- Authentication authentication = getAuthentication (attrs );
418
+ private String resolveClientRegistrationId (ClientRequest request ) {
419
+ Map <String , Object > attrs = request .attributes ();
413
420
String clientRegistrationId = getClientRegistrationId (attrs );
414
421
if (clientRegistrationId == null ) {
415
422
clientRegistrationId = this .defaultClientRegistrationId ;
416
423
}
424
+ Authentication authentication = getAuthentication (attrs );
417
425
if (clientRegistrationId == null
418
426
&& this .defaultOAuth2AuthorizedClient
419
427
&& authentication instanceof OAuth2AuthenticationToken ) {
420
428
clientRegistrationId = ((OAuth2AuthenticationToken ) authentication ).getAuthorizedClientRegistrationId ();
421
429
}
422
- if (clientRegistrationId != null ) {
423
- HttpServletRequest request = getRequest (attrs );
424
- if (authentication == null ) {
425
- authentication = ANONYMOUS_AUTHENTICATION ;
426
- }
427
- OAuth2AuthorizeRequest authorizeRequest = new OAuth2AuthorizeRequest (
428
- clientRegistrationId , authentication , request , getResponse (attrs ));
429
- OAuth2AuthorizedClient authorizedClient = this .authorizedClientManager .authorize (authorizeRequest );
430
- oauth2AuthorizedClient (authorizedClient ).accept (attrs );
430
+ return clientRegistrationId ;
431
+ }
432
+
433
+ private Mono <OAuth2AuthorizedClient > authorizeClient (String clientRegistrationId , ClientRequest request ) {
434
+ if (this .authorizedClientManager == null ) {
435
+ return Mono .empty ();
431
436
}
437
+ Map <String , Object > attrs = request .attributes ();
438
+ Authentication authentication = getAuthentication (attrs );
439
+ if (authentication == null ) {
440
+ authentication = ANONYMOUS_AUTHENTICATION ;
441
+ }
442
+ HttpServletRequest servletRequest = getRequest (attrs );
443
+ HttpServletResponse servletResponse = getResponse (attrs );
444
+ OAuth2AuthorizeRequest authorizeRequest = new OAuth2AuthorizeRequest (
445
+ clientRegistrationId , authentication , servletRequest , servletResponse );
446
+
447
+ // NOTE: 'authorizedClientManager.authorize()' needs to be executed on a dedicated thread via subscribeOn(Schedulers.elastic())
448
+ // since it performs a blocking I/O operation using RestTemplate internally
449
+ return Mono .fromSupplier (() -> this .authorizedClientManager .authorize (authorizeRequest )).subscribeOn (Schedulers .elastic ());
432
450
}
433
451
434
452
private Mono <OAuth2AuthorizedClient > authorizedClient (OAuth2AuthorizedClient authorizedClient , ClientRequest request ) {
@@ -444,7 +462,10 @@ private Mono<OAuth2AuthorizedClient> authorizedClient(OAuth2AuthorizedClient aut
444
462
HttpServletResponse servletResponse = getResponse (attrs );
445
463
OAuth2AuthorizeRequest reauthorizeRequest = new OAuth2AuthorizeRequest (
446
464
authorizedClient , authentication , servletRequest , servletResponse );
447
- return Mono .fromSupplier (() -> this .authorizedClientManager .authorize (reauthorizeRequest ));
465
+
466
+ // NOTE: 'authorizedClientManager.authorize()' needs to be executed on a dedicated thread via subscribeOn(Schedulers.elastic())
467
+ // since it performs a blocking I/O operation using RestTemplate internally
468
+ return Mono .fromSupplier (() -> this .authorizedClientManager .authorize (reauthorizeRequest )).subscribeOn (Schedulers .elastic ());
448
469
}
449
470
450
471
private ClientRequest bearer (ClientRequest request , OAuth2AuthorizedClient authorizedClient ) {
0 commit comments