Polish gh-143
This commit is contained in:
parent
6a5e277a11
commit
ab591dc39d
@ -54,9 +54,7 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
|
|||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -66,12 +64,16 @@ import java.util.Map;
|
|||||||
* An {@link AbstractHttpConfigurer} for OAuth 2.0 Authorization Server support.
|
* An {@link AbstractHttpConfigurer} for OAuth 2.0 Authorization Server support.
|
||||||
*
|
*
|
||||||
* @author Joe Grandja
|
* @author Joe Grandja
|
||||||
|
* @author Daniel Garnier-Moiroux
|
||||||
* @since 0.0.1
|
* @since 0.0.1
|
||||||
* @see AbstractHttpConfigurer
|
* @see AbstractHttpConfigurer
|
||||||
* @see RegisteredClientRepository
|
* @see RegisteredClientRepository
|
||||||
* @see OAuth2AuthorizationService
|
* @see OAuth2AuthorizationService
|
||||||
* @see OAuth2AuthorizationEndpointFilter
|
* @see OAuth2AuthorizationEndpointFilter
|
||||||
* @see OAuth2TokenEndpointFilter
|
* @see OAuth2TokenEndpointFilter
|
||||||
|
* @see OAuth2TokenRevocationEndpointFilter
|
||||||
|
* @see JwkSetEndpointFilter
|
||||||
|
* @see OidcProviderConfigurationEndpointFilter
|
||||||
* @see OAuth2ClientAuthenticationFilter
|
* @see OAuth2ClientAuthenticationFilter
|
||||||
*/
|
*/
|
||||||
public final class OAuth2AuthorizationServerConfigurer<B extends HttpSecurityBuilder<B>>
|
public final class OAuth2AuthorizationServerConfigurer<B extends HttpSecurityBuilder<B>>
|
||||||
@ -147,15 +149,17 @@ public final class OAuth2AuthorizationServerConfigurer<B extends HttpSecurityBui
|
|||||||
* @return a {@code List} of {@link RequestMatcher}'s for the authorization server endpoints
|
* @return a {@code List} of {@link RequestMatcher}'s for the authorization server endpoints
|
||||||
*/
|
*/
|
||||||
public List<RequestMatcher> getEndpointMatchers() {
|
public List<RequestMatcher> getEndpointMatchers() {
|
||||||
// TODO: use ProviderSettings instead
|
// TODO Initialize matchers using URI's from ProviderSettings
|
||||||
return Arrays.asList(this.authorizationEndpointMatcher, this.tokenEndpointMatcher,
|
return Arrays.asList(this.authorizationEndpointMatcher, this.tokenEndpointMatcher,
|
||||||
this.tokenRevocationEndpointMatcher, this.jwkSetEndpointMatcher, this.oidcProviderConfigurationEndpointMatcher);
|
this.tokenRevocationEndpointMatcher, this.jwkSetEndpointMatcher,
|
||||||
|
this.oidcProviderConfigurationEndpointMatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(B builder) {
|
public void init(B builder) {
|
||||||
ProviderSettings providerSettings = getProviderSettings(builder);
|
ProviderSettings providerSettings = getProviderSettings(builder);
|
||||||
validateProviderSettings(providerSettings);
|
validateProviderSettings(providerSettings);
|
||||||
|
|
||||||
OAuth2ClientAuthenticationProvider clientAuthenticationProvider =
|
OAuth2ClientAuthenticationProvider clientAuthenticationProvider =
|
||||||
new OAuth2ClientAuthenticationProvider(
|
new OAuth2ClientAuthenticationProvider(
|
||||||
getRegisteredClientRepository(builder),
|
getRegisteredClientRepository(builder),
|
||||||
@ -208,14 +212,16 @@ public final class OAuth2AuthorizationServerConfigurer<B extends HttpSecurityBui
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configure(B builder) {
|
public void configure(B builder) {
|
||||||
if (getProviderSettings(builder).issuer() != null) {
|
ProviderSettings providerSettings = getProviderSettings(builder);
|
||||||
OidcProviderConfigurationEndpointFilter oidcProviderConfigurationEndpointFilter = new OidcProviderConfigurationEndpointFilter(getProviderSettings(builder));
|
if (providerSettings.issuer() != null) {
|
||||||
|
OidcProviderConfigurationEndpointFilter oidcProviderConfigurationEndpointFilter =
|
||||||
|
new OidcProviderConfigurationEndpointFilter(providerSettings);
|
||||||
builder.addFilterBefore(postProcess(oidcProviderConfigurationEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
|
builder.addFilterBefore(postProcess(oidcProviderConfigurationEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
JwkSetEndpointFilter jwkSetEndpointFilter = new JwkSetEndpointFilter(
|
JwkSetEndpointFilter jwkSetEndpointFilter = new JwkSetEndpointFilter(
|
||||||
getKeySource(builder),
|
getKeySource(builder),
|
||||||
getProviderSettings(builder).jwkSetEndpoint());
|
providerSettings.jwksEndpoint());
|
||||||
builder.addFilterBefore(postProcess(jwkSetEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
|
builder.addFilterBefore(postProcess(jwkSetEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
|
||||||
|
|
||||||
AuthenticationManager authenticationManager = builder.getSharedObject(AuthenticationManager.class);
|
AuthenticationManager authenticationManager = builder.getSharedObject(AuthenticationManager.class);
|
||||||
@ -230,20 +236,20 @@ public final class OAuth2AuthorizationServerConfigurer<B extends HttpSecurityBui
|
|||||||
new OAuth2AuthorizationEndpointFilter(
|
new OAuth2AuthorizationEndpointFilter(
|
||||||
getRegisteredClientRepository(builder),
|
getRegisteredClientRepository(builder),
|
||||||
getAuthorizationService(builder),
|
getAuthorizationService(builder),
|
||||||
getProviderSettings(builder).authorizationEndpoint());
|
providerSettings.authorizationEndpoint());
|
||||||
builder.addFilterBefore(postProcess(authorizationEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
|
builder.addFilterBefore(postProcess(authorizationEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
|
||||||
|
|
||||||
OAuth2TokenEndpointFilter tokenEndpointFilter =
|
OAuth2TokenEndpointFilter tokenEndpointFilter =
|
||||||
new OAuth2TokenEndpointFilter(
|
new OAuth2TokenEndpointFilter(
|
||||||
authenticationManager,
|
authenticationManager,
|
||||||
getAuthorizationService(builder),
|
getAuthorizationService(builder),
|
||||||
getProviderSettings(builder).tokenEndpoint());
|
providerSettings.tokenEndpoint());
|
||||||
builder.addFilterAfter(postProcess(tokenEndpointFilter), FilterSecurityInterceptor.class);
|
builder.addFilterAfter(postProcess(tokenEndpointFilter), FilterSecurityInterceptor.class);
|
||||||
|
|
||||||
OAuth2TokenRevocationEndpointFilter tokenRevocationEndpointFilter =
|
OAuth2TokenRevocationEndpointFilter tokenRevocationEndpointFilter =
|
||||||
new OAuth2TokenRevocationEndpointFilter(
|
new OAuth2TokenRevocationEndpointFilter(
|
||||||
authenticationManager,
|
authenticationManager,
|
||||||
getProviderSettings(builder).tokenRevocationEndpoint());
|
providerSettings.tokenRevocationEndpoint());
|
||||||
builder.addFilterAfter(postProcess(tokenRevocationEndpointFilter), OAuth2TokenEndpointFilter.class);
|
builder.addFilterAfter(postProcess(tokenRevocationEndpointFilter), OAuth2TokenEndpointFilter.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,8 +329,8 @@ public final class OAuth2AuthorizationServerConfigurer<B extends HttpSecurityBui
|
|||||||
if (providerSettings.issuer() != null) {
|
if (providerSettings.issuer() != null) {
|
||||||
try {
|
try {
|
||||||
new URI(providerSettings.issuer()).toURL();
|
new URI(providerSettings.issuer()).toURL();
|
||||||
} catch (MalformedURLException | URISyntaxException e) {
|
} catch (Exception ex) {
|
||||||
throw new IllegalArgumentException("issuer must be a valid URL");
|
throw new IllegalArgumentException("issuer must be a valid URL", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2020 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
|
|
||||||
*
|
|
||||||
* https://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.core.converter;
|
|
||||||
|
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
|
||||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
|
||||||
import org.springframework.core.convert.converter.GenericConverter;
|
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO
|
|
||||||
* This class is temporary and will be removed after upgrading to Spring Security 5.5.0 GA.
|
|
||||||
*
|
|
||||||
* @author Daniel Garnier-Moiroux
|
|
||||||
* @since 0.1.0
|
|
||||||
* @see <a target="_blank" href="https://github.com/spring-projects/spring-security/pull/9146">Issue gh-9146</a>
|
|
||||||
*/
|
|
||||||
final public class ObjectToSetStringConverter2 implements ConditionalGenericConverter {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<GenericConverter.ConvertiblePair> getConvertibleTypes() {
|
|
||||||
Set<GenericConverter.ConvertiblePair> convertibleTypes = new LinkedHashSet<>();
|
|
||||||
convertibleTypes.add(new GenericConverter.ConvertiblePair(Object.class, Set.class));
|
|
||||||
return convertibleTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
|
||||||
if (targetType.getElementTypeDescriptor() == null
|
|
||||||
|| targetType.getElementTypeDescriptor().getType().equals(String.class) || sourceType == null
|
|
||||||
|| ClassUtils.isAssignable(sourceType.getType(), targetType.getElementTypeDescriptor().getType())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
|
||||||
if (source == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (source instanceof Set) {
|
|
||||||
Set<?> sourceList = (Set<?>) source;
|
|
||||||
for (Object entry: sourceList) {
|
|
||||||
if (entry instanceof String) {
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (source instanceof Collection) {
|
|
||||||
Collection<String> results = new LinkedHashSet<>();
|
|
||||||
for (Object object : ((Collection<?>) source)) {
|
|
||||||
if (object != null) {
|
|
||||||
results.add(object.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
return Collections.singleton(source.toString());
|
|
||||||
}
|
|
||||||
}
|
|
@ -23,9 +23,9 @@ import java.net.URI;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,13 +39,11 @@ import java.util.function.Consumer;
|
|||||||
* @see OidcProviderMetadataClaimAccessor
|
* @see OidcProviderMetadataClaimAccessor
|
||||||
* @see <a target="_blank" href="https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse">4.2. OpenID Provider Configuration Response</a>
|
* @see <a target="_blank" href="https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse">4.2. OpenID Provider Configuration Response</a>
|
||||||
*/
|
*/
|
||||||
public class OidcProviderConfiguration implements OidcProviderMetadataClaimAccessor, Serializable {
|
public final class OidcProviderConfiguration implements OidcProviderMetadataClaimAccessor, Serializable {
|
||||||
private static final long serialVersionUID = Version.SERIAL_VERSION_UID;
|
private static final long serialVersionUID = Version.SERIAL_VERSION_UID;
|
||||||
|
|
||||||
private final Map<String, Object> claims;
|
private final Map<String, Object> claims;
|
||||||
|
|
||||||
private OidcProviderConfiguration(Map<String, Object> claims) {
|
private OidcProviderConfiguration(Map<String, Object> claims) {
|
||||||
Assert.notEmpty(claims, "claims cannot be empty");
|
|
||||||
this.claims = Collections.unmodifiableMap(new LinkedHashMap<>(claims));
|
this.claims = Collections.unmodifiableMap(new LinkedHashMap<>(claims));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +58,7 @@ public class OidcProviderConfiguration implements OidcProviderMetadataClaimAcces
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new empty {@link Builder}.
|
* Constructs a new {@link Builder} with empty claims.
|
||||||
*
|
*
|
||||||
* @return the {@link Builder}
|
* @return the {@link Builder}
|
||||||
*/
|
*/
|
||||||
@ -68,7 +66,6 @@ public class OidcProviderConfiguration implements OidcProviderMetadataClaimAcces
|
|||||||
return new Builder();
|
return new Builder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new {@link Builder} with the provided claims.
|
* Constructs a new {@link Builder} with the provided claims.
|
||||||
*
|
*
|
||||||
@ -82,13 +79,8 @@ public class OidcProviderConfiguration implements OidcProviderMetadataClaimAcces
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Helps configure an {@link OidcProviderConfiguration}
|
* Helps configure an {@link OidcProviderConfiguration}
|
||||||
*
|
|
||||||
* @author Daniel Garnier-Moiroux
|
|
||||||
* @since 0.1.0
|
|
||||||
* @see <a target="_blank" href="https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata">OpenID Connect Discovery 1.0</a>
|
|
||||||
* for required claims
|
|
||||||
*/
|
*/
|
||||||
public static final class Builder {
|
public static class Builder {
|
||||||
private final Map<String, Object> claims = new LinkedHashMap<>();
|
private final Map<String, Object> claims = new LinkedHashMap<>();
|
||||||
|
|
||||||
private Builder() {
|
private Builder() {
|
||||||
@ -97,7 +89,7 @@ public class OidcProviderConfiguration implements OidcProviderMetadataClaimAcces
|
|||||||
/**
|
/**
|
||||||
* Use this {@code issuer} in the resulting {@link OidcProviderConfiguration}, REQUIRED.
|
* Use this {@code issuer} in the resulting {@link OidcProviderConfiguration}, REQUIRED.
|
||||||
*
|
*
|
||||||
* @param issuer the issuer URI
|
* @param issuer the URL of the OpenID Provider's Issuer Identifier
|
||||||
* @return the {@link Builder} for further configuration
|
* @return the {@link Builder} for further configuration
|
||||||
*/
|
*/
|
||||||
public Builder issuer(String issuer) {
|
public Builder issuer(String issuer) {
|
||||||
@ -124,6 +116,29 @@ public class OidcProviderConfiguration implements OidcProviderMetadataClaimAcces
|
|||||||
return claim(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT, tokenEndpoint);
|
return claim(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT, tokenEndpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add this Authentication Method to the collection of {@code token_endpoint_auth_methods_supported}
|
||||||
|
* in the resulting {@link OidcProviderConfiguration}, OPTIONAL.
|
||||||
|
*
|
||||||
|
* @param authenticationMethod the OAuth 2.0 Authentication Method supported by the Token endpoint
|
||||||
|
* @return the {@link Builder} for further configuration
|
||||||
|
*/
|
||||||
|
public Builder tokenEndpointAuthenticationMethod(String authenticationMethod) {
|
||||||
|
addClaimToClaimList(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT_AUTH_METHODS_SUPPORTED, authenticationMethod);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@code Consumer} of the Token Endpoint Authentication Method(s) allowing the ability to add, replace, or remove.
|
||||||
|
*
|
||||||
|
* @param authenticationMethodsConsumer a {@code Consumer} of the Token Endpoint Authentication Method(s)
|
||||||
|
* @return the {@link Builder} for further configuration
|
||||||
|
*/
|
||||||
|
public Builder tokenEndpointAuthenticationMethods(Consumer<List<String>> authenticationMethodsConsumer) {
|
||||||
|
acceptClaimValues(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT_AUTH_METHODS_SUPPORTED, authenticationMethodsConsumer);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use this {@code jwks_uri} in the resulting {@link OidcProviderConfiguration}, REQUIRED.
|
* Use this {@code jwks_uri} in the resulting {@link OidcProviderConfiguration}, REQUIRED.
|
||||||
*
|
*
|
||||||
@ -138,11 +153,11 @@ public class OidcProviderConfiguration implements OidcProviderMetadataClaimAcces
|
|||||||
* Add this Response Type to the collection of {@code response_types_supported} in the resulting
|
* Add this Response Type to the collection of {@code response_types_supported} in the resulting
|
||||||
* {@link OidcProviderConfiguration}, REQUIRED.
|
* {@link OidcProviderConfiguration}, REQUIRED.
|
||||||
*
|
*
|
||||||
* @param responseType the OAuth 2.0 {@code response_type} values that the OpenID Provider supports
|
* @param responseType the OAuth 2.0 {@code response_type} value that the OpenID Provider supports
|
||||||
* @return the {@link Builder} for further configuration
|
* @return the {@link Builder} for further configuration
|
||||||
*/
|
*/
|
||||||
public Builder responseType(String responseType) {
|
public Builder responseType(String responseType) {
|
||||||
addClaimToClaimSet(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED, responseType);
|
addClaimToClaimList(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED, responseType);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,54 +167,8 @@ public class OidcProviderConfiguration implements OidcProviderMetadataClaimAcces
|
|||||||
* @param responseTypesConsumer a {@code Consumer} of the Response Type(s)
|
* @param responseTypesConsumer a {@code Consumer} of the Response Type(s)
|
||||||
* @return the {@link Builder} for further configuration
|
* @return the {@link Builder} for further configuration
|
||||||
*/
|
*/
|
||||||
public Builder responseTypes(Consumer<Set<String>> responseTypesConsumer) {
|
public Builder responseTypes(Consumer<List<String>> responseTypesConsumer) {
|
||||||
applyToClaim(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED, responseTypesConsumer);
|
acceptClaimValues(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED, responseTypesConsumer);
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add this Subject Type to the collection of {@code subject_types_supported} in the resulting
|
|
||||||
* {@link OidcProviderConfiguration}, REQUIRED.
|
|
||||||
*
|
|
||||||
* @param subjectType the Subject Identifiers that the OpenID Provider supports
|
|
||||||
* @return the {@link Builder} for further configuration
|
|
||||||
*/
|
|
||||||
public Builder subjectType(String subjectType) {
|
|
||||||
addClaimToClaimSet(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED, subjectType);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@code Consumer} of the Subject Types(s) allowing the ability to add, replace, or remove.
|
|
||||||
*
|
|
||||||
* @param subjectTypesConsumer a {@code Consumer} of the Subject Types(s)
|
|
||||||
* @return the {@link Builder} for further configuration
|
|
||||||
*/
|
|
||||||
public Builder subjectTypes(Consumer<Set<String>> subjectTypesConsumer) {
|
|
||||||
applyToClaim(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED, subjectTypesConsumer);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add this Scope to the collection of {@code scopes_supported} in the resulting
|
|
||||||
* {@link OidcProviderConfiguration}, RECOMMENDED.
|
|
||||||
*
|
|
||||||
* @param scope the OAuth 2.0 {@code scopes} values that the OpenID Provider supports
|
|
||||||
* @return the {@link Builder} for further configuration
|
|
||||||
*/
|
|
||||||
public Builder scope(String scope) {
|
|
||||||
addClaimToClaimSet(OidcProviderMetadataClaimNames.SCOPES_SUPPORTED, scope);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@code Consumer} of the Scopes(s) allowing the ability to add, replace, or remove.
|
|
||||||
*
|
|
||||||
* @param scopesConsumer a {@code Consumer} of the Scopes(s)
|
|
||||||
* @return the {@link Builder} for further configuration
|
|
||||||
*/
|
|
||||||
public Builder scopes(Consumer<Set<String>> scopesConsumer) {
|
|
||||||
applyToClaim(OidcProviderMetadataClaimNames.SCOPES_SUPPORTED, scopesConsumer);
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,11 +176,11 @@ public class OidcProviderConfiguration implements OidcProviderMetadataClaimAcces
|
|||||||
* Add this Grant Type to the collection of {@code grant_types_supported} in the resulting
|
* Add this Grant Type to the collection of {@code grant_types_supported} in the resulting
|
||||||
* {@link OidcProviderConfiguration}, OPTIONAL.
|
* {@link OidcProviderConfiguration}, OPTIONAL.
|
||||||
*
|
*
|
||||||
* @param grantType the OAuth 2.0 {@code grant_type} values that the OpenID Provider supports
|
* @param grantType the OAuth 2.0 {@code grant_type} value that the OpenID Provider supports
|
||||||
* @return the {@link Builder} for further configuration
|
* @return the {@link Builder} for further configuration
|
||||||
*/
|
*/
|
||||||
public Builder grantType(String grantType) {
|
public Builder grantType(String grantType) {
|
||||||
addClaimToClaimSet(OidcProviderMetadataClaimNames.GRANT_TYPES_SUPPORTED, grantType);
|
addClaimToClaimList(OidcProviderMetadataClaimNames.GRANT_TYPES_SUPPORTED, grantType);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,39 +190,62 @@ public class OidcProviderConfiguration implements OidcProviderMetadataClaimAcces
|
|||||||
* @param grantTypesConsumer a {@code Consumer} of the Grant Type(s)
|
* @param grantTypesConsumer a {@code Consumer} of the Grant Type(s)
|
||||||
* @return the {@link Builder} for further configuration
|
* @return the {@link Builder} for further configuration
|
||||||
*/
|
*/
|
||||||
public Builder grantTypes(Consumer<Set<String>> grantTypesConsumer) {
|
public Builder grantTypes(Consumer<List<String>> grantTypesConsumer) {
|
||||||
applyToClaim(OidcProviderMetadataClaimNames.GRANT_TYPES_SUPPORTED, grantTypesConsumer);
|
acceptClaimValues(OidcProviderMetadataClaimNames.GRANT_TYPES_SUPPORTED, grantTypesConsumer);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add this Authentication Method to the collection of {@code token_endpoint_auth_methods_supported}
|
* Add this Subject Type to the collection of {@code subject_types_supported} in the resulting
|
||||||
* in the resulting {@link OidcProviderConfiguration}, OPTIONAL.
|
* {@link OidcProviderConfiguration}, REQUIRED.
|
||||||
*
|
*
|
||||||
* @param authenticationMethod the OAuth 2.0 Authentication Method supported by the Token endpoint
|
* @param subjectType the Subject Type that the OpenID Provider supports
|
||||||
* @return the {@link Builder} for further configuration
|
* @return the {@link Builder} for further configuration
|
||||||
*/
|
*/
|
||||||
public Builder tokenEndpointAuthenticationMethod(String authenticationMethod) {
|
public Builder subjectType(String subjectType) {
|
||||||
addClaimToClaimSet(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT_AUTH_METHODS_SUPPORTED, authenticationMethod);
|
addClaimToClaimList(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED, subjectType);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@code Consumer} of the Token Endpoint Authentication Method(s) allowing the ability to add, replace, or remove.
|
* A {@code Consumer} of the Subject Types(s) allowing the ability to add, replace, or remove.
|
||||||
*
|
*
|
||||||
* @param authenticationMethodsConsumer a {@code Consumer} of the Token Endpoint Authentication Method(s)
|
* @param subjectTypesConsumer a {@code Consumer} of the Subject Types(s)
|
||||||
* @return the {@link Builder} for further configuration
|
* @return the {@link Builder} for further configuration
|
||||||
*/
|
*/
|
||||||
public Builder tokenEndpointAuthenticationMethods(Consumer<Set<String>> authenticationMethodsConsumer) {
|
public Builder subjectTypes(Consumer<List<String>> subjectTypesConsumer) {
|
||||||
applyToClaim(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT_AUTH_METHODS_SUPPORTED, authenticationMethodsConsumer);
|
acceptClaimValues(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED, subjectTypesConsumer);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use this claim in the resulting {@link OidcProviderConfiguration}
|
* Add this Scope to the collection of {@code scopes_supported} in the resulting
|
||||||
|
* {@link OidcProviderConfiguration}, RECOMMENDED.
|
||||||
*
|
*
|
||||||
* @param name The claim name
|
* @param scope the OAuth 2.0 {@code scope} value that the OpenID Provider supports
|
||||||
* @param value The claim value
|
* @return the {@link Builder} for further configuration
|
||||||
|
*/
|
||||||
|
public Builder scope(String scope) {
|
||||||
|
addClaimToClaimList(OidcProviderMetadataClaimNames.SCOPES_SUPPORTED, scope);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@code Consumer} of the Scopes(s) allowing the ability to add, replace, or remove.
|
||||||
|
*
|
||||||
|
* @param scopesConsumer a {@code Consumer} of the Scopes(s)
|
||||||
|
* @return the {@link Builder} for further configuration
|
||||||
|
*/
|
||||||
|
public Builder scopes(Consumer<List<String>> scopesConsumer) {
|
||||||
|
acceptClaimValues(OidcProviderMetadataClaimNames.SCOPES_SUPPORTED, scopesConsumer);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this claim in the resulting {@link OidcProviderConfiguration}.
|
||||||
|
*
|
||||||
|
* @param name the claim name
|
||||||
|
* @param value the claim value
|
||||||
* @return the {@link Builder} for further configuration
|
* @return the {@link Builder} for further configuration
|
||||||
*/
|
*/
|
||||||
public Builder claim(String name, Object value) {
|
public Builder claim(String name, Object value) {
|
||||||
@ -267,7 +259,7 @@ public class OidcProviderConfiguration implements OidcProviderMetadataClaimAcces
|
|||||||
* Provides access to every {@link #claim(String, Object)} declared so far with
|
* Provides access to every {@link #claim(String, Object)} declared so far with
|
||||||
* the possibility to add, replace, or remove.
|
* the possibility to add, replace, or remove.
|
||||||
*
|
*
|
||||||
* @param claimsConsumer the consumer
|
* @param claimsConsumer a {@code Consumer} of the claims
|
||||||
* @return the {@link Builder} for further configurations
|
* @return the {@link Builder} for further configurations
|
||||||
*/
|
*/
|
||||||
public Builder claims(Consumer<Map<String, Object>> claimsConsumer) {
|
public Builder claims(Consumer<Map<String, Object>> claimsConsumer) {
|
||||||
@ -276,15 +268,13 @@ public class OidcProviderConfiguration implements OidcProviderMetadataClaimAcces
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate the claims and build the {@link OidcProviderConfiguration}. The following claims are REQUIRED:
|
* Validate the claims and build the {@link OidcProviderConfiguration}.
|
||||||
* - issuer
|
* <p>
|
||||||
* - authorization_endpoint
|
* The following claims are REQUIRED:
|
||||||
* - token_endpoint
|
* {@code issuer}, {@code authorization_endpoint}, {@code token_endpoint}, {@code jwks_uri},
|
||||||
* - jwks_uri
|
* {@code response_types_supported} and {@code subject_types_supported}.
|
||||||
* - response_types_supported
|
|
||||||
* - subject_types_supported
|
|
||||||
*
|
*
|
||||||
* @return The constructed {@link OidcProviderConfiguration}
|
* @return the {@link OidcProviderConfiguration}
|
||||||
*/
|
*/
|
||||||
public OidcProviderConfiguration build() {
|
public OidcProviderConfiguration build() {
|
||||||
validateClaims();
|
validateClaims();
|
||||||
@ -298,34 +288,43 @@ public class OidcProviderConfiguration implements OidcProviderMetadataClaimAcces
|
|||||||
validateURL(this.claims.get(OidcProviderMetadataClaimNames.AUTHORIZATION_ENDPOINT), "authorizationEndpoint must be a valid URL");
|
validateURL(this.claims.get(OidcProviderMetadataClaimNames.AUTHORIZATION_ENDPOINT), "authorizationEndpoint must be a valid URL");
|
||||||
Assert.notNull(this.claims.get(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT), "tokenEndpoint cannot be null");
|
Assert.notNull(this.claims.get(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT), "tokenEndpoint cannot be null");
|
||||||
validateURL(this.claims.get(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT), "tokenEndpoint must be a valid URL");
|
validateURL(this.claims.get(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT), "tokenEndpoint must be a valid URL");
|
||||||
Assert.notNull(this.claims.get(OidcProviderMetadataClaimNames.JWKS_URI), "jwkSetUri cannot be null");
|
Assert.notNull(this.claims.get(OidcProviderMetadataClaimNames.JWKS_URI), "jwksUri cannot be null");
|
||||||
validateURL(this.claims.get(OidcProviderMetadataClaimNames.JWKS_URI), "jwkSetUri must be a valid URL");
|
validateURL(this.claims.get(OidcProviderMetadataClaimNames.JWKS_URI), "jwksUri must be a valid URL");
|
||||||
Assert.notEmpty((Set<?>) this.claims.get(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED), "subjectTypes cannot be empty");
|
Assert.notNull(this.claims.get(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED), "responseTypes cannot be null");
|
||||||
Assert.notEmpty((Set<?>) this.claims.get(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED), "responseTypes cannot be empty");
|
Assert.isInstanceOf(List.class, this.claims.get(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED), "responseTypes must be of type List");
|
||||||
|
Assert.notEmpty((List<?>) this.claims.get(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED), "responseTypes cannot be empty");
|
||||||
|
Assert.notNull(this.claims.get(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED), "subjectTypes cannot be null");
|
||||||
|
Assert.isInstanceOf(List.class, this.claims.get(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED), "subjectTypes must be of type List");
|
||||||
|
Assert.notEmpty((List<?>) this.claims.get(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED), "subjectTypes cannot be empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateURL(Object url, String errorMessage) {
|
private static void validateURL(Object url, String errorMessage) {
|
||||||
if (url.getClass().isAssignableFrom(URL.class)) return;
|
if (URL.class.isAssignableFrom(url.getClass())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
new URI(url.toString()).toURL();
|
new URI(url.toString()).toURL();
|
||||||
} catch (Exception e) {
|
} catch (Exception ex) {
|
||||||
throw new IllegalArgumentException(errorMessage);
|
throw new IllegalArgumentException(errorMessage, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private void addClaimToClaimSet(String name, String value) {
|
private void addClaimToClaimList(String name, String value) {
|
||||||
this.claims.putIfAbsent(name, new LinkedHashSet<String>());
|
Assert.hasText(name, "name cannot be empty");
|
||||||
((Set<String>) this.claims.get(name)).add(value);
|
Assert.notNull(value, "value cannot be null");
|
||||||
|
this.claims.computeIfAbsent(name, k -> new LinkedList<String>());
|
||||||
|
((List<String>) this.claims.get(name)).add(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private void applyToClaim(String name, Consumer<Set<String>> consumer) {
|
private void acceptClaimValues(String name, Consumer<List<String>> valuesConsumer) {
|
||||||
this.claims.putIfAbsent(name, new LinkedHashSet<String>());
|
Assert.hasText(name, "name cannot be empty");
|
||||||
Set<String> values = (Set<String>) this.claims.get(name);
|
Assert.notNull(valuesConsumer, "valuesConsumer cannot be null");
|
||||||
consumer.accept(values);
|
this.claims.computeIfAbsent(name, k -> new LinkedList<String>());
|
||||||
|
List<String> values = (List<String>) this.claims.get(name);
|
||||||
|
valuesConsumer.accept(values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,30 +35,30 @@ import java.util.List;
|
|||||||
public interface OidcProviderMetadataClaimAccessor extends ClaimAccessor {
|
public interface OidcProviderMetadataClaimAccessor extends ClaimAccessor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the URL the OpenID Provider asserts as its Issuer Identifier {@code (issuer)}.
|
* Returns the {@code URL} the OpenID Provider asserts as its Issuer Identifier {@code (issuer)}.
|
||||||
*
|
*
|
||||||
* @return the URL the OpenID Provider asserts as its Issuer Identifier
|
* @return the {@code URL} the OpenID Provider asserts as its Issuer Identifier
|
||||||
*/
|
*/
|
||||||
default URL getIssuer() {
|
default URL getIssuer() {
|
||||||
return this.getClaimAsURL(OidcProviderMetadataClaimNames.ISSUER);
|
return getClaimAsURL(OidcProviderMetadataClaimNames.ISSUER);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the URL of the OAuth 2.0 Authorization Endpoint {@code (authorization_endpoint)}.
|
* Returns the {@code URL} of the OAuth 2.0 Authorization Endpoint {@code (authorization_endpoint)}.
|
||||||
*
|
*
|
||||||
* @return the URL of the OAuth 2.0 Authorization Endpoint
|
* @return the {@code URL} of the OAuth 2.0 Authorization Endpoint
|
||||||
*/
|
*/
|
||||||
default URL getAuthorizationEndpoint() {
|
default URL getAuthorizationEndpoint() {
|
||||||
return this.getClaimAsURL(OidcProviderMetadataClaimNames.AUTHORIZATION_ENDPOINT);
|
return getClaimAsURL(OidcProviderMetadataClaimNames.AUTHORIZATION_ENDPOINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the URL of the OAuth 2.0 Token Endpoint {@code (token_endpoint)}.
|
* Returns the {@code URL} of the OAuth 2.0 Token Endpoint {@code (token_endpoint)}.
|
||||||
*
|
*
|
||||||
* @return the URL of the OAuth 2.0 Token Endpoint
|
* @return the {@code URL} of the OAuth 2.0 Token Endpoint
|
||||||
*/
|
*/
|
||||||
default URL getTokenEndpoint() {
|
default URL getTokenEndpoint() {
|
||||||
return this.getClaimAsURL(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT);
|
return getClaimAsURL(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -67,16 +67,16 @@ public interface OidcProviderMetadataClaimAccessor extends ClaimAccessor {
|
|||||||
* @return the client authentication methods supported by the OAuth 2.0 Token Endpoint
|
* @return the client authentication methods supported by the OAuth 2.0 Token Endpoint
|
||||||
*/
|
*/
|
||||||
default List<String> getTokenEndpointAuthenticationMethods() {
|
default List<String> getTokenEndpointAuthenticationMethods() {
|
||||||
return this.getClaimAsStringList(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT_AUTH_METHODS_SUPPORTED);
|
return getClaimAsStringList(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT_AUTH_METHODS_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the URL of the JSON Web Key Set {@code (jwks_uri)}.
|
* Returns the {@code URL} of the JSON Web Key Set {@code (jwks_uri)}.
|
||||||
*
|
*
|
||||||
* @return the URL of the JSON Web Key Set
|
* @return the {@code URL} of the JSON Web Key Set
|
||||||
*/
|
*/
|
||||||
default URL getJwksUri() {
|
default URL getJwksUri() {
|
||||||
return this.getClaimAsURL(OidcProviderMetadataClaimNames.JWKS_URI);
|
return getClaimAsURL(OidcProviderMetadataClaimNames.JWKS_URI);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -85,7 +85,7 @@ public interface OidcProviderMetadataClaimAccessor extends ClaimAccessor {
|
|||||||
* @return the OAuth 2.0 {@code response_type} values supported
|
* @return the OAuth 2.0 {@code response_type} values supported
|
||||||
*/
|
*/
|
||||||
default List<String> getResponseTypes() {
|
default List<String> getResponseTypes() {
|
||||||
return this.getClaimAsStringList(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED);
|
return getClaimAsStringList(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,7 +94,7 @@ public interface OidcProviderMetadataClaimAccessor extends ClaimAccessor {
|
|||||||
* @return the OAuth 2.0 {@code grant_type} values supported
|
* @return the OAuth 2.0 {@code grant_type} values supported
|
||||||
*/
|
*/
|
||||||
default List<String> getGrantTypes() {
|
default List<String> getGrantTypes() {
|
||||||
return this.getClaimAsStringList(OidcProviderMetadataClaimNames.GRANT_TYPES_SUPPORTED);
|
return getClaimAsStringList(OidcProviderMetadataClaimNames.GRANT_TYPES_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -103,7 +103,7 @@ public interface OidcProviderMetadataClaimAccessor extends ClaimAccessor {
|
|||||||
* @return the Subject Identifier types supported
|
* @return the Subject Identifier types supported
|
||||||
*/
|
*/
|
||||||
default List<String> getSubjectTypes() {
|
default List<String> getSubjectTypes() {
|
||||||
return this.getClaimAsStringList(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED);
|
return getClaimAsStringList(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -112,7 +112,7 @@ public interface OidcProviderMetadataClaimAccessor extends ClaimAccessor {
|
|||||||
* @return the OAuth 2.0 {@code scope} values supported
|
* @return the OAuth 2.0 {@code scope} values supported
|
||||||
*/
|
*/
|
||||||
default List<String> getScopes() {
|
default List<String> getScopes() {
|
||||||
return this.getClaimAsStringList(OidcProviderMetadataClaimNames.SCOPES_SUPPORTED);
|
return getClaimAsStringList(OidcProviderMetadataClaimNames.SCOPES_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
package org.springframework.security.oauth2.core.oidc;
|
package org.springframework.security.oauth2.core.oidc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The names of the "claims" defined by the OpenID Connect Discovery 1.0 that can be returned
|
* The names of the "claims" defined by OpenID Connect Discovery 1.0 that can be returned
|
||||||
* in the OpenID Provider Configuration Response.
|
* in the OpenID Provider Configuration Response.
|
||||||
*
|
*
|
||||||
* @author Daniel Garnier-Moiroux
|
* @author Daniel Garnier-Moiroux
|
||||||
@ -26,17 +26,17 @@ package org.springframework.security.oauth2.core.oidc;
|
|||||||
public interface OidcProviderMetadataClaimNames {
|
public interface OidcProviderMetadataClaimNames {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code issuer} - the URL the OpenID Provider asserts as its Issuer Identifier
|
* {@code issuer} - the {@code URL} the OpenID Provider asserts as its Issuer Identifier
|
||||||
*/
|
*/
|
||||||
String ISSUER = "issuer";
|
String ISSUER = "issuer";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code authorization_endpoint} - the URL of the OAuth 2.0 Authorization Endpoint
|
* {@code authorization_endpoint} - the {@code URL} of the OAuth 2.0 Authorization Endpoint
|
||||||
*/
|
*/
|
||||||
String AUTHORIZATION_ENDPOINT = "authorization_endpoint";
|
String AUTHORIZATION_ENDPOINT = "authorization_endpoint";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code token_endpoint} - the URL of the OAuth 2.0 Token Endpoint
|
* {@code token_endpoint} - the {@code URL} of the OAuth 2.0 Token Endpoint
|
||||||
*/
|
*/
|
||||||
String TOKEN_ENDPOINT = "token_endpoint";
|
String TOKEN_ENDPOINT = "token_endpoint";
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ public interface OidcProviderMetadataClaimNames {
|
|||||||
String TOKEN_ENDPOINT_AUTH_METHODS_SUPPORTED = "token_endpoint_auth_methods_supported";
|
String TOKEN_ENDPOINT_AUTH_METHODS_SUPPORTED = "token_endpoint_auth_methods_supported";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code jwks_uri} - the URL of the JSON Web Key Set
|
* {@code jwks_uri} - the {@code URL} of the JSON Web Key Set
|
||||||
*/
|
*/
|
||||||
String JWKS_URI = "jwks_uri";
|
String JWKS_URI = "jwks_uri";
|
||||||
|
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2018 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
|
||||||
|
*
|
||||||
|
* https://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.core.oidc.http.converter;
|
||||||
|
|
||||||
|
import org.springframework.http.converter.GenericHttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.json.GsonHttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.json.JsonbHttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
* This class is a straight copy from Spring Security.
|
||||||
|
* It should be consolidated when merging this codebase into Spring Security.
|
||||||
|
*
|
||||||
|
* Utility methods for {@link HttpMessageConverter}'s.
|
||||||
|
*
|
||||||
|
* @author Joe Grandja
|
||||||
|
* @since 5.1
|
||||||
|
*/
|
||||||
|
final class HttpMessageConverters {
|
||||||
|
|
||||||
|
private static final boolean jackson2Present;
|
||||||
|
|
||||||
|
private static final boolean gsonPresent;
|
||||||
|
|
||||||
|
private static final boolean jsonbPresent;
|
||||||
|
|
||||||
|
static {
|
||||||
|
ClassLoader classLoader = HttpMessageConverters.class.getClassLoader();
|
||||||
|
jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader)
|
||||||
|
&& ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);
|
||||||
|
gsonPresent = ClassUtils.isPresent("com.google.gson.Gson", classLoader);
|
||||||
|
jsonbPresent = ClassUtils.isPresent("javax.json.bind.Jsonb", classLoader);
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpMessageConverters() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static GenericHttpMessageConverter<Object> getJsonMessageConverter() {
|
||||||
|
if (jackson2Present) {
|
||||||
|
return new MappingJackson2HttpMessageConverter();
|
||||||
|
}
|
||||||
|
if (gsonPresent) {
|
||||||
|
return new GsonHttpMessageConverter();
|
||||||
|
}
|
||||||
|
if (jsonbPresent) {
|
||||||
|
return new JsonbHttpMessageConverter();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.security.oauth2.core.http.converter;
|
package org.springframework.security.oauth2.core.oidc.http.converter;
|
||||||
|
|
||||||
import org.springframework.core.ParameterizedTypeReference;
|
import org.springframework.core.ParameterizedTypeReference;
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
@ -28,20 +28,17 @@ import org.springframework.http.converter.HttpMessageNotReadableException;
|
|||||||
import org.springframework.http.converter.HttpMessageNotWritableException;
|
import org.springframework.http.converter.HttpMessageNotWritableException;
|
||||||
import org.springframework.security.oauth2.core.converter.ClaimConversionService;
|
import org.springframework.security.oauth2.core.converter.ClaimConversionService;
|
||||||
import org.springframework.security.oauth2.core.converter.ClaimTypeConverter;
|
import org.springframework.security.oauth2.core.converter.ClaimTypeConverter;
|
||||||
import org.springframework.security.oauth2.core.converter.ObjectToSetStringConverter2;
|
|
||||||
import org.springframework.security.oauth2.core.oidc.OidcProviderConfiguration;
|
import org.springframework.security.oauth2.core.oidc.OidcProviderConfiguration;
|
||||||
import org.springframework.security.oauth2.core.oidc.OidcProviderMetadataClaimNames;
|
import org.springframework.security.oauth2.core.oidc.OidcProviderMetadataClaimNames;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link HttpMessageConverter} for an {@link OidcProviderConfiguration OpenID Provider Configuration Metadata}.
|
* A {@link HttpMessageConverter} for an {@link OidcProviderConfiguration OpenID Provider Configuration Response}.
|
||||||
*
|
*
|
||||||
* @author Daniel Garnier-Moiroux
|
* @author Daniel Garnier-Moiroux
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
@ -50,9 +47,9 @@ import java.util.Set;
|
|||||||
*/
|
*/
|
||||||
public class OidcProviderConfigurationHttpMessageConverter
|
public class OidcProviderConfigurationHttpMessageConverter
|
||||||
extends AbstractHttpMessageConverter<OidcProviderConfiguration> {
|
extends AbstractHttpMessageConverter<OidcProviderConfiguration> {
|
||||||
|
|
||||||
private static final ParameterizedTypeReference<Map<String, Object>> STRING_OBJECT_MAP =
|
private static final ParameterizedTypeReference<Map<String, Object>> STRING_OBJECT_MAP =
|
||||||
new ParameterizedTypeReference<Map<String, Object>>() {
|
new ParameterizedTypeReference<Map<String, Object>>() {};
|
||||||
};
|
|
||||||
|
|
||||||
private final GenericHttpMessageConverter<Object> jsonMessageConverter = HttpMessageConverters.getJsonMessageConverter();
|
private final GenericHttpMessageConverter<Object> jsonMessageConverter = HttpMessageConverters.getJsonMessageConverter();
|
||||||
|
|
||||||
@ -73,7 +70,8 @@ public class OidcProviderConfigurationHttpMessageConverter
|
|||||||
protected OidcProviderConfiguration readInternal(Class<? extends OidcProviderConfiguration> clazz, HttpInputMessage inputMessage)
|
protected OidcProviderConfiguration readInternal(Class<? extends OidcProviderConfiguration> clazz, HttpInputMessage inputMessage)
|
||||||
throws HttpMessageNotReadableException {
|
throws HttpMessageNotReadableException {
|
||||||
try {
|
try {
|
||||||
Map<String, Object> providerConfigurationParameters = (Map<String, Object>) this.jsonMessageConverter.read(STRING_OBJECT_MAP.getType(), null, inputMessage);
|
Map<String, Object> providerConfigurationParameters =
|
||||||
|
(Map<String, Object>) this.jsonMessageConverter.read(STRING_OBJECT_MAP.getType(), null, inputMessage);
|
||||||
return this.providerConfigurationConverter.convert(providerConfigurationParameters);
|
return this.providerConfigurationConverter.convert(providerConfigurationParameters);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
throw new HttpMessageNotReadableException(
|
throw new HttpMessageNotReadableException(
|
||||||
@ -82,7 +80,8 @@ public class OidcProviderConfigurationHttpMessageConverter
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void writeInternal(OidcProviderConfiguration providerConfiguration, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
|
protected void writeInternal(OidcProviderConfiguration providerConfiguration, HttpOutputMessage outputMessage)
|
||||||
|
throws HttpMessageNotWritableException {
|
||||||
try {
|
try {
|
||||||
Map<String, Object> providerConfigurationResponseParameters =
|
Map<String, Object> providerConfigurationResponseParameters =
|
||||||
this.providerConfigurationParametersConverter.convert(providerConfiguration);
|
this.providerConfigurationParametersConverter.convert(providerConfiguration);
|
||||||
@ -98,6 +97,18 @@ public class OidcProviderConfigurationHttpMessageConverter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link Converter} used for converting the OpenID Provider Configuration parameters
|
||||||
|
* to an {@link OidcProviderConfiguration}.
|
||||||
|
*
|
||||||
|
* @param providerConfigurationConverter the {@link Converter} used for converting to an
|
||||||
|
* {@link OidcProviderConfiguration}
|
||||||
|
*/
|
||||||
|
public final void setProviderConfigurationConverter(Converter<Map<String, Object>, OidcProviderConfiguration> providerConfigurationConverter) {
|
||||||
|
Assert.notNull(providerConfigurationConverter, "providerConfigurationConverter cannot be null");
|
||||||
|
this.providerConfigurationConverter = providerConfigurationConverter;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the {@link Converter} used for converting the {@link OidcProviderConfiguration} to a
|
* Sets the {@link Converter} used for converting the {@link OidcProviderConfiguration} to a
|
||||||
* {@code Map} representation of the OpenID Provider Configuration.
|
* {@code Map} representation of the OpenID Provider Configuration.
|
||||||
@ -111,18 +122,6 @@ public class OidcProviderConfigurationHttpMessageConverter
|
|||||||
this.providerConfigurationParametersConverter = providerConfigurationParametersConverter;
|
this.providerConfigurationParametersConverter = providerConfigurationParametersConverter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the {@link Converter} used for converting the OpenID Provider Configuration parameters
|
|
||||||
* to an {@link OidcProviderConfiguration}.
|
|
||||||
*
|
|
||||||
* @param providerConfigurationConverter the {@link Converter} used for converting to an
|
|
||||||
* {@link OidcProviderConfiguration}
|
|
||||||
*/
|
|
||||||
public final void setProviderConfigurationConverter(Converter<Map<String, Object>, OidcProviderConfiguration> providerConfigurationConverter) {
|
|
||||||
Assert.notNull(providerConfigurationConverter, "providerConfigurationConverter cannot be null");
|
|
||||||
this.providerConfigurationConverter = providerConfigurationConverter;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class OidcProviderConfigurationConverter implements Converter<Map<String, Object>, OidcProviderConfiguration> {
|
private static final class OidcProviderConfigurationConverter implements Converter<Map<String, Object>, OidcProviderConfiguration> {
|
||||||
private static final ClaimConversionService CLAIM_CONVERSION_SERVICE = ClaimConversionService.getSharedInstance();
|
private static final ClaimConversionService CLAIM_CONVERSION_SERVICE = ClaimConversionService.getSharedInstance();
|
||||||
private static final TypeDescriptor OBJECT_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(Object.class);
|
private static final TypeDescriptor OBJECT_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(Object.class);
|
||||||
@ -130,22 +129,22 @@ public class OidcProviderConfigurationHttpMessageConverter
|
|||||||
private static final TypeDescriptor URL_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(URL.class);
|
private static final TypeDescriptor URL_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(URL.class);
|
||||||
private final ClaimTypeConverter claimTypeConverter;
|
private final ClaimTypeConverter claimTypeConverter;
|
||||||
|
|
||||||
OidcProviderConfigurationConverter() {
|
private OidcProviderConfigurationConverter() {
|
||||||
CLAIM_CONVERSION_SERVICE.addConverter(new ObjectToSetStringConverter2());
|
Converter<Object, ?> collectionStringConverter = getConverter(
|
||||||
Map<String, Converter<Object, ?>> claimNameToConverter = new HashMap<>();
|
TypeDescriptor.collection(Collection.class, STRING_TYPE_DESCRIPTOR));
|
||||||
Converter<Object, ?> setStringConverter = getConverter(TypeDescriptor.collection(Set.class, STRING_TYPE_DESCRIPTOR));
|
|
||||||
Converter<Object, ?> urlConverter = getConverter(URL_TYPE_DESCRIPTOR);
|
Converter<Object, ?> urlConverter = getConverter(URL_TYPE_DESCRIPTOR);
|
||||||
|
|
||||||
claimNameToConverter.put(OidcProviderMetadataClaimNames.ISSUER, urlConverter);
|
Map<String, Converter<Object, ?>> claimConverters = new HashMap<>();
|
||||||
claimNameToConverter.put(OidcProviderMetadataClaimNames.AUTHORIZATION_ENDPOINT, urlConverter);
|
claimConverters.put(OidcProviderMetadataClaimNames.ISSUER, urlConverter);
|
||||||
claimNameToConverter.put(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT, urlConverter);
|
claimConverters.put(OidcProviderMetadataClaimNames.AUTHORIZATION_ENDPOINT, urlConverter);
|
||||||
claimNameToConverter.put(OidcProviderMetadataClaimNames.JWKS_URI, urlConverter);
|
claimConverters.put(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT, urlConverter);
|
||||||
claimNameToConverter.put(OidcProviderMetadataClaimNames.GRANT_TYPES_SUPPORTED, setStringConverter);
|
claimConverters.put(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT_AUTH_METHODS_SUPPORTED, collectionStringConverter);
|
||||||
claimNameToConverter.put(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT_AUTH_METHODS_SUPPORTED, setStringConverter);
|
claimConverters.put(OidcProviderMetadataClaimNames.JWKS_URI, urlConverter);
|
||||||
claimNameToConverter.put(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED, setStringConverter);
|
claimConverters.put(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED, collectionStringConverter);
|
||||||
claimNameToConverter.put(OidcProviderMetadataClaimNames.SCOPES_SUPPORTED, setStringConverter);
|
claimConverters.put(OidcProviderMetadataClaimNames.GRANT_TYPES_SUPPORTED, collectionStringConverter);
|
||||||
claimNameToConverter.put(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED, setStringConverter);
|
claimConverters.put(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED, collectionStringConverter);
|
||||||
this.claimTypeConverter = new ClaimTypeConverter(claimNameToConverter);
|
claimConverters.put(OidcProviderMetadataClaimNames.SCOPES_SUPPORTED, collectionStringConverter);
|
||||||
|
this.claimTypeConverter = new ClaimTypeConverter(claimConverters);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -15,57 +15,61 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.security.oauth2.server.authorization.config;
|
package org.springframework.security.oauth2.server.authorization.config;
|
||||||
|
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A facility for OpenID Connect Provider Configuration settings.
|
* A facility for provider configuration settings.
|
||||||
*
|
*
|
||||||
* @author Daniel Garnier-Moiroux
|
* @author Daniel Garnier-Moiroux
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
* @see Settings
|
* @see Settings
|
||||||
* @see <a target="_blank" href="https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata">OpenID Connect Discovery 1.0</a>
|
|
||||||
*/
|
*/
|
||||||
public class ProviderSettings extends Settings {
|
public class ProviderSettings extends Settings {
|
||||||
private static final String PROVIDER_SETTING_BASE = "setting.provider.";
|
private static final String PROVIDER_SETTING_BASE = "setting.provider.";
|
||||||
public static final String ISSUER = PROVIDER_SETTING_BASE.concat("issuer");
|
public static final String ISSUER = PROVIDER_SETTING_BASE.concat("issuer");
|
||||||
public static final String AUTHORIZATION_ENDPOINT = PROVIDER_SETTING_BASE.concat("authorization-endpoint");
|
public static final String AUTHORIZATION_ENDPOINT = PROVIDER_SETTING_BASE.concat("authorization-endpoint");
|
||||||
public static final String TOKEN_ENDPOINT = PROVIDER_SETTING_BASE.concat("token-endpoint");
|
public static final String TOKEN_ENDPOINT = PROVIDER_SETTING_BASE.concat("token-endpoint");
|
||||||
public static final String JWK_SET_ENDPOINT = PROVIDER_SETTING_BASE.concat("jwk-set-endpoint");
|
public static final String JWKS_ENDPOINT = PROVIDER_SETTING_BASE.concat("jwks-endpoint");
|
||||||
public static final String TOKEN_REVOCATION_ENDPOINT = PROVIDER_SETTING_BASE.concat("token-revocation-endpoint");
|
public static final String TOKEN_REVOCATION_ENDPOINT = PROVIDER_SETTING_BASE.concat("token-revocation-endpoint");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a {@code ProviderSettings}.
|
* Constructs a {@code ProviderSettings}.
|
||||||
*/
|
*/
|
||||||
public ProviderSettings() {
|
public ProviderSettings() {
|
||||||
super(defaultSettings());
|
this(defaultSettings());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the URL for the OpenID Issuer.
|
* Constructs a {@code ProviderSettings} using the provided parameters.
|
||||||
*
|
*
|
||||||
* @return the URL for the OpenID Issuer
|
* @param settings the initial settings
|
||||||
|
*/
|
||||||
|
public ProviderSettings(Map<String, Object> settings) {
|
||||||
|
super(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the URL of the Provider's Issuer Identifier
|
||||||
|
*
|
||||||
|
* @return the URL of the Provider's Issuer Identifier
|
||||||
*/
|
*/
|
||||||
public String issuer() {
|
public String issuer() {
|
||||||
return setting(ISSUER);
|
return setting(ISSUER);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the URL the Provider uses as its Issuer Identity.
|
* Sets the URL the Provider uses as its Issuer Identifier.
|
||||||
*
|
*
|
||||||
* @param issuer the URL the Provider uses as its Issuer Identity.
|
* @param issuer the URL the Provider uses as its Issuer Identifier.
|
||||||
* @return the {@link ProviderSettings} for further configuration
|
* @return the {@link ProviderSettings} for further configuration
|
||||||
*/
|
*/
|
||||||
public ProviderSettings issuer(String issuer) {
|
public ProviderSettings issuer(String issuer) {
|
||||||
Assert.notNull(issuer, "issuer cannot be null");
|
|
||||||
return setting(ISSUER, issuer);
|
return setting(ISSUER, issuer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the provider's OAuth 2.0 Authorization endpoint. The default is {@code /oauth2/authorize}.
|
* Returns the Provider's OAuth 2.0 Authorization endpoint. The default is {@code /oauth2/authorize}.
|
||||||
*
|
*
|
||||||
* @return the Authorization endpoint
|
* @return the Authorization endpoint
|
||||||
*/
|
*/
|
||||||
@ -74,18 +78,17 @@ public class ProviderSettings extends Settings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the provider's OAuth 2.0 Authorization endpoint.
|
* Sets the Provider's OAuth 2.0 Authorization endpoint.
|
||||||
*
|
*
|
||||||
* @param authorizationEndpoint the Authorization endpoint
|
* @param authorizationEndpoint the Authorization endpoint
|
||||||
* @return the {@link ProviderSettings} for further configuration
|
* @return the {@link ProviderSettings} for further configuration
|
||||||
*/
|
*/
|
||||||
public ProviderSettings authorizationEndpoint(String authorizationEndpoint) {
|
public ProviderSettings authorizationEndpoint(String authorizationEndpoint) {
|
||||||
Assert.hasText(authorizationEndpoint, "authorizationEndpoint cannot be empty");
|
|
||||||
return setting(AUTHORIZATION_ENDPOINT, authorizationEndpoint);
|
return setting(AUTHORIZATION_ENDPOINT, authorizationEndpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the provider's OAuth 2.0 Token endpoint. The default is {@code /oauth2/token}.
|
* Returns the Provider's OAuth 2.0 Token endpoint. The default is {@code /oauth2/token}.
|
||||||
*
|
*
|
||||||
* @return the Token endpoint
|
* @return the Token endpoint
|
||||||
*/
|
*/
|
||||||
@ -94,38 +97,36 @@ public class ProviderSettings extends Settings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the provider's OAuth 2.0 Token endpoint.
|
* Sets the Provider's OAuth 2.0 Token endpoint.
|
||||||
*
|
*
|
||||||
* @param tokenEndpoint the Token endpoint
|
* @param tokenEndpoint the Token endpoint
|
||||||
* @return the {@link ProviderSettings} for further configuration
|
* @return the {@link ProviderSettings} for further configuration
|
||||||
*/
|
*/
|
||||||
public ProviderSettings tokenEndpoint(String tokenEndpoint) {
|
public ProviderSettings tokenEndpoint(String tokenEndpoint) {
|
||||||
Assert.hasText(tokenEndpoint, "tokenEndpoint cannot be empty");
|
|
||||||
return setting(TOKEN_ENDPOINT, tokenEndpoint);
|
return setting(TOKEN_ENDPOINT, tokenEndpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the provider's JWK Set endpoint. The default is {@code /oauth2/jwks}.
|
* Returns the Provider's JWK Set endpoint. The default is {@code /oauth2/jwks}.
|
||||||
*
|
*
|
||||||
* @return the JWK Set endpoint
|
* @return the JWK Set endpoint
|
||||||
*/
|
*/
|
||||||
public String jwkSetEndpoint() {
|
public String jwksEndpoint() {
|
||||||
return setting(JWK_SET_ENDPOINT);
|
return setting(JWKS_ENDPOINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the provider's OAuth 2.0 JWK Set endpoint.
|
* Sets the Provider's JWK Set endpoint.
|
||||||
*
|
*
|
||||||
* @param jwkSetEndpoint the JWK Set endpoint
|
* @param jwksEndpoint the JWK Set endpoint
|
||||||
* @return the {@link ProviderSettings} for further configuration
|
* @return the {@link ProviderSettings} for further configuration
|
||||||
*/
|
*/
|
||||||
public ProviderSettings jwkSetEndpoint(String jwkSetEndpoint) {
|
public ProviderSettings jwksEndpoint(String jwksEndpoint) {
|
||||||
Assert.hasText(jwkSetEndpoint, "jwkSetEndpoint cannot be empty");
|
return setting(JWKS_ENDPOINT, jwksEndpoint);
|
||||||
return setting(JWK_SET_ENDPOINT, jwkSetEndpoint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the provider's Token Revocation endpoint. The default is {@code /oauth2/revoke}.
|
* Returns the Provider's OAuth 2.0 Token Revocation endpoint. The default is {@code /oauth2/revoke}.
|
||||||
*
|
*
|
||||||
* @return the Token Revocation endpoint
|
* @return the Token Revocation endpoint
|
||||||
*/
|
*/
|
||||||
@ -134,13 +135,12 @@ public class ProviderSettings extends Settings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the provider's OAuth 2.0 Token Revocation endpoint.
|
* Sets the Provider's OAuth 2.0 Token Revocation endpoint.
|
||||||
*
|
*
|
||||||
* @param tokenRevocationEndpoint the Token Revocation endpoint
|
* @param tokenRevocationEndpoint the Token Revocation endpoint
|
||||||
* @return the {@link ProviderSettings} for further configuration
|
* @return the {@link ProviderSettings} for further configuration
|
||||||
*/
|
*/
|
||||||
public ProviderSettings tokenRevocationEndpoint(String tokenRevocationEndpoint) {
|
public ProviderSettings tokenRevocationEndpoint(String tokenRevocationEndpoint) {
|
||||||
Assert.hasText(tokenRevocationEndpoint, "tokenRevocationEndpoint cannot be empty");
|
|
||||||
return setting(TOKEN_REVOCATION_ENDPOINT, tokenRevocationEndpoint);
|
return setting(TOKEN_REVOCATION_ENDPOINT, tokenRevocationEndpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +148,7 @@ public class ProviderSettings extends Settings {
|
|||||||
Map<String, Object> settings = new HashMap<>();
|
Map<String, Object> settings = new HashMap<>();
|
||||||
settings.put(AUTHORIZATION_ENDPOINT, "/oauth2/authorize");
|
settings.put(AUTHORIZATION_ENDPOINT, "/oauth2/authorize");
|
||||||
settings.put(TOKEN_ENDPOINT, "/oauth2/token");
|
settings.put(TOKEN_ENDPOINT, "/oauth2/token");
|
||||||
settings.put(JWK_SET_ENDPOINT, "/oauth2/jwks");
|
settings.put(JWKS_ENDPOINT, "/oauth2/jwks");
|
||||||
settings.put(TOKEN_REVOCATION_ENDPOINT, "/oauth2/revoke");
|
settings.put(TOKEN_REVOCATION_ENDPOINT, "/oauth2/revoke");
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
@ -20,9 +20,9 @@ import org.springframework.http.MediaType;
|
|||||||
import org.springframework.http.server.ServletServerHttpResponse;
|
import org.springframework.http.server.ServletServerHttpResponse;
|
||||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponseType;
|
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponseType;
|
||||||
import org.springframework.security.oauth2.core.http.converter.OidcProviderConfigurationHttpMessageConverter;
|
|
||||||
import org.springframework.security.oauth2.core.oidc.OidcProviderConfiguration;
|
import org.springframework.security.oauth2.core.oidc.OidcProviderConfiguration;
|
||||||
import org.springframework.security.oauth2.core.oidc.OidcScopes;
|
import org.springframework.security.oauth2.core.oidc.OidcScopes;
|
||||||
|
import org.springframework.security.oauth2.core.oidc.http.converter.OidcProviderConfigurationHttpMessageConverter;
|
||||||
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
|
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
@ -37,12 +37,13 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@code Filter} that processes OpenID Provider Configuration Request.
|
* A {@code Filter} that processes OpenID Provider Configuration Requests.
|
||||||
*
|
*
|
||||||
* @author Daniel Garnier-Moiroux
|
* @author Daniel Garnier-Moiroux
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
|
* @see OidcProviderConfiguration
|
||||||
* @see ProviderSettings
|
* @see ProviderSettings
|
||||||
* @see <a target="_blank" href="https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig">OpenID Connect Discovery 1.0</a>
|
* @see <a target="_blank" href="https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest">4.1. OpenID Provider Configuration Request</a>
|
||||||
*/
|
*/
|
||||||
public class OidcProviderConfigurationEndpointFilter extends OncePerRequestFilter {
|
public class OidcProviderConfigurationEndpointFilter extends OncePerRequestFilter {
|
||||||
/**
|
/**
|
||||||
@ -50,22 +51,24 @@ public class OidcProviderConfigurationEndpointFilter extends OncePerRequestFilte
|
|||||||
*/
|
*/
|
||||||
public static final String DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI = "/.well-known/openid-configuration";
|
public static final String DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI = "/.well-known/openid-configuration";
|
||||||
|
|
||||||
private final RequestMatcher requestMatcher;
|
|
||||||
private final ProviderSettings providerSettings;
|
private final ProviderSettings providerSettings;
|
||||||
private final OidcProviderConfigurationHttpMessageConverter providerConfigurationHttpMessageConverter = new OidcProviderConfigurationHttpMessageConverter();
|
private final RequestMatcher requestMatcher;
|
||||||
|
private final OidcProviderConfigurationHttpMessageConverter providerConfigurationHttpMessageConverter =
|
||||||
|
new OidcProviderConfigurationHttpMessageConverter();
|
||||||
|
|
||||||
public OidcProviderConfigurationEndpointFilter(ProviderSettings providerSettings) {
|
public OidcProviderConfigurationEndpointFilter(ProviderSettings providerSettings) {
|
||||||
Assert.notNull(providerSettings, "providerSettings cannot be null");
|
Assert.notNull(providerSettings, "providerSettings cannot be null");
|
||||||
|
this.providerSettings = providerSettings;
|
||||||
this.requestMatcher = new AntPathRequestMatcher(
|
this.requestMatcher = new AntPathRequestMatcher(
|
||||||
DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI,
|
DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI,
|
||||||
HttpMethod.GET.name()
|
HttpMethod.GET.name()
|
||||||
);
|
);
|
||||||
this.providerSettings = providerSettings;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||||
throws ServletException, IOException {
|
throws ServletException, IOException {
|
||||||
|
|
||||||
if (!this.requestMatcher.matches(request)) {
|
if (!this.requestMatcher.matches(request)) {
|
||||||
filterChain.doFilter(request, response);
|
filterChain.doFilter(request, response);
|
||||||
return;
|
return;
|
||||||
@ -75,20 +78,23 @@ public class OidcProviderConfigurationEndpointFilter extends OncePerRequestFilte
|
|||||||
.issuer(this.providerSettings.issuer())
|
.issuer(this.providerSettings.issuer())
|
||||||
.authorizationEndpoint(asUrl(this.providerSettings.issuer(), this.providerSettings.authorizationEndpoint()))
|
.authorizationEndpoint(asUrl(this.providerSettings.issuer(), this.providerSettings.authorizationEndpoint()))
|
||||||
.tokenEndpoint(asUrl(this.providerSettings.issuer(), this.providerSettings.tokenEndpoint()))
|
.tokenEndpoint(asUrl(this.providerSettings.issuer(), this.providerSettings.tokenEndpoint()))
|
||||||
.jwksUri(asUrl(this.providerSettings.issuer(), this.providerSettings.jwkSetEndpoint()))
|
.tokenEndpointAuthenticationMethod("client_secret_basic") // TODO: Use ClientAuthenticationMethod.CLIENT_SECRET_BASIC in Spring Security 5.5.0
|
||||||
.subjectType("public")
|
.tokenEndpointAuthenticationMethod("client_secret_post") // TODO: Use ClientAuthenticationMethod.CLIENT_SECRET_POST in Spring Security 5.5.0
|
||||||
|
.jwksUri(asUrl(this.providerSettings.issuer(), this.providerSettings.jwksEndpoint()))
|
||||||
.responseType(OAuth2AuthorizationResponseType.CODE.getValue())
|
.responseType(OAuth2AuthorizationResponseType.CODE.getValue())
|
||||||
.scope(OidcScopes.OPENID)
|
|
||||||
.grantType(AuthorizationGrantType.AUTHORIZATION_CODE.getValue())
|
.grantType(AuthorizationGrantType.AUTHORIZATION_CODE.getValue())
|
||||||
.grantType(AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
|
.grantType(AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
|
||||||
.tokenEndpointAuthenticationMethod("client_secret_basic") // TODO: move this ClientAuthenticationMethod
|
.grantType(AuthorizationGrantType.REFRESH_TOKEN.getValue())
|
||||||
|
.subjectType("public")
|
||||||
|
.scope(OidcScopes.OPENID)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
ServletServerHttpResponse resp = new ServletServerHttpResponse(response);
|
ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response);
|
||||||
this.providerConfigurationHttpMessageConverter.write(providerConfiguration, MediaType.APPLICATION_JSON, resp);
|
this.providerConfigurationHttpMessageConverter.write(
|
||||||
|
providerConfiguration, MediaType.APPLICATION_JSON, httpResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String asUrl(String issuer, String endpoint) {
|
private static String asUrl(String issuer, String endpoint) {
|
||||||
return UriComponentsBuilder.fromUriString(issuer).path(endpoint).build().toUriString();
|
return UriComponentsBuilder.fromUriString(issuer).path(endpoint).build().toUriString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,13 +24,11 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
|
|||||||
import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
|
import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
|
||||||
import org.springframework.security.config.test.SpringTestRule;
|
import org.springframework.security.config.test.SpringTestRule;
|
||||||
import org.springframework.security.crypto.key.CryptoKeySource;
|
import org.springframework.security.crypto.key.CryptoKeySource;
|
||||||
import org.springframework.security.crypto.key.StaticKeyGeneratingCryptoKeySource;
|
|
||||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
|
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
|
||||||
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
|
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
|
||||||
import org.springframework.security.oauth2.server.authorization.web.OidcProviderConfigurationEndpointFilter;
|
import org.springframework.security.oauth2.server.authorization.web.OidcProviderConfigurationEndpointFilter;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.test.web.servlet.MvcResult;
|
import org.springframework.test.web.servlet.MvcResult;
|
||||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
@ -40,7 +38,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
|||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Integration tests for the OpenID Connect.
|
* Integration tests for OpenID Connect 1.0.
|
||||||
*
|
*
|
||||||
* @author Daniel Garnier-Moiroux
|
* @author Daniel Garnier-Moiroux
|
||||||
*/
|
*/
|
||||||
@ -54,17 +52,17 @@ public class OidcTests {
|
|||||||
private MockMvc mvc;
|
private MockMvc mvc;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requestWhenIssuerSetAndOpenIDProviderConfigurationRequestThenReturnProviderConfigurationResponse() throws Exception {
|
public void requestWhenConfigurationRequestAndIssuerSetThenReturnConfigurationResponse() throws Exception {
|
||||||
this.spring.register(AuthorizationServerConfigurationWithIssuer.class).autowire();
|
this.spring.register(AuthorizationServerConfigurationWithIssuer.class).autowire();
|
||||||
|
|
||||||
this.mvc.perform(MockMvcRequestBuilders.get(OidcProviderConfigurationEndpointFilter.DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI))
|
this.mvc.perform(get(OidcProviderConfigurationEndpointFilter.DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI))
|
||||||
.andExpect(status().is2xxSuccessful())
|
.andExpect(status().is2xxSuccessful())
|
||||||
.andExpect(jsonPath("issuer").value(issuerUrl))
|
.andExpect(jsonPath("issuer").value(issuerUrl))
|
||||||
.andReturn();
|
.andReturn();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requestWhenIssuerNotSetAndOpenIDProviderConfigurationRequestThenRedirectsToLogin() throws Exception {
|
public void requestWhenConfigurationRequestAndIssuerNotSetThenRedirectToLogin() throws Exception {
|
||||||
this.spring.register(AuthorizationServerConfiguration.class).autowire();
|
this.spring.register(AuthorizationServerConfiguration.class).autowire();
|
||||||
|
|
||||||
MvcResult mvcResult = this.mvc.perform(get(OidcProviderConfigurationEndpointFilter.DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI))
|
MvcResult mvcResult = this.mvc.perform(get(OidcProviderConfigurationEndpointFilter.DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI))
|
||||||
@ -74,16 +72,16 @@ public class OidcTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requestWhenIssuerNotValidUrlThenThrowException() {
|
public void loadContextWhenIssuerNotValidUrlThenThrowException() {
|
||||||
assertThatThrownBy(
|
assertThatThrownBy(
|
||||||
() -> this.spring.register(AuthorizationServerConfigurationWithInvalidUrlIssuer.class).autowire()
|
() -> this.spring.register(AuthorizationServerConfigurationWithInvalidIssuerUrl.class).autowire()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requestWhenIssuerNotValidUriThenThrowException() {
|
public void loadContextWhenIssuerNotValidUriThenThrowException() {
|
||||||
assertThatThrownBy(
|
assertThatThrownBy(
|
||||||
() -> this.spring.register(AuthorizationServerConfigurationWithInvalidUriIssuer.class).autowire()
|
() -> this.spring.register(AuthorizationServerConfigurationWithInvalidIssuerUri.class).autowire()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,20 +96,15 @@ public class OidcTests {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
CryptoKeySource keySource() {
|
CryptoKeySource keySource() {
|
||||||
return new StaticKeyGeneratingCryptoKeySource();
|
return mock(CryptoKeySource.class);
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
ProviderSettings providerSettings() {
|
|
||||||
return new ProviderSettings();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@Import(OAuth2AuthorizationServerConfiguration.class)
|
@Import(OAuth2AuthorizationServerConfiguration.class)
|
||||||
static class AuthorizationServerConfigurationWithIssuer extends AuthorizationServerConfiguration {
|
static class AuthorizationServerConfigurationWithIssuer extends AuthorizationServerConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Override
|
|
||||||
ProviderSettings providerSettings() {
|
ProviderSettings providerSettings() {
|
||||||
return new ProviderSettings().issuer(issuerUrl);
|
return new ProviderSettings().issuer(issuerUrl);
|
||||||
}
|
}
|
||||||
@ -119,9 +112,9 @@ public class OidcTests {
|
|||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@Import(OAuth2AuthorizationServerConfiguration.class)
|
@Import(OAuth2AuthorizationServerConfiguration.class)
|
||||||
static class AuthorizationServerConfigurationWithInvalidUrlIssuer extends AuthorizationServerConfiguration {
|
static class AuthorizationServerConfigurationWithInvalidIssuerUrl extends AuthorizationServerConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Override
|
|
||||||
ProviderSettings providerSettings() {
|
ProviderSettings providerSettings() {
|
||||||
return new ProviderSettings().issuer("urn:example");
|
return new ProviderSettings().issuer("urn:example");
|
||||||
}
|
}
|
||||||
@ -129,9 +122,9 @@ public class OidcTests {
|
|||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@Import(OAuth2AuthorizationServerConfiguration.class)
|
@Import(OAuth2AuthorizationServerConfiguration.class)
|
||||||
static class AuthorizationServerConfigurationWithInvalidUriIssuer extends AuthorizationServerConfiguration {
|
static class AuthorizationServerConfigurationWithInvalidIssuerUri extends AuthorizationServerConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Override
|
|
||||||
ProviderSettings providerSettings() {
|
ProviderSettings providerSettings() {
|
||||||
return new ProviderSettings().issuer("https://not a valid uri");
|
return new ProviderSettings().issuer("https://not a valid uri");
|
||||||
}
|
}
|
||||||
|
@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2020 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
|
|
||||||
*
|
|
||||||
* https://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.core.converter;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO
|
|
||||||
* This class is temporary and will be removed after upgrading to Spring Security 5.5.0 GA.
|
|
||||||
* These tests will probably be folded into tests for {@link ClaimConversionService}.
|
|
||||||
*
|
|
||||||
* Tests for {@link ObjectToSetStringConverter2}.
|
|
||||||
*
|
|
||||||
* @author Daniel Garnier-Moiroux
|
|
||||||
*/
|
|
||||||
public class ObjectToSetStringConverter2Test {
|
|
||||||
@Test
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void convertFromNullThenReturnNull() {
|
|
||||||
ObjectToSetStringConverter2 converter = new ObjectToSetStringConverter2();
|
|
||||||
Set<String> result = (Set<String>) converter.convert(null, null, null);
|
|
||||||
assertThat(result).isNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void convertFromStringThenReturnSet() {
|
|
||||||
ObjectToSetStringConverter2 converter = new ObjectToSetStringConverter2();
|
|
||||||
Set<String> result = (Set<String>) converter.convert("Hello", null, null);
|
|
||||||
assertThat(result).containsExactly("Hello");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void convertFromSetThenReturnSet() {
|
|
||||||
ObjectToSetStringConverter2 converter = new ObjectToSetStringConverter2();
|
|
||||||
Set<String> result = (Set<String>) converter.convert(new HashSet<>(Arrays.asList("Hello", "world")), null, null);
|
|
||||||
assertThat(result).containsExactlyInAnyOrder("Hello", "world");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void convertFromCollectionThenReturnSet() {
|
|
||||||
ObjectToSetStringConverter2 converter = new ObjectToSetStringConverter2();
|
|
||||||
Set<String> result = (Set<String>) converter.convert(Arrays.asList("Hello", "world"), null, null);
|
|
||||||
assertThat(result).containsExactlyInAnyOrder("Hello", "world");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void convertFromEmptyCollectionThenReturnEmptySet() {
|
|
||||||
ObjectToSetStringConverter2 converter = new ObjectToSetStringConverter2();
|
|
||||||
Set<String> result = (Set<String>) converter.convert(Collections.emptyList(), null, null);
|
|
||||||
assertThat(result).isEmpty();
|
|
||||||
}
|
|
||||||
}
|
|
@ -17,11 +17,12 @@ package org.springframework.security.oauth2.core.oidc;
|
|||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
@ -54,7 +55,7 @@ public class OidcProviderConfigurationTests {
|
|||||||
.grantType("authorization_code")
|
.grantType("authorization_code")
|
||||||
.grantType("client_credentials")
|
.grantType("client_credentials")
|
||||||
.subjectType("public")
|
.subjectType("public")
|
||||||
.tokenEndpointAuthenticationMethod("basic")
|
.tokenEndpointAuthenticationMethod("client_secret_basic")
|
||||||
.claim("a-claim", "a-value")
|
.claim("a-claim", "a-value")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@ -66,8 +67,8 @@ public class OidcProviderConfigurationTests {
|
|||||||
assertThat(providerConfiguration.getResponseTypes()).containsExactly("code");
|
assertThat(providerConfiguration.getResponseTypes()).containsExactly("code");
|
||||||
assertThat(providerConfiguration.getGrantTypes()).containsExactlyInAnyOrder("authorization_code", "client_credentials");
|
assertThat(providerConfiguration.getGrantTypes()).containsExactlyInAnyOrder("authorization_code", "client_credentials");
|
||||||
assertThat(providerConfiguration.getSubjectTypes()).containsExactly("public");
|
assertThat(providerConfiguration.getSubjectTypes()).containsExactly("public");
|
||||||
assertThat(providerConfiguration.getTokenEndpointAuthenticationMethods()).containsExactly("basic");
|
assertThat(providerConfiguration.getTokenEndpointAuthenticationMethods()).containsExactly("client_secret_basic");
|
||||||
assertThat(providerConfiguration.getClaimAsString("a-claim")).isEqualTo("a-value");
|
assertThat(providerConfiguration.<String>getClaim("a-claim")).isEqualTo("a-value");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -94,15 +95,15 @@ public class OidcProviderConfigurationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildFromClaimsThenCreated() {
|
public void buildWhenClaimsProvidedThenCreated() {
|
||||||
HashMap<String, Object> claims = new HashMap<>();
|
Map<String, Object> claims = new HashMap<>();
|
||||||
claims.put(OidcProviderMetadataClaimNames.ISSUER, "https://example.com/issuer1");
|
claims.put(OidcProviderMetadataClaimNames.ISSUER, "https://example.com/issuer1");
|
||||||
claims.put(OidcProviderMetadataClaimNames.AUTHORIZATION_ENDPOINT, "https://example.com/issuer1/oauth2/authorize");
|
claims.put(OidcProviderMetadataClaimNames.AUTHORIZATION_ENDPOINT, "https://example.com/issuer1/oauth2/authorize");
|
||||||
claims.put(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT, "https://example.com/issuer1/oauth2/token");
|
claims.put(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT, "https://example.com/issuer1/oauth2/token");
|
||||||
claims.put(OidcProviderMetadataClaimNames.JWKS_URI, "https://example.com/issuer1/oauth2/jwks");
|
claims.put(OidcProviderMetadataClaimNames.JWKS_URI, "https://example.com/issuer1/oauth2/jwks");
|
||||||
claims.put(OidcProviderMetadataClaimNames.SCOPES_SUPPORTED, Collections.singleton("openid"));
|
claims.put(OidcProviderMetadataClaimNames.SCOPES_SUPPORTED, Collections.singletonList("openid"));
|
||||||
claims.put(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED, Collections.singleton("code"));
|
claims.put(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED, Collections.singletonList("code"));
|
||||||
claims.put(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED, Collections.singleton("public"));
|
claims.put(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED, Collections.singletonList("public"));
|
||||||
claims.put("some-claim", "some-value");
|
claims.put("some-claim", "some-value");
|
||||||
|
|
||||||
OidcProviderConfiguration providerConfiguration = OidcProviderConfiguration.withClaims(claims).build();
|
OidcProviderConfiguration providerConfiguration = OidcProviderConfiguration.withClaims(claims).build();
|
||||||
@ -116,19 +117,19 @@ public class OidcProviderConfigurationTests {
|
|||||||
assertThat(providerConfiguration.getGrantTypes()).isNull();
|
assertThat(providerConfiguration.getGrantTypes()).isNull();
|
||||||
assertThat(providerConfiguration.getSubjectTypes()).containsExactly("public");
|
assertThat(providerConfiguration.getSubjectTypes()).containsExactly("public");
|
||||||
assertThat(providerConfiguration.getTokenEndpointAuthenticationMethods()).isNull();
|
assertThat(providerConfiguration.getTokenEndpointAuthenticationMethods()).isNull();
|
||||||
assertThat(providerConfiguration.getClaimAsString("some-claim")).isEqualTo("some-value");
|
assertThat(providerConfiguration.<String>getClaim("some-claim")).isEqualTo("some-value");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildFromClaimsWhenUsingUrlsThenCreated() {
|
public void buildWhenClaimsProvidedWithUrlsThenCreated() {
|
||||||
HashMap<String, Object> claims = new HashMap<>();
|
Map<String, Object> claims = new HashMap<>();
|
||||||
claims.put(OidcProviderMetadataClaimNames.ISSUER, url("https://example.com/issuer1"));
|
claims.put(OidcProviderMetadataClaimNames.ISSUER, url("https://example.com/issuer1"));
|
||||||
claims.put(OidcProviderMetadataClaimNames.AUTHORIZATION_ENDPOINT, url("https://example.com/issuer1/oauth2/authorize"));
|
claims.put(OidcProviderMetadataClaimNames.AUTHORIZATION_ENDPOINT, url("https://example.com/issuer1/oauth2/authorize"));
|
||||||
claims.put(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT, url("https://example.com/issuer1/oauth2/token"));
|
claims.put(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT, url("https://example.com/issuer1/oauth2/token"));
|
||||||
claims.put(OidcProviderMetadataClaimNames.JWKS_URI, url("https://example.com/issuer1/oauth2/jwks"));
|
claims.put(OidcProviderMetadataClaimNames.JWKS_URI, url("https://example.com/issuer1/oauth2/jwks"));
|
||||||
claims.put(OidcProviderMetadataClaimNames.SCOPES_SUPPORTED, Collections.singleton("openid"));
|
claims.put(OidcProviderMetadataClaimNames.SCOPES_SUPPORTED, Collections.singletonList("openid"));
|
||||||
claims.put(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED, Collections.singleton("code"));
|
claims.put(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED, Collections.singletonList("code"));
|
||||||
claims.put(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED, Collections.singleton("public"));
|
claims.put(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED, Collections.singletonList("public"));
|
||||||
claims.put("some-claim", "some-value");
|
claims.put("some-claim", "some-value");
|
||||||
|
|
||||||
OidcProviderConfiguration providerConfiguration = OidcProviderConfiguration.withClaims(claims).build();
|
OidcProviderConfiguration providerConfiguration = OidcProviderConfiguration.withClaims(claims).build();
|
||||||
@ -142,45 +143,46 @@ public class OidcProviderConfigurationTests {
|
|||||||
assertThat(providerConfiguration.getGrantTypes()).isNull();
|
assertThat(providerConfiguration.getGrantTypes()).isNull();
|
||||||
assertThat(providerConfiguration.getSubjectTypes()).containsExactly("public");
|
assertThat(providerConfiguration.getSubjectTypes()).containsExactly("public");
|
||||||
assertThat(providerConfiguration.getTokenEndpointAuthenticationMethods()).isNull();
|
assertThat(providerConfiguration.getTokenEndpointAuthenticationMethods()).isNull();
|
||||||
assertThat(providerConfiguration.getClaimAsString("some-claim")).isEqualTo("some-value");
|
assertThat(providerConfiguration.<String>getClaim("some-claim")).isEqualTo("some-value");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void withClaimsWhenNullThenThrowsException() {
|
public void withClaimsWhenNullThenThrowIllegalArgumentException() {
|
||||||
assertThatThrownBy(() -> OidcProviderConfiguration.withClaims(null))
|
assertThatThrownBy(() -> OidcProviderConfiguration.withClaims(null))
|
||||||
.isInstanceOf(IllegalArgumentException.class);
|
.isInstanceOf(IllegalArgumentException.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void withClaimsWhenMissingRequiredClaimsThenThrowsException() {
|
public void withClaimsWhenMissingRequiredClaimsThenThrowIllegalArgumentException() {
|
||||||
assertThatThrownBy(() -> OidcProviderConfiguration.withClaims(Collections.emptyMap()))
|
assertThatThrownBy(() -> OidcProviderConfiguration.withClaims(Collections.emptyMap()))
|
||||||
.isInstanceOf(IllegalArgumentException.class);
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
|
.hasMessage("claims cannot be empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildWhenCalledTwiceThenGeneratesTwoConfigurations() {
|
public void buildWhenCalledTwiceThenGeneratesTwoConfigurations() {
|
||||||
OidcProviderConfiguration first = minimalConfigurationBuilder
|
OidcProviderConfiguration first = this.minimalConfigurationBuilder
|
||||||
.grantType("client_credentials")
|
.grantType("client_credentials")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
OidcProviderConfiguration second = minimalConfigurationBuilder
|
OidcProviderConfiguration second = this.minimalConfigurationBuilder
|
||||||
.claims((claims) ->
|
.claims((claims) ->
|
||||||
{
|
{
|
||||||
LinkedHashSet<String> newGrantTypes = new LinkedHashSet<>();
|
Set<String> newGrantTypes = new LinkedHashSet<>();
|
||||||
newGrantTypes.add("authorization_code");
|
newGrantTypes.add("authorization_code");
|
||||||
newGrantTypes.add("implicit");
|
newGrantTypes.add("custom_grant");
|
||||||
claims.put(OidcProviderMetadataClaimNames.GRANT_TYPES_SUPPORTED, newGrantTypes);
|
claims.put(OidcProviderMetadataClaimNames.GRANT_TYPES_SUPPORTED, newGrantTypes);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
assertThat(first.getGrantTypes()).containsExactly("client_credentials");
|
assertThat(first.getGrantTypes()).containsExactly("client_credentials");
|
||||||
assertThat(second.getGrantTypes()).containsExactlyInAnyOrder("authorization_code", "implicit");
|
assertThat(second.getGrantTypes()).containsExactlyInAnyOrder("authorization_code", "custom_grant");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildWhenMissingIssuerThenThrowsException() {
|
public void buildWhenMissingIssuerThenThrowIllegalArgumentException() {
|
||||||
OidcProviderConfiguration.Builder builder = minimalConfigurationBuilder
|
OidcProviderConfiguration.Builder builder = this.minimalConfigurationBuilder
|
||||||
.claims((claims) -> claims.remove(OidcProviderMetadataClaimNames.ISSUER));
|
.claims((claims) -> claims.remove(OidcProviderMetadataClaimNames.ISSUER));
|
||||||
|
|
||||||
assertThatThrownBy(builder::build)
|
assertThatThrownBy(builder::build)
|
||||||
@ -189,18 +191,18 @@ public class OidcProviderConfigurationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildWhenIssuerIsNotAnUrlThenThrowsException() {
|
public void buildWhenIssuerNotUrlThenThrowIllegalArgumentException() {
|
||||||
OidcProviderConfiguration.Builder builder = minimalConfigurationBuilder
|
OidcProviderConfiguration.Builder builder = this.minimalConfigurationBuilder
|
||||||
.claims((claims) -> claims.put(OidcProviderMetadataClaimNames.ISSUER, "not an url"));
|
.claims((claims) -> claims.put(OidcProviderMetadataClaimNames.ISSUER, "not an url"));
|
||||||
|
|
||||||
assertThatThrownBy(builder::build)
|
assertThatThrownBy(builder::build)
|
||||||
.isInstanceOf(IllegalArgumentException.class)
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
.hasMessageStartingWith("issuer must be a valid URL");
|
.hasMessage("issuer must be a valid URL");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildWhenMissingAuthorizationEndpointThenThrowsException() {
|
public void buildWhenMissingAuthorizationEndpointThenThrowIllegalArgumentException() {
|
||||||
OidcProviderConfiguration.Builder builder = minimalConfigurationBuilder
|
OidcProviderConfiguration.Builder builder = this.minimalConfigurationBuilder
|
||||||
.claims((claims) -> claims.remove(OidcProviderMetadataClaimNames.AUTHORIZATION_ENDPOINT));
|
.claims((claims) -> claims.remove(OidcProviderMetadataClaimNames.AUTHORIZATION_ENDPOINT));
|
||||||
|
|
||||||
assertThatThrownBy(builder::build)
|
assertThatThrownBy(builder::build)
|
||||||
@ -209,8 +211,8 @@ public class OidcProviderConfigurationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildWhenAuthorizationEndpointIsNotAnUrlThenThrowsException() {
|
public void buildWhenAuthorizationEndpointNotUrlThenThrowIllegalArgumentException() {
|
||||||
OidcProviderConfiguration.Builder builder = minimalConfigurationBuilder
|
OidcProviderConfiguration.Builder builder = this.minimalConfigurationBuilder
|
||||||
.claims((claims) -> claims.put(OidcProviderMetadataClaimNames.AUTHORIZATION_ENDPOINT, "not an url"));
|
.claims((claims) -> claims.put(OidcProviderMetadataClaimNames.AUTHORIZATION_ENDPOINT, "not an url"));
|
||||||
|
|
||||||
assertThatThrownBy(builder::build)
|
assertThatThrownBy(builder::build)
|
||||||
@ -219,8 +221,8 @@ public class OidcProviderConfigurationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildWhenMissingTokenEndpointThenThrowsException() {
|
public void buildWhenMissingTokenEndpointThenThrowIllegalArgumentException() {
|
||||||
OidcProviderConfiguration.Builder builder = minimalConfigurationBuilder
|
OidcProviderConfiguration.Builder builder = this.minimalConfigurationBuilder
|
||||||
.claims((claims) -> claims.remove(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT));
|
.claims((claims) -> claims.remove(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT));
|
||||||
|
|
||||||
assertThatThrownBy(builder::build)
|
assertThatThrownBy(builder::build)
|
||||||
@ -229,8 +231,8 @@ public class OidcProviderConfigurationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildWhenTokenEndpointIsNotAnUrlThenThrowsException() {
|
public void buildWhenTokenEndpointNotUrlThenThrowIllegalArgumentException() {
|
||||||
OidcProviderConfiguration.Builder builder = minimalConfigurationBuilder
|
OidcProviderConfiguration.Builder builder = this.minimalConfigurationBuilder
|
||||||
.claims((claims) -> claims.put(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT, "not an url"));
|
.claims((claims) -> claims.put(OidcProviderMetadataClaimNames.TOKEN_ENDPOINT, "not an url"));
|
||||||
|
|
||||||
assertThatThrownBy(builder::build)
|
assertThatThrownBy(builder::build)
|
||||||
@ -239,48 +241,100 @@ public class OidcProviderConfigurationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildWhenMissingJwksUriThenThrowsException() {
|
public void buildWhenMissingJwksUriThenThrowIllegalArgumentException() {
|
||||||
OidcProviderConfiguration.Builder builder = minimalConfigurationBuilder
|
OidcProviderConfiguration.Builder builder = this.minimalConfigurationBuilder
|
||||||
.claims((claims) -> claims.remove(OidcProviderMetadataClaimNames.JWKS_URI));
|
.claims((claims) -> claims.remove(OidcProviderMetadataClaimNames.JWKS_URI));
|
||||||
|
|
||||||
assertThatThrownBy(builder::build)
|
assertThatThrownBy(builder::build)
|
||||||
.isInstanceOf(IllegalArgumentException.class)
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
.hasMessage("jwkSetUri cannot be null");
|
.hasMessage("jwksUri cannot be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildWheJwksUriIsNotAnUrlThenThrowsException() {
|
public void buildWhenJwksUriNotUrlThenThrowIllegalArgumentException() {
|
||||||
OidcProviderConfiguration.Builder builder = minimalConfigurationBuilder
|
OidcProviderConfiguration.Builder builder = this.minimalConfigurationBuilder
|
||||||
.claims((claims) -> claims.put(OidcProviderMetadataClaimNames.JWKS_URI, "not an url"));
|
.claims((claims) -> claims.put(OidcProviderMetadataClaimNames.JWKS_URI, "not an url"));
|
||||||
|
|
||||||
assertThatThrownBy(builder::build)
|
assertThatThrownBy(builder::build)
|
||||||
.isInstanceOf(IllegalArgumentException.class)
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
.hasMessageStartingWith("jwkSetUri must be a valid URL");
|
.hasMessageStartingWith("jwksUri must be a valid URL");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildWhenMissingResponseTypesThenThrowsException() {
|
public void buildWhenMissingResponseTypesThenThrowIllegalArgumentException() {
|
||||||
OidcProviderConfiguration.Builder builder = minimalConfigurationBuilder
|
OidcProviderConfiguration.Builder builder = this.minimalConfigurationBuilder
|
||||||
.claims((claims) -> claims.remove(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED));
|
.claims((claims) -> claims.remove(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED));
|
||||||
|
|
||||||
assertThatThrownBy(builder::build)
|
assertThatThrownBy(builder::build)
|
||||||
.isInstanceOf(IllegalArgumentException.class)
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
.hasMessage("responseTypes cannot be empty");
|
.hasMessage("responseTypes cannot be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildWhenMissingSubjectTypesThenThrowsException() {
|
public void buildWhenResponseTypesNotListThenThrowIllegalArgumentException() {
|
||||||
OidcProviderConfiguration.Builder builder = minimalConfigurationBuilder
|
OidcProviderConfiguration.Builder builder = this.minimalConfigurationBuilder
|
||||||
|
.claims((claims) -> {
|
||||||
|
claims.remove(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED);
|
||||||
|
claims.put(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED, "code");
|
||||||
|
});
|
||||||
|
|
||||||
|
assertThatThrownBy(builder::build)
|
||||||
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
|
.hasMessageContaining("responseTypes must be of type List");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void buildWhenResponseTypesEmptyListThenThrowIllegalArgumentException() {
|
||||||
|
OidcProviderConfiguration.Builder builder = this.minimalConfigurationBuilder
|
||||||
|
.claims((claims) -> {
|
||||||
|
claims.remove(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED);
|
||||||
|
claims.put(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED, Collections.emptyList());
|
||||||
|
});
|
||||||
|
|
||||||
|
assertThatThrownBy(builder::build)
|
||||||
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
|
.hasMessageContaining("responseTypes cannot be empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void buildWhenMissingSubjectTypesThenThrowIllegalArgumentException() {
|
||||||
|
OidcProviderConfiguration.Builder builder = this.minimalConfigurationBuilder
|
||||||
.claims((claims) -> claims.remove(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED));
|
.claims((claims) -> claims.remove(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED));
|
||||||
|
|
||||||
assertThatThrownBy(builder::build)
|
assertThatThrownBy(builder::build)
|
||||||
.isInstanceOf(IllegalArgumentException.class)
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
.hasMessage("subjectTypes cannot be empty");
|
.hasMessage("subjectTypes cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void buildWhenSubjectTypesNotListThenThrowIllegalArgumentException() {
|
||||||
|
OidcProviderConfiguration.Builder builder = this.minimalConfigurationBuilder
|
||||||
|
.claims((claims) -> {
|
||||||
|
claims.remove(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED);
|
||||||
|
claims.put(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED, "public");
|
||||||
|
});
|
||||||
|
|
||||||
|
assertThatThrownBy(builder::build)
|
||||||
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
|
.hasMessageContaining("subjectTypes must be of type List");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void buildWhenSubjectTypesEmptyListThenThrowIllegalArgumentException() {
|
||||||
|
OidcProviderConfiguration.Builder builder = this.minimalConfigurationBuilder
|
||||||
|
.claims((claims) -> {
|
||||||
|
claims.remove(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED);
|
||||||
|
claims.put(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED, Collections.emptyList());
|
||||||
|
});
|
||||||
|
|
||||||
|
assertThatThrownBy(builder::build)
|
||||||
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
|
.hasMessageContaining("subjectTypes cannot be empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void responseTypesWhenAddingOrRemovingThenCorrectValues() {
|
public void responseTypesWhenAddingOrRemovingThenCorrectValues() {
|
||||||
OidcProviderConfiguration configuration = minimalConfigurationBuilder
|
OidcProviderConfiguration configuration = this.minimalConfigurationBuilder
|
||||||
.responseType("should-be-removed")
|
.responseType("should-be-removed")
|
||||||
.responseTypes(responseTypes -> {
|
.responseTypes(responseTypes -> {
|
||||||
responseTypes.clear();
|
responseTypes.clear();
|
||||||
@ -293,7 +347,7 @@ public class OidcProviderConfigurationTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void responseTypesWhenNotPresentAndAddingThenCorrectValues() {
|
public void responseTypesWhenNotPresentAndAddingThenCorrectValues() {
|
||||||
OidcProviderConfiguration configuration = minimalConfigurationBuilder
|
OidcProviderConfiguration configuration = this.minimalConfigurationBuilder
|
||||||
.claims(claims -> claims.remove(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED))
|
.claims(claims -> claims.remove(OidcProviderMetadataClaimNames.RESPONSE_TYPES_SUPPORTED))
|
||||||
.responseTypes(responseTypes -> responseTypes.add("some-response-type"))
|
.responseTypes(responseTypes -> responseTypes.add("some-response-type"))
|
||||||
.build();
|
.build();
|
||||||
@ -303,7 +357,7 @@ public class OidcProviderConfigurationTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void subjectTypesWhenAddingOrRemovingThenCorrectValues() {
|
public void subjectTypesWhenAddingOrRemovingThenCorrectValues() {
|
||||||
OidcProviderConfiguration configuration = minimalConfigurationBuilder
|
OidcProviderConfiguration configuration = this.minimalConfigurationBuilder
|
||||||
.subjectType("should-be-removed")
|
.subjectType("should-be-removed")
|
||||||
.subjectTypes(subjectTypes -> {
|
.subjectTypes(subjectTypes -> {
|
||||||
subjectTypes.clear();
|
subjectTypes.clear();
|
||||||
@ -316,7 +370,7 @@ public class OidcProviderConfigurationTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void scopesWhenAddingOrRemovingThenCorrectValues() {
|
public void scopesWhenAddingOrRemovingThenCorrectValues() {
|
||||||
OidcProviderConfiguration configuration = minimalConfigurationBuilder
|
OidcProviderConfiguration configuration = this.minimalConfigurationBuilder
|
||||||
.scope("should-be-removed")
|
.scope("should-be-removed")
|
||||||
.scopes(scopes -> {
|
.scopes(scopes -> {
|
||||||
scopes.clear();
|
scopes.clear();
|
||||||
@ -329,7 +383,7 @@ public class OidcProviderConfigurationTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void grantTypesWhenAddingOrRemovingThenCorrectValues() {
|
public void grantTypesWhenAddingOrRemovingThenCorrectValues() {
|
||||||
OidcProviderConfiguration configuration = minimalConfigurationBuilder
|
OidcProviderConfiguration configuration = this.minimalConfigurationBuilder
|
||||||
.grantType("should-be-removed")
|
.grantType("should-be-removed")
|
||||||
.grantTypes(grantTypes -> {
|
.grantTypes(grantTypes -> {
|
||||||
grantTypes.clear();
|
grantTypes.clear();
|
||||||
@ -342,7 +396,7 @@ public class OidcProviderConfigurationTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void tokenEndpointAuthenticationMethodsWhenAddingOrRemovingThenCorrectValues() {
|
public void tokenEndpointAuthenticationMethodsWhenAddingOrRemovingThenCorrectValues() {
|
||||||
OidcProviderConfiguration configuration = minimalConfigurationBuilder
|
OidcProviderConfiguration configuration = this.minimalConfigurationBuilder
|
||||||
.tokenEndpointAuthenticationMethod("should-be-removed")
|
.tokenEndpointAuthenticationMethod("should-be-removed")
|
||||||
.tokenEndpointAuthenticationMethods(authMethods -> {
|
.tokenEndpointAuthenticationMethods(authMethods -> {
|
||||||
authMethods.clear();
|
authMethods.clear();
|
||||||
@ -355,24 +409,22 @@ public class OidcProviderConfigurationTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void claimWhenNameIsNullThenThrowIllegalArgumentException() {
|
public void claimWhenNameIsNullThenThrowIllegalArgumentException() {
|
||||||
OidcProviderConfiguration.Builder builder = OidcProviderConfiguration.withClaims();
|
assertThatThrownBy(() -> OidcProviderConfiguration.withClaims().claim(null, "value"))
|
||||||
assertThatThrownBy(() -> builder.claim(null, "value"))
|
|
||||||
.isInstanceOf(IllegalArgumentException.class)
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
.hasMessage("name cannot be empty");
|
.hasMessage("name cannot be empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void claimWhenValueIsNullThenThrowIllegalArgumentException() {
|
public void claimWhenValueIsNullThenThrowIllegalArgumentException() {
|
||||||
OidcProviderConfiguration.Builder builder = OidcProviderConfiguration.withClaims();
|
assertThatThrownBy(() -> OidcProviderConfiguration.withClaims().claim("claim-name", null))
|
||||||
assertThatThrownBy(() -> builder.claim("claim-name", null))
|
|
||||||
.isInstanceOf(IllegalArgumentException.class)
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
.hasMessage("value cannot be null");
|
.hasMessage("value cannot be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void claimsWhenRemovingAClaimThenIsNotPresent() {
|
public void claimsWhenRemovingClaimThenNotPresent() {
|
||||||
OidcProviderConfiguration configuration =
|
OidcProviderConfiguration configuration =
|
||||||
minimalConfigurationBuilder
|
this.minimalConfigurationBuilder
|
||||||
.grantType("some-grant-type")
|
.grantType("some-grant-type")
|
||||||
.claims((claims) -> claims.remove(OidcProviderMetadataClaimNames.GRANT_TYPES_SUPPORTED))
|
.claims((claims) -> claims.remove(OidcProviderMetadataClaimNames.GRANT_TYPES_SUPPORTED))
|
||||||
.build();
|
.build();
|
||||||
@ -380,9 +432,9 @@ public class OidcProviderConfigurationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void claimsWhenAddingAClaimThenIsPresent() {
|
public void claimsWhenAddingClaimThenPresent() {
|
||||||
OidcProviderConfiguration configuration =
|
OidcProviderConfiguration configuration =
|
||||||
minimalConfigurationBuilder
|
this.minimalConfigurationBuilder
|
||||||
.claims((claims) -> claims.put(OidcProviderMetadataClaimNames.GRANT_TYPES_SUPPORTED, "authorization_code"))
|
.claims((claims) -> claims.put(OidcProviderMetadataClaimNames.GRANT_TYPES_SUPPORTED, "authorization_code"))
|
||||||
.build();
|
.build();
|
||||||
assertThat(configuration.getGrantTypes()).containsExactly("authorization_code");
|
assertThat(configuration.getGrantTypes()).containsExactly("authorization_code");
|
||||||
@ -391,7 +443,7 @@ public class OidcProviderConfigurationTests {
|
|||||||
private static URL url(String urlString) {
|
private static URL url(String urlString) {
|
||||||
try {
|
try {
|
||||||
return new URL(urlString);
|
return new URL(urlString);
|
||||||
} catch (MalformedURLException e) {
|
} catch (Exception ex) {
|
||||||
throw new IllegalArgumentException("urlString must be a valid URL and valid URI");
|
throw new IllegalArgumentException("urlString must be a valid URL and valid URI");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.security.oauth2.core.http.converter;
|
package org.springframework.security.oauth2.core.oidc.http.converter;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.core.convert.converter.Converter;
|
import org.springframework.core.convert.converter.Converter;
|
||||||
@ -24,7 +24,6 @@ import org.springframework.mock.http.MockHttpOutputMessage;
|
|||||||
import org.springframework.mock.http.client.MockClientHttpResponse;
|
import org.springframework.mock.http.client.MockClientHttpResponse;
|
||||||
import org.springframework.security.oauth2.core.oidc.OidcProviderConfiguration;
|
import org.springframework.security.oauth2.core.oidc.OidcProviderConfiguration;
|
||||||
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -48,17 +47,17 @@ public class OidcProviderConfigurationHttpMessageConverterTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void setProviderConfigurationParametersConverterWhenConverterIsNullThenThrowIllegalArgumentException() {
|
public void setProviderConfigurationParametersConverterWhenNullThenThrowIllegalArgumentException() {
|
||||||
assertThatIllegalArgumentException().isThrownBy(() -> this.messageConverter.setProviderConfigurationParametersConverter(null));
|
assertThatIllegalArgumentException().isThrownBy(() -> this.messageConverter.setProviderConfigurationParametersConverter(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void setProviderConfigurationConverterWhenConverterIsNullThenThrowIllegalArgumentException() {
|
public void setProviderConfigurationConverterWhenNullThenThrowIllegalArgumentException() {
|
||||||
assertThatIllegalArgumentException().isThrownBy(() -> this.messageConverter.setProviderConfigurationConverter(null));
|
assertThatIllegalArgumentException().isThrownBy(() -> this.messageConverter.setProviderConfigurationConverter(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void readInternalWhenSuccessfulProviderConfigurationOnlyRequiredParametersThenReadOidcProviderConfiguration() throws Exception {
|
public void readInternalWhenRequiredParametersThenSuccess() throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
String providerConfigurationResponse = "{\n"
|
String providerConfigurationResponse = "{\n"
|
||||||
+ " \"issuer\": \"https://example.com/issuer1\",\n"
|
+ " \"issuer\": \"https://example.com/issuer1\",\n"
|
||||||
@ -85,7 +84,7 @@ public class OidcProviderConfigurationHttpMessageConverterTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void readInternalWhenSuccessfulProviderConfigurationThenReadOidcProviderConfiguration() throws Exception {
|
public void readInternalWhenValidParametersThenSuccess() throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
String providerConfigurationResponse = "{\n"
|
String providerConfigurationResponse = "{\n"
|
||||||
+ " \"issuer\": \"https://example.com/issuer1\",\n"
|
+ " \"issuer\": \"https://example.com/issuer1\",\n"
|
||||||
@ -96,7 +95,7 @@ public class OidcProviderConfigurationHttpMessageConverterTests {
|
|||||||
+ " \"response_types_supported\": [\"code\"],\n"
|
+ " \"response_types_supported\": [\"code\"],\n"
|
||||||
+ " \"grant_types_supported\": [\"authorization_code\", \"client_credentials\"],\n"
|
+ " \"grant_types_supported\": [\"authorization_code\", \"client_credentials\"],\n"
|
||||||
+ " \"subject_types_supported\": [\"public\"],\n"
|
+ " \"subject_types_supported\": [\"public\"],\n"
|
||||||
+ " \"token_endpoint_auth_methods_supported\": [\"basic\"],\n"
|
+ " \"token_endpoint_auth_methods_supported\": [\"client_secret_basic\"],\n"
|
||||||
+ " \"custom_claim\": \"value\",\n"
|
+ " \"custom_claim\": \"value\",\n"
|
||||||
+ " \"custom_collection_claim\": [\"value1\", \"value2\"]\n"
|
+ " \"custom_collection_claim\": [\"value1\", \"value2\"]\n"
|
||||||
+ "}\n";
|
+ "}\n";
|
||||||
@ -113,8 +112,8 @@ public class OidcProviderConfigurationHttpMessageConverterTests {
|
|||||||
assertThat(providerConfiguration.getResponseTypes()).containsExactly("code");
|
assertThat(providerConfiguration.getResponseTypes()).containsExactly("code");
|
||||||
assertThat(providerConfiguration.getGrantTypes()).containsExactlyInAnyOrder("authorization_code", "client_credentials");
|
assertThat(providerConfiguration.getGrantTypes()).containsExactlyInAnyOrder("authorization_code", "client_credentials");
|
||||||
assertThat(providerConfiguration.getSubjectTypes()).containsExactly("public");
|
assertThat(providerConfiguration.getSubjectTypes()).containsExactly("public");
|
||||||
assertThat(providerConfiguration.getTokenEndpointAuthenticationMethods()).containsExactly("basic");
|
assertThat(providerConfiguration.getTokenEndpointAuthenticationMethods()).containsExactly("client_secret_basic");
|
||||||
assertThat(providerConfiguration.getClaimAsString("custom_claim")).isEqualTo("value");
|
assertThat(providerConfiguration.<String>getClaim("custom_claim")).isEqualTo("value");
|
||||||
assertThat(providerConfiguration.getClaimAsStringList("custom_collection_claim")).containsExactlyInAnyOrder("value1", "value2");
|
assertThat(providerConfiguration.getClaimAsStringList("custom_collection_claim")).containsExactlyInAnyOrder("value1", "value2");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +143,7 @@ public class OidcProviderConfigurationHttpMessageConverterTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void writeInternalWhenOidcProviderConfigurationThenWriteTokenResponse() throws Exception {
|
public void writeInternalWhenProviderConfigurationThenSuccess() {
|
||||||
OidcProviderConfiguration providerConfiguration =
|
OidcProviderConfiguration providerConfiguration =
|
||||||
OidcProviderConfiguration.withClaims()
|
OidcProviderConfiguration.withClaims()
|
||||||
.issuer("https://example.com/issuer1")
|
.issuer("https://example.com/issuer1")
|
||||||
@ -156,7 +155,7 @@ public class OidcProviderConfigurationHttpMessageConverterTests {
|
|||||||
.grantType("authorization_code")
|
.grantType("authorization_code")
|
||||||
.grantType("client_credentials")
|
.grantType("client_credentials")
|
||||||
.subjectType("public")
|
.subjectType("public")
|
||||||
.tokenEndpointAuthenticationMethod("basic")
|
.tokenEndpointAuthenticationMethod("client_secret_basic")
|
||||||
.claim("custom_claim", "value")
|
.claim("custom_claim", "value")
|
||||||
.claim("custom_collection_claim", Arrays.asList("value1", "value2"))
|
.claim("custom_collection_claim", Arrays.asList("value1", "value2"))
|
||||||
.build();
|
.build();
|
||||||
@ -173,14 +172,13 @@ public class OidcProviderConfigurationHttpMessageConverterTests {
|
|||||||
assertThat(providerConfigurationResponse).contains("\"response_types_supported\":[\"code\"]");
|
assertThat(providerConfigurationResponse).contains("\"response_types_supported\":[\"code\"]");
|
||||||
assertThat(providerConfigurationResponse).contains("\"grant_types_supported\":[\"authorization_code\",\"client_credentials\"]");
|
assertThat(providerConfigurationResponse).contains("\"grant_types_supported\":[\"authorization_code\",\"client_credentials\"]");
|
||||||
assertThat(providerConfigurationResponse).contains("\"subject_types_supported\":[\"public\"]");
|
assertThat(providerConfigurationResponse).contains("\"subject_types_supported\":[\"public\"]");
|
||||||
assertThat(providerConfigurationResponse).contains("\"token_endpoint_auth_methods_supported\":[\"basic\"]");
|
assertThat(providerConfigurationResponse).contains("\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\"]");
|
||||||
assertThat(providerConfigurationResponse).contains("\"custom_claim\":\"value\"");
|
assertThat(providerConfigurationResponse).contains("\"custom_claim\":\"value\"");
|
||||||
assertThat(providerConfigurationResponse).contains("\"custom_collection_claim\":[\"value1\",\"value2\"]");
|
assertThat(providerConfigurationResponse).contains("\"custom_collection_claim\":[\"value1\",\"value2\"]");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
public void writeInternalWhenWriteFailsThenThrowsException() {
|
||||||
public void writeInternalWhenWriteFailsThenThrowsException() throws MalformedURLException {
|
|
||||||
String errorMessage = "this is not a valid converter";
|
String errorMessage = "this is not a valid converter";
|
||||||
Converter<OidcProviderConfiguration, Map<String, Object>> failingConverter =
|
Converter<OidcProviderConfiguration, Map<String, Object>> failingConverter =
|
||||||
source -> {
|
source -> {
|
||||||
@ -190,10 +188,10 @@ public class OidcProviderConfigurationHttpMessageConverterTests {
|
|||||||
|
|
||||||
OidcProviderConfiguration providerConfiguration =
|
OidcProviderConfiguration providerConfiguration =
|
||||||
OidcProviderConfiguration.withClaims()
|
OidcProviderConfiguration.withClaims()
|
||||||
.issuer("https://example.com")
|
.issuer("https://example.com/issuer1")
|
||||||
.authorizationEndpoint("https://example.com")
|
.authorizationEndpoint("https://example.com/issuer1/oauth2/authorize")
|
||||||
.tokenEndpoint("https://example.com")
|
.tokenEndpoint("https://example.com/issuer1/oauth2/token")
|
||||||
.jwksUri("https://example.com")
|
.jwksUri("https://example.com/issuer1/oauth2/jwks")
|
||||||
.responseType("code")
|
.responseType("code")
|
||||||
.subjectType("public")
|
.subjectType("public")
|
||||||
.build();
|
.build();
|
@ -17,8 +17,6 @@ package org.springframework.security.oauth2.server.authorization.config;
|
|||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
|
|
||||||
@ -28,41 +26,42 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
|||||||
* @author Daniel Garnier-Moiroux
|
* @author Daniel Garnier-Moiroux
|
||||||
*/
|
*/
|
||||||
public class ProviderSettingsTests {
|
public class ProviderSettingsTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void constructorWhenDefaultThenDefaultsAreSetAndIssuerIsNotSet() {
|
public void constructorWhenDefaultThenDefaultsAreSet() {
|
||||||
ProviderSettings providerSettings = new ProviderSettings();
|
ProviderSettings providerSettings = new ProviderSettings();
|
||||||
|
|
||||||
assertThat(providerSettings.issuer()).isNull();
|
assertThat(providerSettings.issuer()).isNull();
|
||||||
assertThat(providerSettings.authorizationEndpoint()).isEqualTo("/oauth2/authorize");
|
assertThat(providerSettings.authorizationEndpoint()).isEqualTo("/oauth2/authorize");
|
||||||
assertThat(providerSettings.tokenEndpoint()).isEqualTo("/oauth2/token");
|
assertThat(providerSettings.tokenEndpoint()).isEqualTo("/oauth2/token");
|
||||||
assertThat(providerSettings.jwkSetEndpoint()).isEqualTo("/oauth2/jwks");
|
assertThat(providerSettings.jwksEndpoint()).isEqualTo("/oauth2/jwks");
|
||||||
assertThat(providerSettings.tokenRevocationEndpoint()).isEqualTo("/oauth2/revoke");
|
assertThat(providerSettings.tokenRevocationEndpoint()).isEqualTo("/oauth2/revoke");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void settingsWhenProvidedThenSet() throws MalformedURLException {
|
public void settingsWhenProvidedThenSet() {
|
||||||
String authorizationEndpoint = "/my-endpoints/authorize";
|
String authorizationEndpoint = "/oauth2/v1/authorize";
|
||||||
String tokenEndpoint = "/my-endpoints/token";
|
String tokenEndpoint = "/oauth2/v1/token";
|
||||||
String jwksEndpoint = "/my-endpoints/jwks";
|
String jwksEndpoint = "/oauth2/v1/jwks";
|
||||||
String tokenRevocationEndpoint = "/my-endpoints/revoke";
|
String tokenRevocationEndpoint = "/oauth2/v1/revoke";
|
||||||
String issuer = "https://example.com/9000";
|
String issuer = "https://example.com:9000";
|
||||||
|
|
||||||
ProviderSettings providerSettings = new ProviderSettings()
|
ProviderSettings providerSettings = new ProviderSettings()
|
||||||
.issuer(issuer)
|
.issuer(issuer)
|
||||||
.authorizationEndpoint(authorizationEndpoint)
|
.authorizationEndpoint(authorizationEndpoint)
|
||||||
.tokenEndpoint(tokenEndpoint)
|
.tokenEndpoint(tokenEndpoint)
|
||||||
.jwkSetEndpoint(jwksEndpoint)
|
.jwksEndpoint(jwksEndpoint)
|
||||||
.tokenRevocationEndpoint(tokenRevocationEndpoint);
|
.tokenRevocationEndpoint(tokenRevocationEndpoint);
|
||||||
|
|
||||||
assertThat(providerSettings.issuer()).isEqualTo(issuer);
|
assertThat(providerSettings.issuer()).isEqualTo(issuer);
|
||||||
assertThat(providerSettings.authorizationEndpoint()).isEqualTo(authorizationEndpoint);
|
assertThat(providerSettings.authorizationEndpoint()).isEqualTo(authorizationEndpoint);
|
||||||
assertThat(providerSettings.tokenEndpoint()).isEqualTo(tokenEndpoint);
|
assertThat(providerSettings.tokenEndpoint()).isEqualTo(tokenEndpoint);
|
||||||
assertThat(providerSettings.jwkSetEndpoint()).isEqualTo(jwksEndpoint);
|
assertThat(providerSettings.jwksEndpoint()).isEqualTo(jwksEndpoint);
|
||||||
assertThat(providerSettings.tokenRevocationEndpoint()).isEqualTo(tokenRevocationEndpoint);
|
assertThat(providerSettings.tokenRevocationEndpoint()).isEqualTo(tokenRevocationEndpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void settingWhenCalledThenReturnTokenSettings() {
|
public void settingWhenCustomThenReturnAllSettings() {
|
||||||
ProviderSettings providerSettings = new ProviderSettings()
|
ProviderSettings providerSettings = new ProviderSettings()
|
||||||
.setting("name1", "value1")
|
.setting("name1", "value1")
|
||||||
.settings(settings -> settings.put("name2", "value2"));
|
.settings(settings -> settings.put("name2", "value2"));
|
||||||
@ -73,54 +72,42 @@ public class ProviderSettingsTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void issuerWhenNullThenThrowsIllegalArgumentException() {
|
public void issuerWhenNullThenThrowIllegalArgumentException() {
|
||||||
ProviderSettings settings = new ProviderSettings();
|
ProviderSettings settings = new ProviderSettings();
|
||||||
assertThatThrownBy(() -> settings.issuer(null))
|
assertThatThrownBy(() -> settings.issuer(null))
|
||||||
.isInstanceOf(IllegalArgumentException.class)
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
.hasMessage("issuer cannot be null");
|
.hasMessage("value cannot be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void authorizationEndpointWhenNullThenThrowsIllegalArgumentException() {
|
public void authorizationEndpointWhenNullThenThrowIllegalArgumentException() {
|
||||||
ProviderSettings settings = new ProviderSettings();
|
ProviderSettings settings = new ProviderSettings();
|
||||||
assertThatThrownBy(() -> settings.authorizationEndpoint(null))
|
assertThatThrownBy(() -> settings.authorizationEndpoint(null))
|
||||||
.isInstanceOf(IllegalArgumentException.class)
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
.hasMessage("authorizationEndpoint cannot be empty");
|
.hasMessage("value cannot be null");
|
||||||
assertThatThrownBy(() -> settings.authorizationEndpoint(""))
|
|
||||||
.isInstanceOf(IllegalArgumentException.class)
|
|
||||||
.hasMessage("authorizationEndpoint cannot be empty");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void tokenEndpointWhenNullThenThrowsIllegalArgumentException() {
|
public void tokenEndpointWhenNullThenThrowIllegalArgumentException() {
|
||||||
ProviderSettings settings = new ProviderSettings();
|
ProviderSettings settings = new ProviderSettings();
|
||||||
assertThatThrownBy(() -> settings.tokenEndpoint(null))
|
assertThatThrownBy(() -> settings.tokenEndpoint(null))
|
||||||
.isInstanceOf(IllegalArgumentException.class)
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
.hasMessage("tokenEndpoint cannot be empty");
|
.hasMessage("value cannot be null");
|
||||||
assertThatThrownBy(() -> settings.tokenEndpoint(""))
|
|
||||||
.isInstanceOf(IllegalArgumentException.class)
|
|
||||||
.hasMessage("tokenEndpoint cannot be empty");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void tokenRevocationEndpointWhenNullThenThrowsIllegalArgumentException() {
|
public void tokenRevocationEndpointWhenNullThenThrowIllegalArgumentException() {
|
||||||
ProviderSettings settings = new ProviderSettings();
|
ProviderSettings settings = new ProviderSettings();
|
||||||
assertThatThrownBy(() -> settings.tokenRevocationEndpoint(null))
|
assertThatThrownBy(() -> settings.tokenRevocationEndpoint(null))
|
||||||
.isInstanceOf(IllegalArgumentException.class)
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
.hasMessage("tokenRevocationEndpoint cannot be empty");
|
.hasMessage("value cannot be null");
|
||||||
assertThatThrownBy(() -> settings.tokenRevocationEndpoint(""))
|
|
||||||
.isInstanceOf(IllegalArgumentException.class)
|
|
||||||
.hasMessage("tokenRevocationEndpoint cannot be empty");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void jwkSetEndpointWhenNullThenThrowsIllegalArgumentException() {
|
public void jwksEndpointWhenNullThenThrowIllegalArgumentException() {
|
||||||
ProviderSettings settings = new ProviderSettings();
|
ProviderSettings settings = new ProviderSettings();
|
||||||
assertThatThrownBy(() -> settings.jwkSetEndpoint(null))
|
assertThatThrownBy(() -> settings.jwksEndpoint(null))
|
||||||
.isInstanceOf(IllegalArgumentException.class)
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
.hasMessage("jwkSetEndpoint cannot be empty");
|
.hasMessage("value cannot be null");
|
||||||
assertThatThrownBy(() -> settings.jwkSetEndpoint(""))
|
|
||||||
.isInstanceOf(IllegalArgumentException.class)
|
|
||||||
.hasMessage("jwkSetEndpoint cannot be empty");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ import static org.mockito.Mockito.verifyNoInteractions;
|
|||||||
* @author Daniel Garnier-Moiroux
|
* @author Daniel Garnier-Moiroux
|
||||||
*/
|
*/
|
||||||
public class OidcProviderConfigurationEndpointFilterTests {
|
public class OidcProviderConfigurationEndpointFilterTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void constructorWhenProviderSettingsNullThenThrowIllegalArgumentException() {
|
public void constructorWhenProviderSettingsNullThenThrowIllegalArgumentException() {
|
||||||
assertThatThrownBy(() -> new OidcProviderConfigurationEndpointFilter(null))
|
assertThatThrownBy(() -> new OidcProviderConfigurationEndpointFilter(null))
|
||||||
@ -46,8 +47,10 @@ public class OidcProviderConfigurationEndpointFilterTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doFilterWhenRequestDoesNotMatchThenNotProcessed() throws Exception {
|
public void doFilterWhenNotConfigurationRequestThenNotProcessed() throws Exception {
|
||||||
OidcProviderConfigurationEndpointFilter filter = new OidcProviderConfigurationEndpointFilter(new ProviderSettings());
|
OidcProviderConfigurationEndpointFilter filter =
|
||||||
|
new OidcProviderConfigurationEndpointFilter(new ProviderSettings());
|
||||||
|
|
||||||
String requestUri = "/path";
|
String requestUri = "/path";
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
|
||||||
request.setServletPath(requestUri);
|
request.setServletPath(requestUri);
|
||||||
@ -60,20 +63,38 @@ public class OidcProviderConfigurationEndpointFilterTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doFilterWhenSuccessThenConfigurationResponse() throws Exception {
|
public void doFilterWhenConfigurationRequestPostThenNotProcessed() throws Exception {
|
||||||
String authorizationEndpoint = "/my-endpoints/authorize";
|
OidcProviderConfigurationEndpointFilter filter =
|
||||||
String tokenEndpoint = "/my-endpoints/token";
|
new OidcProviderConfigurationEndpointFilter(new ProviderSettings());
|
||||||
String jwksEndpoint = "/my-endpoints/jwks";
|
|
||||||
|
String requestUri = OidcProviderConfigurationEndpointFilter.DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI;
|
||||||
|
MockHttpServletRequest request = new MockHttpServletRequest("POST", requestUri);
|
||||||
|
request.setServletPath(requestUri);
|
||||||
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
|
FilterChain filterChain = mock(FilterChain.class);
|
||||||
|
|
||||||
|
filter.doFilter(request, response, filterChain);
|
||||||
|
|
||||||
|
verify(filterChain).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void doFilterWhenConfigurationRequestThenConfigurationResponse() throws Exception {
|
||||||
|
String authorizationEndpoint = "/oauth2/v1/authorize";
|
||||||
|
String tokenEndpoint = "/oauth2/v1/token";
|
||||||
|
String jwksEndpoint = "/oauth2/v1/jwks";
|
||||||
|
|
||||||
ProviderSettings providerSettings = new ProviderSettings()
|
ProviderSettings providerSettings = new ProviderSettings()
|
||||||
.issuer("https://example.com/issuer1")
|
.issuer("https://example.com/issuer1")
|
||||||
.authorizationEndpoint(authorizationEndpoint)
|
.authorizationEndpoint(authorizationEndpoint)
|
||||||
.tokenEndpoint(tokenEndpoint)
|
.tokenEndpoint(tokenEndpoint)
|
||||||
.jwkSetEndpoint(jwksEndpoint);
|
.jwksEndpoint(jwksEndpoint);
|
||||||
OidcProviderConfigurationEndpointFilter filter = new OidcProviderConfigurationEndpointFilter(providerSettings);
|
OidcProviderConfigurationEndpointFilter filter =
|
||||||
|
new OidcProviderConfigurationEndpointFilter(providerSettings);
|
||||||
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", org.springframework.security.oauth2.server.authorization.web.OidcProviderConfigurationEndpointFilter.DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI);
|
String requestUri = OidcProviderConfigurationEndpointFilter.DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI;
|
||||||
request.setServletPath(org.springframework.security.oauth2.server.authorization.web.OidcProviderConfigurationEndpointFilter.DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI);
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
|
||||||
|
request.setServletPath(requestUri);
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
FilterChain filterChain = mock(FilterChain.class);
|
FilterChain filterChain = mock(FilterChain.class);
|
||||||
|
|
||||||
@ -84,29 +105,31 @@ public class OidcProviderConfigurationEndpointFilterTests {
|
|||||||
assertThat(response.getContentType()).isEqualTo(MediaType.APPLICATION_JSON_VALUE);
|
assertThat(response.getContentType()).isEqualTo(MediaType.APPLICATION_JSON_VALUE);
|
||||||
String providerConfigurationResponse = response.getContentAsString();
|
String providerConfigurationResponse = response.getContentAsString();
|
||||||
assertThat(providerConfigurationResponse).contains("\"issuer\":\"https://example.com/issuer1\"");
|
assertThat(providerConfigurationResponse).contains("\"issuer\":\"https://example.com/issuer1\"");
|
||||||
assertThat(providerConfigurationResponse).contains("\"authorization_endpoint\":\"https://example.com/issuer1/my-endpoints/authorize\"");
|
assertThat(providerConfigurationResponse).contains("\"authorization_endpoint\":\"https://example.com/issuer1/oauth2/v1/authorize\"");
|
||||||
assertThat(providerConfigurationResponse).contains("\"token_endpoint\":\"https://example.com/issuer1/my-endpoints/token\"");
|
assertThat(providerConfigurationResponse).contains("\"token_endpoint\":\"https://example.com/issuer1/oauth2/v1/token\"");
|
||||||
assertThat(providerConfigurationResponse).contains("\"jwks_uri\":\"https://example.com/issuer1/my-endpoints/jwks\"");
|
assertThat(providerConfigurationResponse).contains("\"jwks_uri\":\"https://example.com/issuer1/oauth2/v1/jwks\"");
|
||||||
assertThat(providerConfigurationResponse).contains("\"scopes_supported\":[\"openid\"]");
|
assertThat(providerConfigurationResponse).contains("\"scopes_supported\":[\"openid\"]");
|
||||||
assertThat(providerConfigurationResponse).contains("\"response_types_supported\":[\"code\"]");
|
assertThat(providerConfigurationResponse).contains("\"response_types_supported\":[\"code\"]");
|
||||||
assertThat(providerConfigurationResponse).contains("\"grant_types_supported\":[\"authorization_code\",\"client_credentials\"]");
|
assertThat(providerConfigurationResponse).contains("\"grant_types_supported\":[\"authorization_code\",\"client_credentials\",\"refresh_token\"]");
|
||||||
assertThat(providerConfigurationResponse).contains("\"subject_types_supported\":[\"public\"]");
|
assertThat(providerConfigurationResponse).contains("\"subject_types_supported\":[\"public\"]");
|
||||||
assertThat(providerConfigurationResponse).contains("\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\"]");
|
assertThat(providerConfigurationResponse).contains("\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\"]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doFilterWhenProviderSettingsWithInvalidIssuerThenThrowIllegalArgumentException() {
|
public void doFilterWhenProviderSettingsWithInvalidIssuerThenThrowIllegalArgumentException() {
|
||||||
ProviderSettings providerSettings = new ProviderSettings()
|
ProviderSettings providerSettings = new ProviderSettings()
|
||||||
.issuer("https://this is an invalid URL");
|
.issuer("https://this is an invalid URL");
|
||||||
OidcProviderConfigurationEndpointFilter filter = new OidcProviderConfigurationEndpointFilter(providerSettings);
|
OidcProviderConfigurationEndpointFilter filter =
|
||||||
|
new OidcProviderConfigurationEndpointFilter(providerSettings);
|
||||||
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", org.springframework.security.oauth2.server.authorization.web.OidcProviderConfigurationEndpointFilter.DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI);
|
String requestUri = OidcProviderConfigurationEndpointFilter.DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI;
|
||||||
request.setServletPath(org.springframework.security.oauth2.server.authorization.web.OidcProviderConfigurationEndpointFilter.DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI);
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
|
||||||
|
request.setServletPath(requestUri);
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
FilterChain filterChain = mock(FilterChain.class);
|
FilterChain filterChain = mock(FilterChain.class);
|
||||||
|
|
||||||
assertThatThrownBy(() -> filter.doFilter(request, response, filterChain))
|
assertThatThrownBy(() -> filter.doFilter(request, response, filterChain))
|
||||||
.isInstanceOf(IllegalArgumentException.class);
|
.isInstanceOf(IllegalArgumentException.class)
|
||||||
|
.hasMessage("issuer must be a valid URL");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user