parent
							
								
									6c5fd38a3f
								
							
						
					
					
						commit
						525f40490c
					
				| 
						 | 
					@ -1098,3 +1098,9 @@ class OAuth2ResourceServerController {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
----
 | 
					----
 | 
				
			||||||
====
 | 
					====
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[NOTE]
 | 
				
			||||||
 | 
					`JwtBearerReactiveOAuth2AuthorizedClientProvider` resolves the `Jwt` assertion via `OAuth2AuthorizationContext.getPrincipal().getPrincipal()` by default, hence the use of `JwtAuthenticationToken` in the preceding example.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[TIP]
 | 
				
			||||||
 | 
					If you need to resolve the `Jwt` assertion from a different source, you can provide `JwtBearerReactiveOAuth2AuthorizedClientProvider.setJwtAssertionResolver()` with a custom `Function<OAuth2AuthorizationContext, Mono<Jwt>>`.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1352,3 +1352,9 @@ class OAuth2ResourceServerController {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
----
 | 
					----
 | 
				
			||||||
====
 | 
					====
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[NOTE]
 | 
				
			||||||
 | 
					`JwtBearerOAuth2AuthorizedClientProvider` resolves the `Jwt` assertion via `OAuth2AuthorizationContext.getPrincipal().getPrincipal()` by default, hence the use of `JwtAuthenticationToken` in the preceding example.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[TIP]
 | 
				
			||||||
 | 
					If you need to resolve the `Jwt` assertion from a different source, you can provide `JwtBearerOAuth2AuthorizedClientProvider.setJwtAssertionResolver()` with a custom `Function<OAuth2AuthorizationContext, Jwt>`.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright 2002-2021 the original author or authors.
 | 
					 * Copyright 2002-2022 the original author or authors.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 * you may not use this file except in compliance with the License.
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,7 @@ package org.springframework.security.oauth2.client;
 | 
				
			||||||
import java.time.Clock;
 | 
					import java.time.Clock;
 | 
				
			||||||
import java.time.Duration;
 | 
					import java.time.Duration;
 | 
				
			||||||
import java.time.Instant;
 | 
					import java.time.Instant;
 | 
				
			||||||
 | 
					import java.util.function.Function;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.lang.Nullable;
 | 
					import org.springframework.lang.Nullable;
 | 
				
			||||||
import org.springframework.security.oauth2.client.endpoint.DefaultJwtBearerTokenResponseClient;
 | 
					import org.springframework.security.oauth2.client.endpoint.DefaultJwtBearerTokenResponseClient;
 | 
				
			||||||
| 
						 | 
					@ -45,6 +46,8 @@ public final class JwtBearerOAuth2AuthorizedClientProvider implements OAuth2Auth
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private OAuth2AccessTokenResponseClient<JwtBearerGrantRequest> accessTokenResponseClient = new DefaultJwtBearerTokenResponseClient();
 | 
						private OAuth2AccessTokenResponseClient<JwtBearerGrantRequest> accessTokenResponseClient = new DefaultJwtBearerTokenResponseClient();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private Function<OAuth2AuthorizationContext, Jwt> jwtAssertionResolver = this::resolveJwtAssertion;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private Duration clockSkew = Duration.ofSeconds(60);
 | 
						private Duration clockSkew = Duration.ofSeconds(60);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private Clock clock = Clock.systemUTC();
 | 
						private Clock clock = Clock.systemUTC();
 | 
				
			||||||
| 
						 | 
					@ -75,10 +78,10 @@ public final class JwtBearerOAuth2AuthorizedClientProvider implements OAuth2Auth
 | 
				
			||||||
			// need for re-authorization
 | 
								// need for re-authorization
 | 
				
			||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (!(context.getPrincipal().getPrincipal() instanceof Jwt)) {
 | 
							Jwt jwt = this.jwtAssertionResolver.apply(context);
 | 
				
			||||||
 | 
							if (jwt == null) {
 | 
				
			||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Jwt jwt = (Jwt) context.getPrincipal().getPrincipal();
 | 
					 | 
				
			||||||
		// As per spec, in section 4.1 Using Assertions as Authorization Grants
 | 
							// As per spec, in section 4.1 Using Assertions as Authorization Grants
 | 
				
			||||||
		// https://tools.ietf.org/html/rfc7521#section-4.1
 | 
							// https://tools.ietf.org/html/rfc7521#section-4.1
 | 
				
			||||||
		//
 | 
							//
 | 
				
			||||||
| 
						 | 
					@ -97,6 +100,13 @@ public final class JwtBearerOAuth2AuthorizedClientProvider implements OAuth2Auth
 | 
				
			||||||
				tokenResponse.getAccessToken());
 | 
									tokenResponse.getAccessToken());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private Jwt resolveJwtAssertion(OAuth2AuthorizationContext context) {
 | 
				
			||||||
 | 
							if (!(context.getPrincipal().getPrincipal() instanceof Jwt)) {
 | 
				
			||||||
 | 
								return null;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return (Jwt) context.getPrincipal().getPrincipal();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private OAuth2AccessTokenResponse getTokenResponse(ClientRegistration clientRegistration,
 | 
						private OAuth2AccessTokenResponse getTokenResponse(ClientRegistration clientRegistration,
 | 
				
			||||||
			JwtBearerGrantRequest jwtBearerGrantRequest) {
 | 
								JwtBearerGrantRequest jwtBearerGrantRequest) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
| 
						 | 
					@ -123,6 +133,17 @@ public final class JwtBearerOAuth2AuthorizedClientProvider implements OAuth2Auth
 | 
				
			||||||
		this.accessTokenResponseClient = accessTokenResponseClient;
 | 
							this.accessTokenResponseClient = accessTokenResponseClient;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Sets the resolver used for resolving the {@link Jwt} assertion.
 | 
				
			||||||
 | 
						 * @param jwtAssertionResolver the resolver used for resolving the {@link Jwt}
 | 
				
			||||||
 | 
						 * assertion
 | 
				
			||||||
 | 
						 * @since 5.7
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setJwtAssertionResolver(Function<OAuth2AuthorizationContext, Jwt> jwtAssertionResolver) {
 | 
				
			||||||
 | 
							Assert.notNull(jwtAssertionResolver, "jwtAssertionResolver cannot be null");
 | 
				
			||||||
 | 
							this.jwtAssertionResolver = jwtAssertionResolver;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Sets the maximum acceptable clock skew, which is used when checking the
 | 
						 * Sets the maximum acceptable clock skew, which is used when checking the
 | 
				
			||||||
	 * {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is
 | 
						 * {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright 2002-2021 the original author or authors.
 | 
					 * Copyright 2002-2022 the original author or authors.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 * you may not use this file except in compliance with the License.
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,7 @@ package org.springframework.security.oauth2.client;
 | 
				
			||||||
import java.time.Clock;
 | 
					import java.time.Clock;
 | 
				
			||||||
import java.time.Duration;
 | 
					import java.time.Duration;
 | 
				
			||||||
import java.time.Instant;
 | 
					import java.time.Instant;
 | 
				
			||||||
 | 
					import java.util.function.Function;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import reactor.core.publisher.Mono;
 | 
					import reactor.core.publisher.Mono;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,6 +46,8 @@ public final class JwtBearerReactiveOAuth2AuthorizedClientProvider implements Re
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private ReactiveOAuth2AccessTokenResponseClient<JwtBearerGrantRequest> accessTokenResponseClient = new WebClientReactiveJwtBearerTokenResponseClient();
 | 
						private ReactiveOAuth2AccessTokenResponseClient<JwtBearerGrantRequest> accessTokenResponseClient = new WebClientReactiveJwtBearerTokenResponseClient();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private Function<OAuth2AuthorizationContext, Mono<Jwt>> jwtAssertionResolver = this::resolveJwtAssertion;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private Duration clockSkew = Duration.ofSeconds(60);
 | 
						private Duration clockSkew = Duration.ofSeconds(60);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private Clock clock = Clock.systemUTC();
 | 
						private Clock clock = Clock.systemUTC();
 | 
				
			||||||
| 
						 | 
					@ -74,10 +77,7 @@ public final class JwtBearerReactiveOAuth2AuthorizedClientProvider implements Re
 | 
				
			||||||
			// need for re-authorization
 | 
								// need for re-authorization
 | 
				
			||||||
			return Mono.empty();
 | 
								return Mono.empty();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (!(context.getPrincipal().getPrincipal() instanceof Jwt)) {
 | 
					
 | 
				
			||||||
			return Mono.empty();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		Jwt jwt = (Jwt) context.getPrincipal().getPrincipal();
 | 
					 | 
				
			||||||
		// As per spec, in section 4.1 Using Assertions as Authorization Grants
 | 
							// As per spec, in section 4.1 Using Assertions as Authorization Grants
 | 
				
			||||||
		// https://tools.ietf.org/html/rfc7521#section-4.1
 | 
							// https://tools.ietf.org/html/rfc7521#section-4.1
 | 
				
			||||||
		//
 | 
							//
 | 
				
			||||||
| 
						 | 
					@ -90,13 +90,26 @@ public final class JwtBearerReactiveOAuth2AuthorizedClientProvider implements Re
 | 
				
			||||||
		// issued with a reasonably short lifetime. Clients can refresh an
 | 
							// issued with a reasonably short lifetime. Clients can refresh an
 | 
				
			||||||
		// expired access token by requesting a new one using the same
 | 
							// expired access token by requesting a new one using the same
 | 
				
			||||||
		// assertion, if it is still valid, or with a new assertion.
 | 
							// assertion, if it is still valid, or with a new assertion.
 | 
				
			||||||
		return Mono.just(new JwtBearerGrantRequest(clientRegistration, jwt))
 | 
					
 | 
				
			||||||
 | 
							// @formatter:off
 | 
				
			||||||
 | 
							return this.jwtAssertionResolver.apply(context)
 | 
				
			||||||
 | 
									.map((jwt) -> new JwtBearerGrantRequest(clientRegistration, jwt))
 | 
				
			||||||
				.flatMap(this.accessTokenResponseClient::getTokenResponse)
 | 
									.flatMap(this.accessTokenResponseClient::getTokenResponse)
 | 
				
			||||||
				.onErrorMap(OAuth2AuthorizationException.class,
 | 
									.onErrorMap(OAuth2AuthorizationException.class,
 | 
				
			||||||
						(ex) -> new ClientAuthorizationException(ex.getError(), clientRegistration.getRegistrationId(),
 | 
											(ex) -> new ClientAuthorizationException(ex.getError(), clientRegistration.getRegistrationId(),
 | 
				
			||||||
								ex))
 | 
													ex))
 | 
				
			||||||
				.map((tokenResponse) -> new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(),
 | 
									.map((tokenResponse) -> new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(),
 | 
				
			||||||
						tokenResponse.getAccessToken()));
 | 
											tokenResponse.getAccessToken()));
 | 
				
			||||||
 | 
							// @formatter:on
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private Mono<Jwt> resolveJwtAssertion(OAuth2AuthorizationContext context) {
 | 
				
			||||||
 | 
							// @formatter:off
 | 
				
			||||||
 | 
							return Mono.just(context)
 | 
				
			||||||
 | 
									.map((ctx) -> ctx.getPrincipal().getPrincipal())
 | 
				
			||||||
 | 
									.filter((principal) -> principal instanceof Jwt)
 | 
				
			||||||
 | 
									.cast(Jwt.class);
 | 
				
			||||||
 | 
							// @formatter:on
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private boolean hasTokenExpired(OAuth2Token token) {
 | 
						private boolean hasTokenExpired(OAuth2Token token) {
 | 
				
			||||||
| 
						 | 
					@ -115,6 +128,17 @@ public final class JwtBearerReactiveOAuth2AuthorizedClientProvider implements Re
 | 
				
			||||||
		this.accessTokenResponseClient = accessTokenResponseClient;
 | 
							this.accessTokenResponseClient = accessTokenResponseClient;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Sets the resolver used for resolving the {@link Jwt} assertion.
 | 
				
			||||||
 | 
						 * @param jwtAssertionResolver the resolver used for resolving the {@link Jwt}
 | 
				
			||||||
 | 
						 * assertion
 | 
				
			||||||
 | 
						 * @since 5.7
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void setJwtAssertionResolver(Function<OAuth2AuthorizationContext, Mono<Jwt>> jwtAssertionResolver) {
 | 
				
			||||||
 | 
							Assert.notNull(jwtAssertionResolver, "jwtAssertionResolver cannot be null");
 | 
				
			||||||
 | 
							this.jwtAssertionResolver = jwtAssertionResolver;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Sets the maximum acceptable clock skew, which is used when checking the
 | 
						 * Sets the maximum acceptable clock skew, which is used when checking the
 | 
				
			||||||
	 * {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is
 | 
						 * {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright 2002-2021 the original author or authors.
 | 
					 * Copyright 2002-2022 the original author or authors.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 * you may not use this file except in compliance with the License.
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
| 
						 | 
					@ -18,6 +18,7 @@ package org.springframework.security.oauth2.client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.time.Duration;
 | 
					import java.time.Duration;
 | 
				
			||||||
import java.time.Instant;
 | 
					import java.time.Instant;
 | 
				
			||||||
 | 
					import java.util.function.Function;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.junit.jupiter.api.BeforeEach;
 | 
					import org.junit.jupiter.api.BeforeEach;
 | 
				
			||||||
import org.junit.jupiter.api.Test;
 | 
					import org.junit.jupiter.api.Test;
 | 
				
			||||||
| 
						 | 
					@ -42,6 +43,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
 | 
				
			||||||
import static org.mockito.ArgumentMatchers.any;
 | 
					import static org.mockito.ArgumentMatchers.any;
 | 
				
			||||||
import static org.mockito.BDDMockito.given;
 | 
					import static org.mockito.BDDMockito.given;
 | 
				
			||||||
import static org.mockito.Mockito.mock;
 | 
					import static org.mockito.Mockito.mock;
 | 
				
			||||||
 | 
					import static org.mockito.Mockito.verify;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Tests for {@link JwtBearerOAuth2AuthorizedClientProvider}.
 | 
					 * Tests for {@link JwtBearerOAuth2AuthorizedClientProvider}.
 | 
				
			||||||
| 
						 | 
					@ -87,6 +89,13 @@ public class JwtBearerOAuth2AuthorizedClientProviderTests {
 | 
				
			||||||
				.withMessage("accessTokenResponseClient cannot be null");
 | 
									.withMessage("accessTokenResponseClient cannot be null");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						public void setJwtAssertionResolverWhenNullThenThrowIllegalArgumentException() {
 | 
				
			||||||
 | 
							assertThatIllegalArgumentException()
 | 
				
			||||||
 | 
									.isThrownBy(() -> this.authorizedClientProvider.setJwtAssertionResolver(null))
 | 
				
			||||||
 | 
									.withMessage("jwtAssertionResolver cannot be null");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void setClockSkewWhenNullThenThrowIllegalArgumentException() {
 | 
						public void setClockSkewWhenNullThenThrowIllegalArgumentException() {
 | 
				
			||||||
		// @formatter:off
 | 
							// @formatter:off
 | 
				
			||||||
| 
						 | 
					@ -198,7 +207,7 @@ public class JwtBearerOAuth2AuthorizedClientProviderTests {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void authorizeWhenJwtBearerAndNotAuthorizedAndPrincipalNotJwtThenUnableToAuthorize() {
 | 
						public void authorizeWhenJwtBearerAndNotAuthorizedAndJwtDoesNotResolveThenUnableToAuthorize() {
 | 
				
			||||||
		// @formatter:off
 | 
							// @formatter:off
 | 
				
			||||||
		OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext
 | 
							OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext
 | 
				
			||||||
				.withClientRegistration(this.clientRegistration)
 | 
									.withClientRegistration(this.clientRegistration)
 | 
				
			||||||
| 
						 | 
					@ -209,7 +218,7 @@ public class JwtBearerOAuth2AuthorizedClientProviderTests {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void authorizeWhenJwtBearerAndNotAuthorizedAndPrincipalJwtThenAuthorize() {
 | 
						public void authorizeWhenJwtBearerAndNotAuthorizedAndJwtResolvesThenAuthorize() {
 | 
				
			||||||
		OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build();
 | 
							OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build();
 | 
				
			||||||
		given(this.accessTokenResponseClient.getTokenResponse(any())).willReturn(accessTokenResponse);
 | 
							given(this.accessTokenResponseClient.getTokenResponse(any())).willReturn(accessTokenResponse);
 | 
				
			||||||
		// @formatter:off
 | 
							// @formatter:off
 | 
				
			||||||
| 
						 | 
					@ -224,4 +233,25 @@ public class JwtBearerOAuth2AuthorizedClientProviderTests {
 | 
				
			||||||
		assertThat(authorizedClient.getAccessToken()).isEqualTo(accessTokenResponse.getAccessToken());
 | 
							assertThat(authorizedClient.getAccessToken()).isEqualTo(accessTokenResponse.getAccessToken());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						public void authorizeWhenCustomJwtAssertionResolverSetThenUsed() {
 | 
				
			||||||
 | 
							Function<OAuth2AuthorizationContext, Jwt> jwtAssertionResolver = mock(Function.class);
 | 
				
			||||||
 | 
							given(jwtAssertionResolver.apply(any())).willReturn(this.jwtAssertion);
 | 
				
			||||||
 | 
							this.authorizedClientProvider.setJwtAssertionResolver(jwtAssertionResolver);
 | 
				
			||||||
 | 
							OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build();
 | 
				
			||||||
 | 
							given(this.accessTokenResponseClient.getTokenResponse(any())).willReturn(accessTokenResponse);
 | 
				
			||||||
 | 
							// @formatter:off
 | 
				
			||||||
 | 
							TestingAuthenticationToken principal = new TestingAuthenticationToken("user", "password");
 | 
				
			||||||
 | 
							OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext
 | 
				
			||||||
 | 
									.withClientRegistration(this.clientRegistration)
 | 
				
			||||||
 | 
									.principal(principal)
 | 
				
			||||||
 | 
									.build();
 | 
				
			||||||
 | 
							// @formatter:on
 | 
				
			||||||
 | 
							OAuth2AuthorizedClient authorizedClient = this.authorizedClientProvider.authorize(authorizationContext);
 | 
				
			||||||
 | 
							verify(jwtAssertionResolver).apply(any());
 | 
				
			||||||
 | 
							assertThat(authorizedClient.getClientRegistration()).isSameAs(this.clientRegistration);
 | 
				
			||||||
 | 
							assertThat(authorizedClient.getPrincipalName()).isEqualTo(principal.getName());
 | 
				
			||||||
 | 
							assertThat(authorizedClient.getAccessToken()).isEqualTo(accessTokenResponse.getAccessToken());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright 2002-2021 the original author or authors.
 | 
					 * Copyright 2002-2022 the original author or authors.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 * you may not use this file except in compliance with the License.
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,7 @@ package org.springframework.security.oauth2.client;
 | 
				
			||||||
import java.time.Clock;
 | 
					import java.time.Clock;
 | 
				
			||||||
import java.time.Duration;
 | 
					import java.time.Duration;
 | 
				
			||||||
import java.time.Instant;
 | 
					import java.time.Instant;
 | 
				
			||||||
 | 
					import java.util.function.Function;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.junit.jupiter.api.BeforeEach;
 | 
					import org.junit.jupiter.api.BeforeEach;
 | 
				
			||||||
import org.junit.jupiter.api.Test;
 | 
					import org.junit.jupiter.api.Test;
 | 
				
			||||||
| 
						 | 
					@ -93,6 +94,13 @@ public class JwtBearerReactiveOAuth2AuthorizedClientProviderTests {
 | 
				
			||||||
				.withMessage("accessTokenResponseClient cannot be null");
 | 
									.withMessage("accessTokenResponseClient cannot be null");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						public void setJwtAssertionResolverWhenNullThenThrowIllegalArgumentException() {
 | 
				
			||||||
 | 
							assertThatIllegalArgumentException()
 | 
				
			||||||
 | 
									.isThrownBy(() -> this.authorizedClientProvider.setJwtAssertionResolver(null))
 | 
				
			||||||
 | 
									.withMessage("jwtAssertionResolver cannot be null");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void setClockSkewWhenNullThenThrowIllegalArgumentException() {
 | 
						public void setClockSkewWhenNullThenThrowIllegalArgumentException() {
 | 
				
			||||||
		// @formatter:off
 | 
							// @formatter:off
 | 
				
			||||||
| 
						 | 
					@ -222,7 +230,7 @@ public class JwtBearerReactiveOAuth2AuthorizedClientProviderTests {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void authorizeWhenJwtBearerAndNotAuthorizedAndPrincipalNotJwtThenUnableToAuthorize() {
 | 
						public void authorizeWhenJwtBearerAndNotAuthorizedAndJwtDoesNotResolveThenUnableToAuthorize() {
 | 
				
			||||||
		// @formatter:off
 | 
							// @formatter:off
 | 
				
			||||||
		OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext
 | 
							OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext
 | 
				
			||||||
				.withClientRegistration(this.clientRegistration)
 | 
									.withClientRegistration(this.clientRegistration)
 | 
				
			||||||
| 
						 | 
					@ -251,7 +259,7 @@ public class JwtBearerReactiveOAuth2AuthorizedClientProviderTests {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void authorizeWhenJwtBearerAndNotAuthorizedAndPrincipalJwtThenAuthorize() {
 | 
						public void authorizeWhenJwtBearerAndNotAuthorizedAndJwtResolvesThenAuthorize() {
 | 
				
			||||||
		OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build();
 | 
							OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build();
 | 
				
			||||||
		given(this.accessTokenResponseClient.getTokenResponse(any())).willReturn(Mono.just(accessTokenResponse));
 | 
							given(this.accessTokenResponseClient.getTokenResponse(any())).willReturn(Mono.just(accessTokenResponse));
 | 
				
			||||||
		// @formatter:off
 | 
							// @formatter:off
 | 
				
			||||||
| 
						 | 
					@ -266,4 +274,25 @@ public class JwtBearerReactiveOAuth2AuthorizedClientProviderTests {
 | 
				
			||||||
		assertThat(authorizedClient.getAccessToken()).isEqualTo(accessTokenResponse.getAccessToken());
 | 
							assertThat(authorizedClient.getAccessToken()).isEqualTo(accessTokenResponse.getAccessToken());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						public void authorizeWhenCustomJwtAssertionResolverSetThenUsed() {
 | 
				
			||||||
 | 
							Function<OAuth2AuthorizationContext, Mono<Jwt>> jwtAssertionResolver = mock(Function.class);
 | 
				
			||||||
 | 
							given(jwtAssertionResolver.apply(any())).willReturn(Mono.just(this.jwtAssertion));
 | 
				
			||||||
 | 
							this.authorizedClientProvider.setJwtAssertionResolver(jwtAssertionResolver);
 | 
				
			||||||
 | 
							OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build();
 | 
				
			||||||
 | 
							given(this.accessTokenResponseClient.getTokenResponse(any())).willReturn(Mono.just(accessTokenResponse));
 | 
				
			||||||
 | 
							// @formatter:off
 | 
				
			||||||
 | 
							TestingAuthenticationToken principal = new TestingAuthenticationToken("user", "password");
 | 
				
			||||||
 | 
							OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext
 | 
				
			||||||
 | 
									.withClientRegistration(this.clientRegistration)
 | 
				
			||||||
 | 
									.principal(principal)
 | 
				
			||||||
 | 
									.build();
 | 
				
			||||||
 | 
							// @formatter:on
 | 
				
			||||||
 | 
							OAuth2AuthorizedClient authorizedClient = this.authorizedClientProvider.authorize(authorizationContext).block();
 | 
				
			||||||
 | 
							verify(jwtAssertionResolver).apply(any());
 | 
				
			||||||
 | 
							assertThat(authorizedClient.getClientRegistration()).isSameAs(this.clientRegistration);
 | 
				
			||||||
 | 
							assertThat(authorizedClient.getPrincipalName()).isEqualTo(principal.getName());
 | 
				
			||||||
 | 
							assertThat(authorizedClient.getAccessToken()).isEqualTo(accessTokenResponse.getAccessToken());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue