Remove JwtDecoderRegistry

Fixes gh-4754
This commit is contained in:
Joe Grandja 2017-10-30 11:31:19 -04:00
parent 727098d6c0
commit 511d702ee0
4 changed files with 27 additions and 107 deletions

View File

@ -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.OAuth2AccessTokenResponseClient;
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.userinfo.OidcUserRequest;
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) {
oidcUserService = new OidcUserService();
}
JwtDecoderRegistry jwtDecoderRegistry = new NimbusJwtDecoderRegistry();
OidcAuthorizationCodeAuthenticationProvider oidcAuthorizationCodeAuthenticationProvider =
new OidcAuthorizationCodeAuthenticationProvider(
accessTokenResponseClient, oidcUserService, jwtDecoderRegistry);
accessTokenResponseClient, oidcUserService);
if (this.userInfoEndpointConfig.userAuthoritiesMapper != null) {
oidcAuthorizationCodeAuthenticationProvider.setAuthoritiesMapper(
this.userInfoEndpointConfig.userAuthoritiesMapper);

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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.endpoint.OAuth2AccessTokenResponseClient;
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.OidcUserService;
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.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoderJwkSupport;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.net.URL;
import java.time.Instant;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 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_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 MISSING_SIGNATURE_VERIFIER_ERROR_CODE = "missing_signature_verifier";
private final OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient;
private final OAuth2UserService<OidcUserRequest, OidcUser> userService;
private final JwtDecoderRegistry jwtDecoderRegistry;
private final Map<String, JwtDecoder> jwtDecoders = new ConcurrentHashMap<>();
private GrantedAuthoritiesMapper authoritiesMapper = (authorities -> authorities);
public OidcAuthorizationCodeAuthenticationProvider(
OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient,
OAuth2UserService<OidcUserRequest, OidcUser> userService,
JwtDecoderRegistry jwtDecoderRegistry) {
OAuth2UserService<OidcUserRequest, OidcUser> userService) {
Assert.notNull(accessTokenResponseClient, "accessTokenResponseClient cannot be null");
Assert.notNull(userService, "userService cannot be null");
Assert.notNull(jwtDecoderRegistry, "jwtDecoderRegistry cannot be null");
this.accessTokenResponseClient = accessTokenResponseClient;
this.userService = userService;
this.jwtDecoderRegistry = jwtDecoderRegistry;
}
@Override
@ -142,11 +143,7 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati
"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));
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);
}
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) {
// 3.1.3.7 ID Token Validation
// http://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation