parent
727098d6c0
commit
511d702ee0
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue