Browse Source

Remove JwtDecoderRegistry

Fixes gh-4754
Joe Grandja 7 years ago
parent
commit
511d702ee0

+ 1 - 4
config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java

@@ -27,8 +27,6 @@ import org.springframework.security.oauth2.client.authentication.OAuth2LoginAuth
 import org.springframework.security.oauth2.client.endpoint.NimbusAuthorizationCodeTokenResponseClient;
 import org.springframework.security.oauth2.client.endpoint.NimbusAuthorizationCodeTokenResponseClient;
 import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
 import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
 import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest;
 import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest;
-import org.springframework.security.oauth2.client.jwt.JwtDecoderRegistry;
-import org.springframework.security.oauth2.client.jwt.NimbusJwtDecoderRegistry;
 import org.springframework.security.oauth2.client.oidc.authentication.OidcAuthorizationCodeAuthenticationProvider;
 import org.springframework.security.oauth2.client.oidc.authentication.OidcAuthorizationCodeAuthenticationProvider;
 import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
 import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
 import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
 import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
@@ -252,11 +250,10 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>> exten
 		if (oidcUserService == null) {
 		if (oidcUserService == null) {
 			oidcUserService = new OidcUserService();
 			oidcUserService = new OidcUserService();
 		}
 		}
-		JwtDecoderRegistry jwtDecoderRegistry = new NimbusJwtDecoderRegistry();
 
 
 		OidcAuthorizationCodeAuthenticationProvider oidcAuthorizationCodeAuthenticationProvider =
 		OidcAuthorizationCodeAuthenticationProvider oidcAuthorizationCodeAuthenticationProvider =
 			new OidcAuthorizationCodeAuthenticationProvider(
 			new OidcAuthorizationCodeAuthenticationProvider(
-				accessTokenResponseClient, oidcUserService, jwtDecoderRegistry);
+				accessTokenResponseClient, oidcUserService);
 		if (this.userInfoEndpointConfig.userAuthoritiesMapper != null) {
 		if (this.userInfoEndpointConfig.userAuthoritiesMapper != null) {
 			oidcAuthorizationCodeAuthenticationProvider.setAuthoritiesMapper(
 			oidcAuthorizationCodeAuthenticationProvider.setAuthoritiesMapper(
 				this.userInfoEndpointConfig.userAuthoritiesMapper);
 				this.userInfoEndpointConfig.userAuthoritiesMapper);

+ 0 - 33
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jwt/JwtDecoderRegistry.java

@@ -1,33 +0,0 @@
-/*
- * Copyright 2002-2017 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.oauth2.client.jwt;
-
-import org.springframework.security.oauth2.jwt.JwtDecoder;
-import org.springframework.security.oauth2.client.registration.ClientRegistration;
-
-/**
- * A registry of {@link JwtDecoder}'s that are associated to a {@link ClientRegistration}.
- *
- * @author Joe Grandja
- * @since 5.0
- * @see JwtDecoder
- * @see ClientRegistration
- */
-public interface JwtDecoderRegistry {
-
-	JwtDecoder getJwtDecoder(ClientRegistration registration);
-
-}

+ 0 - 59
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jwt/NimbusJwtDecoderRegistry.java

@@ -1,59 +0,0 @@
-/*
- * Copyright 2002-2017 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.oauth2.client.jwt;
-
-import org.springframework.security.oauth2.jwt.JwtDecoder;
-import org.springframework.security.oauth2.jwt.NimbusJwtDecoderJwkSupport;
-import org.springframework.security.oauth2.client.registration.ClientRegistration;
-import org.springframework.util.Assert;
-import org.springframework.util.StringUtils;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * A {@link JwtDecoderRegistry} that creates/manages instances of
- * {@link NimbusJwtDecoderJwkSupport}, which uses the <b>Nimbus JOSE + JWT SDK</b> internally.
- *
- * @author Joe Grandja
- * @since 5.0
- * @see JwtDecoderRegistry
- * @see NimbusJwtDecoderJwkSupport
- * @see <a target="_blank" href="https://connect2id.com/products/nimbus-jose-jwt">Nimbus JOSE + JWT SDK</a>
- */
-public class NimbusJwtDecoderRegistry implements JwtDecoderRegistry {
-	private final Map<String, JwtDecoder> jwtDecoders = new ConcurrentHashMap<>();
-
-	@Override
-	public JwtDecoder getJwtDecoder(ClientRegistration registration) {
-		Assert.notNull(registration, "registration cannot be null");
-		if (!this.jwtDecoders.containsKey(registration.getRegistrationId())) {
-			JwtDecoder jwtDecoder = this.createJwtDecoder(registration);
-			if (jwtDecoder != null) {
-				this.jwtDecoders.put(registration.getRegistrationId(), jwtDecoder);
-			}
-		}
-		return this.jwtDecoders.get(registration.getRegistrationId());
-	}
-
-	private JwtDecoder createJwtDecoder(ClientRegistration registration) {
-		JwtDecoder jwtDecoder = null;
-		if (StringUtils.hasText(registration.getProviderDetails().getJwkSetUri())) {
-			jwtDecoder = new NimbusJwtDecoderJwkSupport(registration.getProviderDetails().getJwkSetUri());
-		}
-		return jwtDecoder;
-	}
-}

+ 26 - 11
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeAuthenticationProvider.java

@@ -23,7 +23,6 @@ import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMap
 import org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationToken;
 import org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationToken;
 import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
 import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
 import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest;
 import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest;
-import org.springframework.security.oauth2.client.jwt.JwtDecoderRegistry;
 import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
 import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
 import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
 import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
 import org.springframework.security.oauth2.client.registration.ClientRegistration;
 import org.springframework.security.oauth2.client.registration.ClientRegistration;
@@ -40,13 +39,17 @@ import org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames
 import org.springframework.security.oauth2.core.oidc.user.OidcUser;
 import org.springframework.security.oauth2.core.oidc.user.OidcUser;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.JwtDecoder;
 import org.springframework.security.oauth2.jwt.JwtDecoder;
+import org.springframework.security.oauth2.jwt.NimbusJwtDecoderJwkSupport;
 import org.springframework.util.Assert;
 import org.springframework.util.Assert;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
 
 
 import java.net.URL;
 import java.net.URL;
 import java.time.Instant;
 import java.time.Instant;
 import java.util.Collection;
 import java.util.Collection;
 import java.util.List;
 import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 
 /**
 /**
  * An implementation of an {@link AuthenticationProvider}
  * An implementation of an {@link AuthenticationProvider}
@@ -74,22 +77,20 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati
 	private static final String INVALID_STATE_PARAMETER_ERROR_CODE = "invalid_state_parameter";
 	private static final String INVALID_STATE_PARAMETER_ERROR_CODE = "invalid_state_parameter";
 	private static final String INVALID_REDIRECT_URI_PARAMETER_ERROR_CODE = "invalid_redirect_uri_parameter";
 	private static final String INVALID_REDIRECT_URI_PARAMETER_ERROR_CODE = "invalid_redirect_uri_parameter";
 	private static final String INVALID_ID_TOKEN_ERROR_CODE = "invalid_id_token";
 	private static final String INVALID_ID_TOKEN_ERROR_CODE = "invalid_id_token";
+	private static final String MISSING_SIGNATURE_VERIFIER_ERROR_CODE = "missing_signature_verifier";
 	private final OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient;
 	private final OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient;
 	private final OAuth2UserService<OidcUserRequest, OidcUser> userService;
 	private final OAuth2UserService<OidcUserRequest, OidcUser> userService;
-	private final JwtDecoderRegistry jwtDecoderRegistry;
+	private final Map<String, JwtDecoder> jwtDecoders = new ConcurrentHashMap<>();
 	private GrantedAuthoritiesMapper authoritiesMapper = (authorities -> authorities);
 	private GrantedAuthoritiesMapper authoritiesMapper = (authorities -> authorities);
 
 
 	public OidcAuthorizationCodeAuthenticationProvider(
 	public OidcAuthorizationCodeAuthenticationProvider(
 		OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient,
 		OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient,
-		OAuth2UserService<OidcUserRequest, OidcUser> userService,
-		JwtDecoderRegistry jwtDecoderRegistry) {
+		OAuth2UserService<OidcUserRequest, OidcUser> userService) {
 
 
 		Assert.notNull(accessTokenResponseClient, "accessTokenResponseClient cannot be null");
 		Assert.notNull(accessTokenResponseClient, "accessTokenResponseClient cannot be null");
 		Assert.notNull(userService, "userService cannot be null");
 		Assert.notNull(userService, "userService cannot be null");
-		Assert.notNull(jwtDecoderRegistry, "jwtDecoderRegistry cannot be null");
 		this.accessTokenResponseClient = accessTokenResponseClient;
 		this.accessTokenResponseClient = accessTokenResponseClient;
 		this.userService = userService;
 		this.userService = userService;
-		this.jwtDecoderRegistry = jwtDecoderRegistry;
 	}
 	}
 
 
 	@Override
 	@Override
@@ -142,11 +143,7 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati
 				"Missing (required) ID Token in Token Response for Client Registration: " + clientRegistration.getRegistrationId());
 				"Missing (required) ID Token in Token Response for Client Registration: " + clientRegistration.getRegistrationId());
 		}
 		}
 
 
-		JwtDecoder jwtDecoder = this.jwtDecoderRegistry.getJwtDecoder(clientRegistration);
-		if (jwtDecoder == null) {
-			throw new IllegalArgumentException("Failed to find a registered JwtDecoder for Client Registration: '" +
-				clientRegistration.getRegistrationId() + "'. Check to ensure you have configured the JwkSet URI.");
-		}
+		JwtDecoder jwtDecoder = this.getJwtDecoder(clientRegistration);
 		Jwt jwt = jwtDecoder.decode((String) accessTokenResponse.getAdditionalParameters().get(OidcParameterNames.ID_TOKEN));
 		Jwt jwt = jwtDecoder.decode((String) accessTokenResponse.getAdditionalParameters().get(OidcParameterNames.ID_TOKEN));
 		OidcIdToken idToken = new OidcIdToken(jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt(), jwt.getClaims());
 		OidcIdToken idToken = new OidcIdToken(jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt(), jwt.getClaims());
 
 
@@ -179,6 +176,24 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati
 		return OAuth2LoginAuthenticationToken.class.isAssignableFrom(authentication);
 		return OAuth2LoginAuthenticationToken.class.isAssignableFrom(authentication);
 	}
 	}
 
 
+	private JwtDecoder getJwtDecoder(ClientRegistration clientRegistration) {
+		JwtDecoder jwtDecoder = this.jwtDecoders.get(clientRegistration.getRegistrationId());
+		if (jwtDecoder == null) {
+			if (!StringUtils.hasText(clientRegistration.getProviderDetails().getJwkSetUri())) {
+				OAuth2Error oauth2Error = new OAuth2Error(
+					MISSING_SIGNATURE_VERIFIER_ERROR_CODE,
+					"Failed to find a Signature Verifier for Client Registration: '" +
+						clientRegistration.getRegistrationId() + "'. Check to ensure you have configured the JwkSet URI.",
+					null
+				);
+				throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
+			}
+			jwtDecoder = new NimbusJwtDecoderJwkSupport(clientRegistration.getProviderDetails().getJwkSetUri());
+			this.jwtDecoders.put(clientRegistration.getRegistrationId(), jwtDecoder);
+		}
+		return jwtDecoder;
+	}
+
 	private void validateIdToken(OidcIdToken idToken, ClientRegistration clientRegistration) {
 	private void validateIdToken(OidcIdToken idToken, ClientRegistration clientRegistration) {
 		// 3.1.3.7  ID Token Validation
 		// 3.1.3.7  ID Token Validation
 		// http://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation
 		// http://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation