|
22 | 22 | import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
23 | 23 | import org.springframework.security.core.context.SecurityContext;
|
24 | 24 | import org.springframework.security.oauth2.client.ClientCredentialsReactiveOAuth2AuthorizedClientProvider;
|
| 25 | +import org.springframework.security.oauth2.client.OAuth2AuthorizationContext; |
25 | 26 | import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest;
|
26 | 27 | import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
|
27 | 28 | import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientManager;
|
|
35 | 36 | import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
|
36 | 37 | import org.springframework.security.oauth2.client.web.DefaultReactiveOAuth2AuthorizedClientManager;
|
37 | 38 | import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository;
|
| 39 | +import org.springframework.security.oauth2.client.web.server.UnAuthenticatedServerOAuth2AuthorizedClientRepository; |
38 | 40 | import org.springframework.util.Assert;
|
39 | 41 | import org.springframework.web.reactive.function.client.ClientRequest;
|
40 | 42 | import org.springframework.web.reactive.function.client.ClientResponse;
|
@@ -124,6 +126,17 @@ private static ReactiveOAuth2AuthorizedClientManager createDefaultAuthorizedClie
|
124 | 126 | .clientCredentials()
|
125 | 127 | .password()
|
126 | 128 | .build();
|
| 129 | + |
| 130 | + // gh-7544 |
| 131 | + if (authorizedClientRepository instanceof UnAuthenticatedServerOAuth2AuthorizedClientRepository) { |
| 132 | + UnAuthenticatedReactiveOAuth2AuthorizedClientManager unauthenticatedAuthorizedClientManager = |
| 133 | + new UnAuthenticatedReactiveOAuth2AuthorizedClientManager( |
| 134 | + clientRegistrationRepository, |
| 135 | + (UnAuthenticatedServerOAuth2AuthorizedClientRepository) authorizedClientRepository); |
| 136 | + unauthenticatedAuthorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); |
| 137 | + return unauthenticatedAuthorizedClientManager; |
| 138 | + } |
| 139 | + |
127 | 140 | DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager = new DefaultReactiveOAuth2AuthorizedClientManager(
|
128 | 141 | clientRegistrationRepository, authorizedClientRepository);
|
129 | 142 | authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
|
@@ -266,7 +279,11 @@ private void updateDefaultAuthorizedClientManager() {
|
266 | 279 | .clientCredentials(this::updateClientCredentialsProvider)
|
267 | 280 | .password(configurer -> configurer.clockSkew(this.accessTokenExpiresSkew))
|
268 | 281 | .build();
|
269 |
| - ((DefaultReactiveOAuth2AuthorizedClientManager) this.authorizedClientManager).setAuthorizedClientProvider(authorizedClientProvider); |
| 282 | + if (this.authorizedClientManager instanceof UnAuthenticatedReactiveOAuth2AuthorizedClientManager) { |
| 283 | + ((UnAuthenticatedReactiveOAuth2AuthorizedClientManager) this.authorizedClientManager).setAuthorizedClientProvider(authorizedClientProvider); |
| 284 | + } else { |
| 285 | + ((DefaultReactiveOAuth2AuthorizedClientManager) this.authorizedClientManager).setAuthorizedClientProvider(authorizedClientProvider); |
| 286 | + } |
270 | 287 | }
|
271 | 288 |
|
272 | 289 | private void updateClientCredentialsProvider(ReactiveOAuth2AuthorizedClientProviderBuilder.ClientCredentialsGrantBuilder builder) {
|
@@ -376,4 +393,52 @@ private ClientRequest bearer(ClientRequest request, OAuth2AuthorizedClient autho
|
376 | 393 | .headers(headers -> headers.setBearerAuth(authorizedClient.getAccessToken().getTokenValue()))
|
377 | 394 | .build();
|
378 | 395 | }
|
| 396 | + |
| 397 | + private static class UnAuthenticatedReactiveOAuth2AuthorizedClientManager implements ReactiveOAuth2AuthorizedClientManager { |
| 398 | + private final ReactiveClientRegistrationRepository clientRegistrationRepository; |
| 399 | + private final UnAuthenticatedServerOAuth2AuthorizedClientRepository authorizedClientRepository; |
| 400 | + private ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider; |
| 401 | + |
| 402 | + private UnAuthenticatedReactiveOAuth2AuthorizedClientManager( |
| 403 | + ReactiveClientRegistrationRepository clientRegistrationRepository, |
| 404 | + UnAuthenticatedServerOAuth2AuthorizedClientRepository authorizedClientRepository) { |
| 405 | + this.clientRegistrationRepository = clientRegistrationRepository; |
| 406 | + this.authorizedClientRepository = authorizedClientRepository; |
| 407 | + } |
| 408 | + |
| 409 | + @Override |
| 410 | + public Mono<OAuth2AuthorizedClient> authorize(OAuth2AuthorizeRequest authorizeRequest) { |
| 411 | + Assert.notNull(authorizeRequest, "authorizeRequest cannot be null"); |
| 412 | + |
| 413 | + String clientRegistrationId = authorizeRequest.getClientRegistrationId(); |
| 414 | + Authentication principal = authorizeRequest.getPrincipal(); |
| 415 | + |
| 416 | + return Mono.justOrEmpty(authorizeRequest.getAuthorizedClient()) |
| 417 | + .switchIfEmpty(Mono.defer(() -> this.authorizedClientRepository.loadAuthorizedClient(clientRegistrationId, principal, null))) |
| 418 | + .flatMap(authorizedClient -> { |
| 419 | + // Re-authorize |
| 420 | + return Mono.just(OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient).principal(principal).build()) |
| 421 | + .flatMap(this.authorizedClientProvider::authorize) |
| 422 | + .flatMap(reauthorizedClient -> this.authorizedClientRepository.saveAuthorizedClient(reauthorizedClient, principal, null).thenReturn(reauthorizedClient)) |
| 423 | + // Default to the existing authorizedClient if the client was not re-authorized |
| 424 | + .defaultIfEmpty(authorizeRequest.getAuthorizedClient() != null ? |
| 425 | + authorizeRequest.getAuthorizedClient() : authorizedClient); |
| 426 | + }) |
| 427 | + .switchIfEmpty(Mono.deferWithContext(context -> |
| 428 | + // Authorize |
| 429 | + this.clientRegistrationRepository.findByRegistrationId(clientRegistrationId) |
| 430 | + .switchIfEmpty(Mono.error(() -> new IllegalArgumentException( |
| 431 | + "Could not find ClientRegistration with id '" + clientRegistrationId + "'"))) |
| 432 | + .flatMap(clientRegistration -> Mono.just(OAuth2AuthorizationContext.withClientRegistration(clientRegistration).principal(principal).build())) |
| 433 | + .flatMap(this.authorizedClientProvider::authorize) |
| 434 | + .flatMap(authorizedClient -> this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, principal, null).thenReturn(authorizedClient)) |
| 435 | + .subscriberContext(context) |
| 436 | + )); |
| 437 | + } |
| 438 | + |
| 439 | + private void setAuthorizedClientProvider(ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider) { |
| 440 | + Assert.notNull(authorizedClientProvider, "authorizedClientProvider cannot be null"); |
| 441 | + this.authorizedClientProvider = authorizedClientProvider; |
| 442 | + } |
| 443 | + } |
379 | 444 | }
|
0 commit comments