Browse Source

Polish gh-6415

Joe Grandja 6 năm trước cách đây
mục cha
commit
2a867997e2

+ 1 - 0
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeAuthenticationProvider.java

@@ -66,6 +66,7 @@ import java.util.Map;
  * @see OAuth2AccessTokenResponseClient
  * @see OidcUserService
  * @see OidcUser
+ * @see OidcIdTokenDecoderFactory
  * @see <a target="_blank" href="http://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth">Section 3.1 Authorization Code Grant Flow</a>
  * @see <a target="_blank" href="http://openid.net/specs/openid-connect-core-1_0.html#TokenRequest">Section 3.1.3.1 Token Request</a>
  * @see <a target="_blank" href="http://openid.net/specs/openid-connect-core-1_0.html#TokenResponse">Section 3.1.3.3 Token Response</a>

+ 1 - 0
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeReactiveAuthenticationManager.java

@@ -66,6 +66,7 @@ import java.util.Map;
  * @see ReactiveOAuth2AccessTokenResponseClient
  * @see ReactiveOAuth2UserService
  * @see OAuth2User
+ * @see ReactiveOidcIdTokenDecoderFactory
  * @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-4.1">Section 4.1 Authorization Code Grant Flow</a>
  * @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-4.1.3">Section 4.1.3 Access Token Request</a>
  * @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-4.1.4">Section 4.1.4 Access Token Response</a>

+ 13 - 9
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenDecoderFactory.java

@@ -19,6 +19,7 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio
 import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
 import org.springframework.security.oauth2.core.OAuth2Error;
 import org.springframework.security.oauth2.core.OAuth2TokenValidator;
+import org.springframework.security.oauth2.core.oidc.OidcIdToken;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.JwtDecoder;
 import org.springframework.security.oauth2.jwt.JwtDecoderFactory;
@@ -33,14 +34,16 @@ import java.util.function.Function;
 import static org.springframework.security.oauth2.jwt.JwtProcessors.withJwkSetUri;
 
 /**
- * Provides a default or custom implementation for {@link OAuth2TokenValidator}
+ * A {@link JwtDecoderFactory factory} that provides a {@link JwtDecoder}
+ * used for {@link OidcIdToken} signature verification.
+ * The provided {@link JwtDecoder} is associated to a specific {@link ClientRegistration}.
  *
  * @author Joe Grandja
  * @author Rafael Dominguez
  * @since 5.2
- *
- * @see OAuth2TokenValidator
- * @see Jwt
+ * @see JwtDecoderFactory
+ * @see ClientRegistration
+ * @see OidcIdToken
  */
 public final class OidcIdTokenDecoderFactory implements JwtDecoderFactory<ClientRegistration> {
 	private static final String MISSING_SIGNATURE_VERIFIER_ERROR_CODE = "missing_signature_verifier";
@@ -49,7 +52,7 @@ public final class OidcIdTokenDecoderFactory implements JwtDecoderFactory<Client
 
 	@Override
 	public JwtDecoder createDecoder(ClientRegistration clientRegistration) {
-		Assert.notNull(clientRegistration, "clientRegistration cannot be null.");
+		Assert.notNull(clientRegistration, "clientRegistration cannot be null");
 		return this.jwtDecoders.computeIfAbsent(clientRegistration.getRegistrationId(), key -> {
 			if (!StringUtils.hasText(clientRegistration.getProviderDetails().getJwkSetUri())) {
 				OAuth2Error oauth2Error = new OAuth2Error(
@@ -63,19 +66,20 @@ public final class OidcIdTokenDecoderFactory implements JwtDecoderFactory<Client
 			}
 			String jwkSetUri = clientRegistration.getProviderDetails().getJwkSetUri();
 			NimbusJwtDecoder jwtDecoder = new NimbusJwtDecoder(withJwkSetUri(jwkSetUri).build());
-			OAuth2TokenValidator<Jwt> jwtValidator = jwtValidatorFactory.apply(clientRegistration);
+			OAuth2TokenValidator<Jwt> jwtValidator = this.jwtValidatorFactory.apply(clientRegistration);
 			jwtDecoder.setJwtValidator(jwtValidator);
 			return jwtDecoder;
 		});
 	}
 
 	/**
-	 * Allows user customization for the {@link OAuth2TokenValidator}
+	 * Sets the factory that provides an {@link OAuth2TokenValidator}, which is used by the {@link JwtDecoder}.
+	 * The default is {@link OidcIdTokenValidator}.
 	 *
-	 * @param jwtValidatorFactory
+	 * @param jwtValidatorFactory the factory that provides an {@link OAuth2TokenValidator}
 	 */
 	public final void setJwtValidatorFactory(Function<ClientRegistration, OAuth2TokenValidator<Jwt>> jwtValidatorFactory) {
-		Assert.notNull(jwtValidatorFactory, "jwtValidatorFactory cannot be null.");
+		Assert.notNull(jwtValidatorFactory, "jwtValidatorFactory cannot be null");
 		this.jwtValidatorFactory = jwtValidatorFactory;
 	}
 }

+ 13 - 9
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/ReactiveOidcIdTokenDecoderFactory.java

@@ -19,6 +19,7 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio
 import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
 import org.springframework.security.oauth2.core.OAuth2Error;
 import org.springframework.security.oauth2.core.OAuth2TokenValidator;
+import org.springframework.security.oauth2.core.oidc.OidcIdToken;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder;
 import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder;
@@ -31,14 +32,16 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.Function;
 
 /**
- * Provides a default or custom reactive implementation for {@link OAuth2TokenValidator}
+ * A {@link ReactiveJwtDecoderFactory factory} that provides a {@link ReactiveJwtDecoder}
+ * used for {@link OidcIdToken} signature verification.
+ * The provided {@link ReactiveJwtDecoder} is associated to a specific {@link ClientRegistration}.
  *
  * @author Joe Grandja
  * @author Rafael Dominguez
  * @since 5.2
- *
- * @see OAuth2TokenValidator
- * @see Jwt
+ * @see ReactiveJwtDecoderFactory
+ * @see ClientRegistration
+ * @see OidcIdToken
  */
 public final class ReactiveOidcIdTokenDecoderFactory implements ReactiveJwtDecoderFactory<ClientRegistration> {
 	private static final String MISSING_SIGNATURE_VERIFIER_ERROR_CODE = "missing_signature_verifier";
@@ -47,7 +50,7 @@ public final class ReactiveOidcIdTokenDecoderFactory implements ReactiveJwtDecod
 
 	@Override
 	public ReactiveJwtDecoder createDecoder(ClientRegistration clientRegistration) {
-		Assert.notNull(clientRegistration, "clientRegistration cannot be null.");
+		Assert.notNull(clientRegistration, "clientRegistration cannot be null");
 		return this.jwtDecoders.computeIfAbsent(clientRegistration.getRegistrationId(), key -> {
 			if (!StringUtils.hasText(clientRegistration.getProviderDetails().getJwkSetUri())) {
 				OAuth2Error oauth2Error = new OAuth2Error(
@@ -61,19 +64,20 @@ public final class ReactiveOidcIdTokenDecoderFactory implements ReactiveJwtDecod
 			}
 			NimbusReactiveJwtDecoder jwtDecoder = new NimbusReactiveJwtDecoder(
 					clientRegistration.getProviderDetails().getJwkSetUri());
-			OAuth2TokenValidator<Jwt> jwtValidator = jwtValidatorFactory.apply(clientRegistration);
+			OAuth2TokenValidator<Jwt> jwtValidator = this.jwtValidatorFactory.apply(clientRegistration);
 			jwtDecoder.setJwtValidator(jwtValidator);
 			return jwtDecoder;
 		});
 	}
 
 	/**
-	 * Allows user customization for the {@link OAuth2TokenValidator}
+	 * Sets the factory that provides an {@link OAuth2TokenValidator}, which is used by the {@link ReactiveJwtDecoder}.
+	 * The default is {@link OidcIdTokenValidator}.
 	 *
-	 * @param jwtValidatorFactory
+	 * @param jwtValidatorFactory the factory that provides an {@link OAuth2TokenValidator}
 	 */
 	public final void setJwtValidatorFactory(Function<ClientRegistration, OAuth2TokenValidator<Jwt>> jwtValidatorFactory) {
-		Assert.notNull(jwtValidatorFactory, "jwtValidatorFactory cannot be null.");
+		Assert.notNull(jwtValidatorFactory, "jwtValidatorFactory cannot be null");
 		this.jwtValidatorFactory = jwtValidatorFactory;
 	}
 }

+ 20 - 31
oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenDecoderFactoryTests.java

@@ -23,15 +23,12 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
 import org.springframework.security.oauth2.core.OAuth2TokenValidator;
 import org.springframework.security.oauth2.jwt.Jwt;
 
-import java.time.Duration;
 import java.util.function.Function;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
 
 /**
  * @author Joe Grandja
@@ -45,55 +42,47 @@ public class OidcIdTokenDecoderFactoryTests {
 
 	private OidcIdTokenDecoderFactory idTokenDecoderFactory;
 
+	private Function<ClientRegistration, OAuth2TokenValidator<Jwt>> defaultJwtValidatorFactory = OidcIdTokenValidator::new;
+
 	@Before
 	public void setUp() {
-		idTokenDecoderFactory = new OidcIdTokenDecoderFactory();
+		this.idTokenDecoderFactory = new OidcIdTokenDecoderFactory();
 	}
 
 	@Test
-	public void setJwtValidatorFactoryWhenNullThenThrowIllegalArgumentException(){
-		assertThatThrownBy(()-> idTokenDecoderFactory.setJwtValidatorFactory(null))
+	public void setJwtValidatorFactoryWhenNullThenThrowIllegalArgumentException() {
+		assertThatThrownBy(() -> this.idTokenDecoderFactory.setJwtValidatorFactory(null))
 				.isInstanceOf(IllegalArgumentException.class);
 	}
 
 	@Test
-	public void createDecoderWhenClientRegistrationNullThenThrowIllegalArgumentException(){
-		assertThatThrownBy(() -> idTokenDecoderFactory.createDecoder(null))
+	public void createDecoderWhenClientRegistrationNullThenThrowIllegalArgumentException() {
+		assertThatThrownBy(() -> this.idTokenDecoderFactory.createDecoder(null))
 				.isInstanceOf(IllegalArgumentException.class);
 	}
 
 	@Test
-	public void createDecoderWhenJwkSetUriEmptyThenThrowOAuth2AuthenticationException(){
-		assertThatThrownBy(()-> idTokenDecoderFactory.createDecoder(registration.jwkSetUri(null).build()))
-		.isInstanceOf(OAuth2AuthenticationException.class);
+	public void createDecoderWhenJwkSetUriEmptyThenThrowOAuth2AuthenticationException() {
+		assertThatThrownBy(() -> this.idTokenDecoderFactory.createDecoder(this.registration.jwkSetUri(null).build()))
+				.isInstanceOf(OAuth2AuthenticationException.class);
 	}
 
 	@Test
-	public void createDecoderWhenClientRegistrationValidThenReturnDecoder(){
-		assertThat(idTokenDecoderFactory.createDecoder(registration.build()))
+	public void createDecoderWhenClientRegistrationValidThenReturnDecoder() {
+		assertThat(this.idTokenDecoderFactory.createDecoder(this.registration.build()))
 				.isNotNull();
 	}
 
 	@Test
-	public void createDecoderWhenCustomJwtValidatorFactorySetThenApplied(){
-		Function<ClientRegistration, OAuth2TokenValidator<Jwt>> customValidator = mock(Function.class);
-		idTokenDecoderFactory.setJwtValidatorFactory(customValidator);
+	public void createDecoderWhenCustomJwtValidatorFactorySetThenApplied() {
+		Function<ClientRegistration, OAuth2TokenValidator<Jwt>> customJwtValidatorFactory = mock(Function.class);
+		this.idTokenDecoderFactory.setJwtValidatorFactory(customJwtValidatorFactory);
 
-		when(customValidator.apply(any(ClientRegistration.class)))
-				.thenReturn(customJwtValidatorFactory.apply(registration.build()));
+		when(customJwtValidatorFactory.apply(any(ClientRegistration.class)))
+				.thenReturn(this.defaultJwtValidatorFactory.apply(this.registration.build()));
 
-		idTokenDecoderFactory.createDecoder(registration.build());
+		this.idTokenDecoderFactory.createDecoder(this.registration.build());
 
-		verify(customValidator).apply(any(ClientRegistration.class));
+		verify(customJwtValidatorFactory).apply(any(ClientRegistration.class));
 	}
-
-	private Function<ClientRegistration, OAuth2TokenValidator<Jwt>> customJwtValidatorFactory = (c) -> {
-		OidcIdTokenValidator idTokenValidator = new OidcIdTokenValidator(c);
-		if (c.getRegistrationId().equals("registration-id1")) {
-			idTokenValidator.setClockSkew(Duration.ofSeconds(30));
-		} else if (c.getRegistrationId().equals("registration-id2")) {
-			idTokenValidator.setClockSkew(Duration.ofSeconds(70));
-		}
-		return idTokenValidator;
-	};
 }

+ 19 - 30
oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/ReactiveOidcIdTokenDecoderFactoryTests.java

@@ -23,15 +23,12 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
 import org.springframework.security.oauth2.core.OAuth2TokenValidator;
 import org.springframework.security.oauth2.jwt.Jwt;
 
-import java.time.Duration;
 import java.util.function.Function;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
 
 /**
  * @author Joe Grandja
@@ -45,55 +42,47 @@ public class ReactiveOidcIdTokenDecoderFactoryTests {
 
 	private ReactiveOidcIdTokenDecoderFactory idTokenDecoderFactory;
 
+	private Function<ClientRegistration, OAuth2TokenValidator<Jwt>> defaultJwtValidatorFactory = OidcIdTokenValidator::new;
+
 	@Before
 	public void setUp() {
-		idTokenDecoderFactory = new ReactiveOidcIdTokenDecoderFactory();
+		this.idTokenDecoderFactory = new ReactiveOidcIdTokenDecoderFactory();
 	}
 
 	@Test
-	public void setJwtValidatorFactoryWhenNullThenThrowIllegalArgumentException(){
-		assertThatThrownBy(()-> idTokenDecoderFactory.setJwtValidatorFactory(null))
+	public void setJwtValidatorFactoryWhenNullThenThrowIllegalArgumentException() {
+		assertThatThrownBy(() -> this.idTokenDecoderFactory.setJwtValidatorFactory(null))
 				.isInstanceOf(IllegalArgumentException.class);
 	}
 
 	@Test
-	public void createDecoderWhenClientRegistrationNullThenThrowIllegalArgumentException(){
-		assertThatThrownBy(() -> idTokenDecoderFactory.createDecoder(null))
+	public void createDecoderWhenClientRegistrationNullThenThrowIllegalArgumentException() {
+		assertThatThrownBy(() -> this.idTokenDecoderFactory.createDecoder(null))
 				.isInstanceOf(IllegalArgumentException.class);
 	}
 
 	@Test
-	public void createDecoderWhenJwkSetUriEmptyThenThrowOAuth2AuthenticationException(){
-		assertThatThrownBy(()-> idTokenDecoderFactory.createDecoder(registration.jwkSetUri(null).build()))
+	public void createDecoderWhenJwkSetUriEmptyThenThrowOAuth2AuthenticationException() {
+		assertThatThrownBy(() -> this.idTokenDecoderFactory.createDecoder(this.registration.jwkSetUri(null).build()))
 				.isInstanceOf(OAuth2AuthenticationException.class);
 	}
 
 	@Test
-	public void createDecoderWhenClientRegistrationValidThenReturnDecoder(){
-		assertThat(idTokenDecoderFactory.createDecoder(registration.build()))
+	public void createDecoderWhenClientRegistrationValidThenReturnDecoder() {
+		assertThat(this.idTokenDecoderFactory.createDecoder(this.registration.build()))
 				.isNotNull();
 	}
 
 	@Test
-	public void createDecoderWhenCustomJwtValidatorFactorySetThenApplied(){
-		Function<ClientRegistration, OAuth2TokenValidator<Jwt>> customValidator = mock(Function.class);
-		idTokenDecoderFactory.setJwtValidatorFactory(customValidator);
+	public void createDecoderWhenCustomJwtValidatorFactorySetThenApplied() {
+		Function<ClientRegistration, OAuth2TokenValidator<Jwt>> customJwtValidatorFactory = mock(Function.class);
+		this.idTokenDecoderFactory.setJwtValidatorFactory(customJwtValidatorFactory);
 
-		when(customValidator.apply(any(ClientRegistration.class)))
-				.thenReturn(customJwtValidatorFactory.apply(registration.build()));
+		when(customJwtValidatorFactory.apply(any(ClientRegistration.class)))
+				.thenReturn(this.defaultJwtValidatorFactory.apply(this.registration.build()));
 
-		idTokenDecoderFactory.createDecoder(registration.build());
+		this.idTokenDecoderFactory.createDecoder(this.registration.build());
 
-		verify(customValidator).apply(any(ClientRegistration.class));
+		verify(customJwtValidatorFactory).apply(any(ClientRegistration.class));
 	}
-
-	private Function<ClientRegistration, OAuth2TokenValidator<Jwt>> customJwtValidatorFactory = (c) -> {
-			OidcIdTokenValidator idTokenValidator = new OidcIdTokenValidator(c);
-			if (c.getRegistrationId().equals("registration-id1")) {
-				idTokenValidator.setClockSkew(Duration.ofSeconds(30));
-			} else if (c.getRegistrationId().equals("registration-id2")) {
-				idTokenValidator.setClockSkew(Duration.ofSeconds(70));
-			}
-			return idTokenValidator;
-		};
 }