Make Settings implementations immutable

Closes gh-366
This commit is contained in:
Joe Grandja
2021-07-22 04:56:27 -04:00
parent 79fd004346
commit 0d7727a7d4
42 changed files with 674 additions and 645 deletions

View File

@@ -130,7 +130,7 @@ public final class OAuth2AuthorizationEndpointConfigurer extends AbstractOAuth2C
*
* <ul>
* <li>It must be an HTTP POST</li>
* <li>It must be submitted to {@link ProviderSettings#authorizationEndpoint()}</li>
* <li>It must be submitted to {@link ProviderSettings#getAuthorizationEndpoint()} ()}</li>
* <li>It must include the received {@code client_id} as an HTTP parameter</li>
* <li>It must include the received {@code state} as an HTTP parameter</li>
* <li>It must include the list of {@code scope}s the {@code Resource Owner}
@@ -150,10 +150,10 @@ public final class OAuth2AuthorizationEndpointConfigurer extends AbstractOAuth2C
ProviderSettings providerSettings = OAuth2ConfigurerUtils.getProviderSettings(builder);
this.requestMatcher = new OrRequestMatcher(
new AntPathRequestMatcher(
providerSettings.authorizationEndpoint(),
providerSettings.getAuthorizationEndpoint(),
HttpMethod.GET.name()),
new AntPathRequestMatcher(
providerSettings.authorizationEndpoint(),
providerSettings.getAuthorizationEndpoint(),
HttpMethod.POST.name()));
List<AuthenticationProvider> authenticationProviders =
@@ -172,7 +172,7 @@ public final class OAuth2AuthorizationEndpointConfigurer extends AbstractOAuth2C
OAuth2AuthorizationEndpointFilter authorizationEndpointFilter =
new OAuth2AuthorizationEndpointFilter(
authenticationManager,
providerSettings.authorizationEndpoint());
providerSettings.getAuthorizationEndpoint());
if (this.authorizationRequestConverter != null) {
authorizationEndpointFilter.setAuthenticationConverter(this.authorizationRequestConverter);
}

View File

@@ -227,7 +227,7 @@ public final class OAuth2AuthorizationServerConfigurer<B extends HttpSecurityBui
this.configurers.values().forEach(configurer -> configurer.configure(builder));
ProviderSettings providerSettings = OAuth2ConfigurerUtils.getProviderSettings(builder);
if (providerSettings.issuer() != null) {
if (providerSettings.getIssuer() != null) {
OidcProviderConfigurationEndpointFilter oidcProviderConfigurationEndpointFilter =
new OidcProviderConfigurationEndpointFilter(providerSettings);
builder.addFilterBefore(postProcess(oidcProviderConfigurationEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
@@ -240,7 +240,7 @@ public final class OAuth2AuthorizationServerConfigurer<B extends HttpSecurityBui
JWKSource<SecurityContext> jwkSource = OAuth2ConfigurerUtils.getJwkSource(builder);
NimbusJwkSetEndpointFilter jwkSetEndpointFilter = new NimbusJwkSetEndpointFilter(
jwkSource,
providerSettings.jwkSetEndpoint());
providerSettings.getJwkSetEndpoint());
builder.addFilterBefore(postProcess(jwkSetEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
AuthenticationManager authenticationManager = builder.getSharedObject(AuthenticationManager.class);
@@ -257,20 +257,20 @@ public final class OAuth2AuthorizationServerConfigurer<B extends HttpSecurityBui
OAuth2TokenIntrospectionEndpointFilter tokenIntrospectionEndpointFilter =
new OAuth2TokenIntrospectionEndpointFilter(
authenticationManager,
providerSettings.tokenIntrospectionEndpoint());
providerSettings.getTokenIntrospectionEndpoint());
builder.addFilterAfter(postProcess(tokenIntrospectionEndpointFilter), FilterSecurityInterceptor.class);
OAuth2TokenRevocationEndpointFilter tokenRevocationEndpointFilter =
new OAuth2TokenRevocationEndpointFilter(
authenticationManager,
providerSettings.tokenRevocationEndpoint());
providerSettings.getTokenRevocationEndpoint());
builder.addFilterAfter(postProcess(tokenRevocationEndpointFilter), OAuth2TokenIntrospectionEndpointFilter.class);
// TODO Make OpenID Client Registration an "opt-in" feature
OidcClientRegistrationEndpointFilter oidcClientRegistrationEndpointFilter =
new OidcClientRegistrationEndpointFilter(
authenticationManager,
providerSettings.oidcClientRegistrationEndpoint());
providerSettings.getOidcClientRegistrationEndpoint());
builder.addFilterAfter(postProcess(oidcClientRegistrationEndpointFilter), OAuth2TokenRevocationEndpointFilter.class);
}
@@ -292,23 +292,23 @@ public final class OAuth2AuthorizationServerConfigurer<B extends HttpSecurityBui
private void initEndpointMatchers(ProviderSettings providerSettings) {
this.tokenIntrospectionEndpointMatcher = new AntPathRequestMatcher(
providerSettings.tokenIntrospectionEndpoint(), HttpMethod.POST.name());
providerSettings.getTokenIntrospectionEndpoint(), HttpMethod.POST.name());
this.tokenRevocationEndpointMatcher = new AntPathRequestMatcher(
providerSettings.tokenRevocationEndpoint(), HttpMethod.POST.name());
providerSettings.getTokenRevocationEndpoint(), HttpMethod.POST.name());
this.jwkSetEndpointMatcher = new AntPathRequestMatcher(
providerSettings.jwkSetEndpoint(), HttpMethod.GET.name());
providerSettings.getJwkSetEndpoint(), HttpMethod.GET.name());
this.oidcProviderConfigurationEndpointMatcher = new AntPathRequestMatcher(
"/.well-known/openid-configuration", HttpMethod.GET.name());
this.authorizationServerMetadataEndpointMatcher = new AntPathRequestMatcher(
"/.well-known/oauth-authorization-server", HttpMethod.GET.name());
this.oidcClientRegistrationEndpointMatcher = new AntPathRequestMatcher(
providerSettings.oidcClientRegistrationEndpoint(), HttpMethod.POST.name());
providerSettings.getOidcClientRegistrationEndpoint(), HttpMethod.POST.name());
}
private static void validateProviderSettings(ProviderSettings providerSettings) {
if (providerSettings.issuer() != null) {
if (providerSettings.getIssuer() != null) {
try {
new URI(providerSettings.issuer()).toURL();
new URI(providerSettings.getIssuer()).toURL();
} catch (Exception ex) {
throw new IllegalArgumentException("issuer must be a valid URL", ex);
}

View File

@@ -124,7 +124,7 @@ final class OAuth2ConfigurerUtils {
if (providerSettings == null) {
providerSettings = getOptionalBean(builder, ProviderSettings.class);
if (providerSettings == null) {
providerSettings = new ProviderSettings();
providerSettings = ProviderSettings.builder().build();
}
builder.setSharedObject(ProviderSettings.class, providerSettings);
}

View File

@@ -119,7 +119,7 @@ public final class OAuth2TokenEndpointConfigurer extends AbstractOAuth2Configure
<B extends HttpSecurityBuilder<B>> void init(B builder) {
ProviderSettings providerSettings = OAuth2ConfigurerUtils.getProviderSettings(builder);
this.requestMatcher = new AntPathRequestMatcher(
providerSettings.tokenEndpoint(), HttpMethod.POST.name());
providerSettings.getTokenEndpoint(), HttpMethod.POST.name());
List<AuthenticationProvider> authenticationProviders =
!this.authenticationProviders.isEmpty() ?
@@ -137,7 +137,7 @@ public final class OAuth2TokenEndpointConfigurer extends AbstractOAuth2Configure
OAuth2TokenEndpointFilter tokenEndpointFilter =
new OAuth2TokenEndpointFilter(
authenticationManager,
providerSettings.tokenEndpoint());
providerSettings.getTokenEndpoint());
if (this.accessTokenRequestConverter != null) {
tokenEndpointFilter.setAuthenticationConverter(this.accessTokenRequestConverter);
}

View File

@@ -50,7 +50,7 @@ final class JwtUtils {
String issuer, String subject, Set<String> authorizedScopes) {
Instant issuedAt = Instant.now();
Instant expiresAt = issuedAt.plus(registeredClient.getTokenSettings().accessTokenTimeToLive());
Instant expiresAt = issuedAt.plus(registeredClient.getTokenSettings().getAccessTokenTimeToLive());
// @formatter:off
JwtClaimsSet.Builder claimsBuilder = JwtClaimsSet.builder();

View File

@@ -140,7 +140,7 @@ public final class OAuth2AuthorizationCodeAuthenticationProvider implements Auth
throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_GRANT));
}
String issuer = this.providerSettings != null ? this.providerSettings.issuer() : null;
String issuer = this.providerSettings != null ? this.providerSettings.getIssuer() : null;
Set<String> authorizedScopes = authorization.getAttribute(
OAuth2Authorization.AUTHORIZED_SCOPE_ATTRIBUTE_NAME);
@@ -174,7 +174,7 @@ public final class OAuth2AuthorizationCodeAuthenticationProvider implements Auth
OAuth2RefreshToken refreshToken = null;
if (registeredClient.getAuthorizationGrantTypes().contains(AuthorizationGrantType.REFRESH_TOKEN)) {
refreshToken = OAuth2RefreshTokenAuthenticationProvider.generateRefreshToken(
registeredClient.getTokenSettings().refreshTokenTimeToLive());
registeredClient.getTokenSettings().getRefreshTokenTimeToLive());
}
Jwt jwtIdToken = null;

View File

@@ -151,7 +151,7 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationProvider implemen
authorizationCodeRequestAuthentication, registeredClient, null);
}
}
} else if (registeredClient.getClientSettings().requireProofKey()) {
} else if (registeredClient.getClientSettings().isRequireProofKey()) {
throwError(OAuth2ErrorCodes.INVALID_REQUEST, PkceParameterNames.CODE_CHALLENGE, PKCE_ERROR_URI,
authorizationCodeRequestAuthentication, registeredClient, null);
}
@@ -341,7 +341,7 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationProvider implemen
private static boolean requireAuthorizationConsent(RegisteredClient registeredClient,
OAuth2AuthorizationRequest authorizationRequest, OAuth2AuthorizationConsent authorizationConsent) {
if (!registeredClient.getClientSettings().requireAuthorizationConsent()) {
if (!registeredClient.getClientSettings().isRequireAuthorizationConsent()) {
return false;
}
// 'openid' scope does not require consent

View File

@@ -150,7 +150,7 @@ public final class OAuth2ClientAuthenticationProvider implements AuthenticationP
String codeChallenge = (String) authorizationRequest.getAdditionalParameters()
.get(PkceParameterNames.CODE_CHALLENGE);
if (!StringUtils.hasText(codeChallenge) &&
registeredClient.getClientSettings().requireProofKey()) {
registeredClient.getClientSettings().isRequireProofKey()) {
throwInvalidClient();
}

View File

@@ -113,7 +113,7 @@ public final class OAuth2ClientCredentialsAuthenticationProvider implements Auth
authorizedScopes = new LinkedHashSet<>(clientCredentialsAuthentication.getScopes());
}
String issuer = this.providerSettings != null ? this.providerSettings.issuer() : null;
String issuer = this.providerSettings != null ? this.providerSettings.getIssuer() : null;
JoseHeader.Builder headersBuilder = JwtUtils.headers();
JwtClaimsSet.Builder claimsBuilder = JwtUtils.accessTokenClaims(

View File

@@ -147,7 +147,7 @@ public final class OAuth2RefreshTokenAuthenticationProvider implements Authentic
scopes = authorizedScopes;
}
String issuer = this.providerSettings != null ? this.providerSettings.issuer() : null;
String issuer = this.providerSettings != null ? this.providerSettings.getIssuer() : null;
JoseHeader.Builder headersBuilder = JwtUtils.headers();
JwtClaimsSet.Builder claimsBuilder = JwtUtils.accessTokenClaims(
@@ -178,8 +178,8 @@ public final class OAuth2RefreshTokenAuthenticationProvider implements Authentic
TokenSettings tokenSettings = registeredClient.getTokenSettings();
OAuth2RefreshToken currentRefreshToken = refreshToken.getToken();
if (!tokenSettings.reuseRefreshTokens()) {
currentRefreshToken = generateRefreshToken(tokenSettings.refreshTokenTimeToLive());
if (!tokenSettings.isReuseRefreshTokens()) {
currentRefreshToken = generateRefreshToken(tokenSettings.getRefreshTokenTimeToLive());
}
Jwt jwtIdToken = null;

View File

@@ -39,6 +39,8 @@ import org.springframework.jdbc.core.SqlParameterValue;
import org.springframework.security.jackson2.SecurityJackson2Modules;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.server.authorization.config.ClientSettings;
import org.springframework.security.oauth2.server.authorization.config.TokenSettings;
import org.springframework.security.oauth2.server.authorization.jackson2.OAuth2AuthorizationServerJackson2Module;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -211,12 +213,10 @@ public class JdbcRegisteredClientRepository implements RegisteredClientRepositor
// @formatter:on
Map<String, Object> clientSettingsMap = parseMap(rs.getString("client_settings"));
builder.clientSettings(clientSettings ->
clientSettings.settings().putAll(clientSettingsMap));
builder.clientSettings(ClientSettings.withSettings(clientSettingsMap).build());
Map<String, Object> tokenSettingsMap = parseMap(rs.getString("token_settings"));
builder.tokenSettings(tokenSettings ->
tokenSettings.settings().putAll(tokenSettingsMap));
builder.tokenSettings(TokenSettings.withSettings(tokenSettingsMap).build());
return builder.build();
}
@@ -303,8 +303,8 @@ public class JdbcRegisteredClientRepository implements RegisteredClientRepositor
new SqlParameterValue(Types.VARCHAR, StringUtils.collectionToCommaDelimitedString(authorizationGrantTypes)),
new SqlParameterValue(Types.VARCHAR, StringUtils.collectionToCommaDelimitedString(registeredClient.getRedirectUris())),
new SqlParameterValue(Types.VARCHAR, StringUtils.collectionToCommaDelimitedString(registeredClient.getScopes())),
new SqlParameterValue(Types.VARCHAR, writeMap(registeredClient.getClientSettings().settings())),
new SqlParameterValue(Types.VARCHAR, writeMap(registeredClient.getTokenSettings().settings())));
new SqlParameterValue(Types.VARCHAR, writeMap(registeredClient.getClientSettings().getSettings())),
new SqlParameterValue(Types.VARCHAR, writeMap(registeredClient.getTokenSettings().getSettings())));
}
public final void setObjectMapper(ObjectMapper objectMapper) {

View File

@@ -190,15 +190,15 @@ public class RegisteredClient implements Serializable {
Objects.equals(this.authorizationGrantTypes, that.authorizationGrantTypes) &&
Objects.equals(this.redirectUris, that.redirectUris) &&
Objects.equals(this.scopes, that.scopes) &&
Objects.equals(this.clientSettings.settings(), that.getClientSettings().settings()) &&
Objects.equals(this.tokenSettings.settings(), that.tokenSettings.settings());
Objects.equals(this.clientSettings, that.clientSettings) &&
Objects.equals(this.tokenSettings, that.tokenSettings);
}
@Override
public int hashCode() {
return Objects.hash(this.id, this.clientId, this.clientIdIssuedAt, this.clientSecret, this.clientSecretExpiresAt,
this.clientName, this.clientAuthenticationMethods, this.authorizationGrantTypes, this.redirectUris,
this.scopes, this.clientSettings.settings(), this.tokenSettings.settings());
this.scopes, this.clientSettings, this.tokenSettings);
}
@Override
@@ -211,8 +211,8 @@ public class RegisteredClient implements Serializable {
", authorizationGrantTypes=" + this.authorizationGrantTypes +
", redirectUris=" + this.redirectUris +
", scopes=" + this.scopes +
", clientSettings=" + this.clientSettings.settings() +
", tokenSettings=" + this.tokenSettings.settings() +
", clientSettings=" + this.clientSettings +
", tokenSettings=" + this.tokenSettings +
'}';
}
@@ -253,8 +253,8 @@ public class RegisteredClient implements Serializable {
private Set<AuthorizationGrantType> authorizationGrantTypes = new HashSet<>();
private Set<String> redirectUris = new HashSet<>();
private Set<String> scopes = new HashSet<>();
private ClientSettings clientSettings = new ClientSettings();
private TokenSettings tokenSettings = new TokenSettings();
private ClientSettings clientSettings;
private TokenSettings tokenSettings;
protected Builder(String id) {
this.id = id;
@@ -279,8 +279,8 @@ public class RegisteredClient implements Serializable {
if (!CollectionUtils.isEmpty(registeredClient.scopes)) {
this.scopes.addAll(registeredClient.scopes);
}
this.clientSettings = new ClientSettings(registeredClient.clientSettings.settings());
this.tokenSettings = new TokenSettings(registeredClient.tokenSettings.settings());
this.clientSettings = ClientSettings.withSettings(registeredClient.getClientSettings().getSettings()).build();
this.tokenSettings = TokenSettings.withSettings(registeredClient.getTokenSettings().getSettings()).build();
}
/**
@@ -444,26 +444,24 @@ public class RegisteredClient implements Serializable {
}
/**
* A {@link Consumer} of the client configuration settings,
* allowing the ability to add, replace, or remove.
* Sets the {@link ClientSettings client configuration settings}.
*
* @param clientSettingsConsumer a {@link Consumer} of the client configuration settings
* @param clientSettings the client configuration settings
* @return the {@link Builder}
*/
public Builder clientSettings(Consumer<ClientSettings> clientSettingsConsumer) {
clientSettingsConsumer.accept(this.clientSettings);
public Builder clientSettings(ClientSettings clientSettings) {
this.clientSettings = clientSettings;
return this;
}
/**
* A {@link Consumer} of the token configuration settings,
* allowing the ability to add, replace, or remove.
* Sets the {@link TokenSettings token configuration settings}.
*
* @param tokenSettingsConsumer a {@link Consumer} of the token configuration settings
* @param tokenSettings the token configuration settings
* @return the {@link Builder}
*/
public Builder tokenSettings(Consumer<TokenSettings> tokenSettingsConsumer) {
tokenSettingsConsumer.accept(this.tokenSettings);
public Builder tokenSettings(TokenSettings tokenSettings) {
this.tokenSettings = tokenSettings;
return this;
}
@@ -506,8 +504,10 @@ public class RegisteredClient implements Serializable {
new HashSet<>(this.redirectUris));
registeredClient.scopes = Collections.unmodifiableSet(
new HashSet<>(this.scopes));
registeredClient.clientSettings = new ClientSettings(this.clientSettings.settings());
registeredClient.tokenSettings = new TokenSettings(this.tokenSettings.settings());
registeredClient.clientSettings = this.clientSettings != null ?
this.clientSettings : ClientSettings.builder().build();
registeredClient.tokenSettings = this.tokenSettings != null ?
this.tokenSettings : TokenSettings.builder().build();
return registeredClient;
}

View File

@@ -0,0 +1,137 @@
/*
* Copyright 2020-2021 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.server.authorization.config;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import org.springframework.security.oauth2.core.Version;
import org.springframework.util.Assert;
/**
* Base implementation for configuration settings.
*
* @author Joe Grandja
* @since 0.0.2
*/
public abstract class AbstractSettings implements Serializable {
private static final long serialVersionUID = Version.SERIAL_VERSION_UID;
private final Map<String, Object> settings;
protected AbstractSettings(Map<String, Object> settings) {
Assert.notEmpty(settings, "settings cannot be empty");
this.settings = Collections.unmodifiableMap(new HashMap<>(settings));
}
/**
* Returns a configuration setting.
*
* @param name the name of the setting
* @param <T> the type of the setting
* @return the value of the setting, or {@code null} if not available
*/
@SuppressWarnings("unchecked")
public <T> T getSetting(String name) {
Assert.hasText(name, "name cannot be empty");
return (T) getSettings().get(name);
}
/**
* Returns a {@code Map} of the configuration settings.
*
* @return a {@code Map} of the configuration settings
*/
public Map<String, Object> getSettings() {
return this.settings;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
AbstractSettings that = (AbstractSettings) obj;
return this.settings.equals(that.settings);
}
@Override
public int hashCode() {
return Objects.hash(this.settings);
}
@Override
public String toString() {
return "AbstractSettings {" +
"settings=" + this.settings +
'}';
}
/**
* A builder for subclasses of {@link AbstractSettings}.
*/
protected static abstract class AbstractBuilder<T extends AbstractSettings, B extends AbstractBuilder<T, B>> {
private final Map<String, Object> settings = new HashMap<>();
protected AbstractBuilder() {
}
/**
* Sets a configuration setting.
*
* @param name the name of the setting
* @param value the value of the setting
* @return the {@link AbstractBuilder} for further configuration
*/
public B setting(String name, Object value) {
Assert.hasText(name, "name cannot be empty");
Assert.notNull(value, "value cannot be null");
getSettings().put(name, value);
return getThis();
}
/**
* A {@code Consumer} of the configuration settings {@code Map}
* allowing the ability to add, replace, or remove.
*
* @param settingsConsumer a {@link Consumer} of the configuration settings {@code Map}
* @return the {@link AbstractBuilder} for further configuration
*/
public B settings(Consumer<Map<String, Object>> settingsConsumer) {
settingsConsumer.accept(getSettings());
return getThis();
}
public abstract T build();
protected final Map<String, Object> getSettings() {
return this.settings;
}
@SuppressWarnings("unchecked")
protected final B getThis() {
return (B) this;
}
}
}

View File

@@ -15,34 +15,23 @@
*/
package org.springframework.security.oauth2.server.authorization.config;
import java.util.HashMap;
import java.util.Map;
import org.springframework.util.Assert;
/**
* A facility for client configuration settings.
*
* @author Joe Grandja
* @since 0.0.2
* @see Settings
* @see AbstractSettings
*/
public class ClientSettings extends Settings {
public final class ClientSettings extends AbstractSettings {
private static final String CLIENT_SETTING_BASE = "setting.client.";
public static final String REQUIRE_PROOF_KEY = CLIENT_SETTING_BASE.concat("require-proof-key");
public static final String REQUIRE_AUTHORIZATION_CONSENT = CLIENT_SETTING_BASE.concat("require-authorization-consent");
/**
* Constructs a {@code ClientSettings}.
*/
public ClientSettings() {
this(defaultSettings());
}
/**
* Constructs a {@code ClientSettings} using the provided parameters.
*
* @param settings the initial settings
*/
public ClientSettings(Map<String, Object> settings) {
private ClientSettings(Map<String, Object> settings) {
super(settings);
}
@@ -52,20 +41,8 @@ public class ClientSettings extends Settings {
*
* @return {@code true} if the client is required to provide a proof key challenge and verifier, {@code false} otherwise
*/
public boolean requireProofKey() {
return setting(REQUIRE_PROOF_KEY);
}
/**
* Set to {@code true} if the client is required to provide a proof key challenge and verifier
* when performing the Authorization Code Grant flow.
*
* @param requireProofKey {@code true} if the client is required to provide a proof key challenge and verifier, {@code false} otherwise
* @return the {@link ClientSettings}
*/
public ClientSettings requireProofKey(boolean requireProofKey) {
setting(REQUIRE_PROOF_KEY, requireProofKey);
return this;
public boolean isRequireProofKey() {
return getSetting(REQUIRE_PROOF_KEY);
}
/**
@@ -74,26 +51,73 @@ public class ClientSettings extends Settings {
*
* @return {@code true} if authorization consent is required when the client requests access, {@code false} otherwise
*/
public boolean requireAuthorizationConsent() {
return setting(REQUIRE_AUTHORIZATION_CONSENT);
public boolean isRequireAuthorizationConsent() {
return getSetting(REQUIRE_AUTHORIZATION_CONSENT);
}
/**
* Set to {@code true} if authorization consent is required when the client requests access.
* This applies to all interactive flows (e.g. {@code authorization_code} and {@code device_code}).
* Constructs a new {@link Builder} with the default settings.
*
* @param requireAuthorizationConsent {@code true} if authorization consent is required when the client requests access, {@code false} otherwise
* @return the {@link ClientSettings}
* @return the {@link Builder}
*/
public ClientSettings requireAuthorizationConsent(boolean requireAuthorizationConsent) {
setting(REQUIRE_AUTHORIZATION_CONSENT, requireAuthorizationConsent);
return this;
public static Builder builder() {
return new Builder()
.requireProofKey(false)
.requireAuthorizationConsent(false);
}
protected static Map<String, Object> defaultSettings() {
Map<String, Object> settings = new HashMap<>();
settings.put(REQUIRE_PROOF_KEY, false);
settings.put(REQUIRE_AUTHORIZATION_CONSENT, false);
return settings;
/**
* Constructs a new {@link Builder} with the provided settings.
*
* @param settings the settings to initialize the builder
* @return the {@link Builder}
*/
public static Builder withSettings(Map<String, Object> settings) {
Assert.notEmpty(settings, "settings cannot be empty");
return new Builder()
.settings(s -> s.putAll(settings));
}
/**
* A builder for {@link ClientSettings}.
*/
public static class Builder extends AbstractBuilder<ClientSettings, Builder> {
private Builder() {
}
/**
* Set to {@code true} if the client is required to provide a proof key challenge and verifier
* when performing the Authorization Code Grant flow.
*
* @param requireProofKey {@code true} if the client is required to provide a proof key challenge and verifier, {@code false} otherwise
* @return the {@link Builder} for further configuration
*/
public Builder requireProofKey(boolean requireProofKey) {
return setting(REQUIRE_PROOF_KEY, requireProofKey);
}
/**
* Set to {@code true} if authorization consent is required when the client requests access.
* This applies to all interactive flows (e.g. {@code authorization_code} and {@code device_code}).
*
* @param requireAuthorizationConsent {@code true} if authorization consent is required when the client requests access, {@code false} otherwise
* @return the {@link Builder} for further configuration
*/
public Builder requireAuthorizationConsent(boolean requireAuthorizationConsent) {
return setting(REQUIRE_AUTHORIZATION_CONSENT, requireAuthorizationConsent);
}
/**
* Builds the {@link ClientSettings}.
*
* @return the {@link ClientSettings}
*/
@Override
public ClientSettings build() {
return new ClientSettings(getSettings());
}
}
}

View File

@@ -15,17 +15,19 @@
*/
package org.springframework.security.oauth2.server.authorization.config;
import java.util.HashMap;
import java.util.Map;
import org.springframework.util.Assert;
/**
* A facility for provider configuration settings.
*
* @author Daniel Garnier-Moiroux
* @author Joe Grandja
* @since 0.1.0
* @see Settings
* @see AbstractSettings
*/
public class ProviderSettings extends Settings {
public final class ProviderSettings extends AbstractSettings {
private static final String PROVIDER_SETTING_BASE = "setting.provider.";
public static final String ISSUER = PROVIDER_SETTING_BASE.concat("issuer");
public static final String AUTHORIZATION_ENDPOINT = PROVIDER_SETTING_BASE.concat("authorization-endpoint");
@@ -35,19 +37,7 @@ public class ProviderSettings extends Settings {
public static final String TOKEN_INTROSPECTION_ENDPOINT = PROVIDER_SETTING_BASE.concat("token-introspection-endpoint");
public static final String OIDC_CLIENT_REGISTRATION_ENDPOINT = PROVIDER_SETTING_BASE.concat("oidc-client-registration-endpoint");
/**
* Constructs a {@code ProviderSettings}.
*/
public ProviderSettings() {
this(defaultSettings());
}
/**
* Constructs a {@code ProviderSettings} using the provided parameters.
*
* @param settings the initial settings
*/
public ProviderSettings(Map<String, Object> settings) {
private ProviderSettings(Map<String, Object> settings) {
super(settings);
}
@@ -56,18 +46,8 @@ public class ProviderSettings extends Settings {
*
* @return the URL of the Provider's Issuer Identifier
*/
public String issuer() {
return setting(ISSUER);
}
/**
* Sets the URL the Provider uses as its Issuer Identifier.
*
* @param issuer the URL the Provider uses as its Issuer Identifier.
* @return the {@link ProviderSettings} for further configuration
*/
public ProviderSettings issuer(String issuer) {
return setting(ISSUER, issuer);
public String getIssuer() {
return getSetting(ISSUER);
}
/**
@@ -75,18 +55,8 @@ public class ProviderSettings extends Settings {
*
* @return the Authorization endpoint
*/
public String authorizationEndpoint() {
return setting(AUTHORIZATION_ENDPOINT);
}
/**
* Sets the Provider's OAuth 2.0 Authorization endpoint.
*
* @param authorizationEndpoint the Authorization endpoint
* @return the {@link ProviderSettings} for further configuration
*/
public ProviderSettings authorizationEndpoint(String authorizationEndpoint) {
return setting(AUTHORIZATION_ENDPOINT, authorizationEndpoint);
public String getAuthorizationEndpoint() {
return getSetting(AUTHORIZATION_ENDPOINT);
}
/**
@@ -94,18 +64,8 @@ public class ProviderSettings extends Settings {
*
* @return the Token endpoint
*/
public String tokenEndpoint() {
return setting(TOKEN_ENDPOINT);
}
/**
* Sets the Provider's OAuth 2.0 Token endpoint.
*
* @param tokenEndpoint the Token endpoint
* @return the {@link ProviderSettings} for further configuration
*/
public ProviderSettings tokenEndpoint(String tokenEndpoint) {
return setting(TOKEN_ENDPOINT, tokenEndpoint);
public String getTokenEndpoint() {
return getSetting(TOKEN_ENDPOINT);
}
/**
@@ -113,18 +73,8 @@ public class ProviderSettings extends Settings {
*
* @return the JWK Set endpoint
*/
public String jwkSetEndpoint() {
return setting(JWK_SET_ENDPOINT);
}
/**
* Sets the Provider's JWK Set endpoint.
*
* @param jwkSetEndpoint the JWK Set endpoint
* @return the {@link ProviderSettings} for further configuration
*/
public ProviderSettings jwkSetEndpoint(String jwkSetEndpoint) {
return setting(JWK_SET_ENDPOINT, jwkSetEndpoint);
public String getJwkSetEndpoint() {
return getSetting(JWK_SET_ENDPOINT);
}
/**
@@ -132,18 +82,8 @@ public class ProviderSettings extends Settings {
*
* @return the Token Revocation endpoint
*/
public String tokenRevocationEndpoint() {
return setting(TOKEN_REVOCATION_ENDPOINT);
}
/**
* Sets the Provider's OAuth 2.0 Token Revocation endpoint.
*
* @param tokenRevocationEndpoint the Token Revocation endpoint
* @return the {@link ProviderSettings} for further configuration
*/
public ProviderSettings tokenRevocationEndpoint(String tokenRevocationEndpoint) {
return setting(TOKEN_REVOCATION_ENDPOINT, tokenRevocationEndpoint);
public String getTokenRevocationEndpoint() {
return getSetting(TOKEN_REVOCATION_ENDPOINT);
}
/**
@@ -151,18 +91,8 @@ public class ProviderSettings extends Settings {
*
* @return the Token Introspection endpoint
*/
public String tokenIntrospectionEndpoint() {
return setting(TOKEN_INTROSPECTION_ENDPOINT);
}
/**
* Sets the Provider's OAuth 2.0 Token Introspection endpoint.
*
* @param tokenIntrospectionEndpoint the Token Introspection endpoint
* @return the {@link ProviderSettings} for further configuration
*/
public ProviderSettings tokenIntrospectionEndpoint(String tokenIntrospectionEndpoint) {
return setting(TOKEN_INTROSPECTION_ENDPOINT, tokenIntrospectionEndpoint);
public String getTokenIntrospectionEndpoint() {
return getSetting(TOKEN_INTROSPECTION_ENDPOINT);
}
/**
@@ -170,28 +100,125 @@ public class ProviderSettings extends Settings {
*
* @return the OpenID Connect 1.0 Client Registration endpoint
*/
public String oidcClientRegistrationEndpoint() {
return setting(OIDC_CLIENT_REGISTRATION_ENDPOINT);
public String getOidcClientRegistrationEndpoint() {
return getSetting(OIDC_CLIENT_REGISTRATION_ENDPOINT);
}
/**
* Sets the Provider's OpenID Connect 1.0 Client Registration endpoint.
* Constructs a new {@link Builder} with the default settings.
*
* @param oidcClientRegistrationEndpoint the OpenID Connect 1.0 Client Registration endpoint
* @return the {@link ProviderSettings} for further configuration
* @return the {@link Builder}
*/
public ProviderSettings oidcClientRegistrationEndpoint(String oidcClientRegistrationEndpoint) {
return setting(OIDC_CLIENT_REGISTRATION_ENDPOINT, oidcClientRegistrationEndpoint);
public static Builder builder() {
return new Builder()
.authorizationEndpoint("/oauth2/authorize")
.tokenEndpoint("/oauth2/token")
.jwkSetEndpoint("/oauth2/jwks")
.tokenRevocationEndpoint("/oauth2/revoke")
.tokenIntrospectionEndpoint("/oauth2/introspect")
.oidcClientRegistrationEndpoint("/connect/register");
}
protected static Map<String, Object> defaultSettings() {
Map<String, Object> settings = new HashMap<>();
settings.put(AUTHORIZATION_ENDPOINT, "/oauth2/authorize");
settings.put(TOKEN_ENDPOINT, "/oauth2/token");
settings.put(JWK_SET_ENDPOINT, "/oauth2/jwks");
settings.put(TOKEN_REVOCATION_ENDPOINT, "/oauth2/revoke");
settings.put(TOKEN_INTROSPECTION_ENDPOINT, "/oauth2/introspect");
settings.put(OIDC_CLIENT_REGISTRATION_ENDPOINT, "/connect/register");
return settings;
/**
* Constructs a new {@link Builder} with the provided settings.
*
* @param settings the settings to initialize the builder
* @return the {@link Builder}
*/
public static Builder withSettings(Map<String, Object> settings) {
Assert.notEmpty(settings, "settings cannot be empty");
return new Builder()
.settings(s -> s.putAll(settings));
}
/**
* A builder for {@link ProviderSettings}.
*/
public static class Builder extends AbstractBuilder<ProviderSettings, Builder> {
private Builder() {
}
/**
* Sets the URL the Provider uses as its Issuer Identifier.
*
* @param issuer the URL the Provider uses as its Issuer Identifier.
* @return the {@link Builder} for further configuration
*/
public Builder issuer(String issuer) {
return setting(ISSUER, issuer);
}
/**
* Sets the Provider's OAuth 2.0 Authorization endpoint.
*
* @param authorizationEndpoint the Authorization endpoint
* @return the {@link Builder} for further configuration
*/
public Builder authorizationEndpoint(String authorizationEndpoint) {
return setting(AUTHORIZATION_ENDPOINT, authorizationEndpoint);
}
/**
* Sets the Provider's OAuth 2.0 Token endpoint.
*
* @param tokenEndpoint the Token endpoint
* @return the {@link Builder} for further configuration
*/
public Builder tokenEndpoint(String tokenEndpoint) {
return setting(TOKEN_ENDPOINT, tokenEndpoint);
}
/**
* Sets the Provider's JWK Set endpoint.
*
* @param jwkSetEndpoint the JWK Set endpoint
* @return the {@link Builder} for further configuration
*/
public Builder jwkSetEndpoint(String jwkSetEndpoint) {
return setting(JWK_SET_ENDPOINT, jwkSetEndpoint);
}
/**
* Sets the Provider's OAuth 2.0 Token Revocation endpoint.
*
* @param tokenRevocationEndpoint the Token Revocation endpoint
* @return the {@link Builder} for further configuration
*/
public Builder tokenRevocationEndpoint(String tokenRevocationEndpoint) {
return setting(TOKEN_REVOCATION_ENDPOINT, tokenRevocationEndpoint);
}
/**
* Sets the Provider's OAuth 2.0 Token Introspection endpoint.
*
* @param tokenIntrospectionEndpoint the Token Introspection endpoint
* @return the {@link Builder} for further configuration
*/
public Builder tokenIntrospectionEndpoint(String tokenIntrospectionEndpoint) {
return setting(TOKEN_INTROSPECTION_ENDPOINT, tokenIntrospectionEndpoint);
}
/**
* Sets the Provider's OpenID Connect 1.0 Client Registration endpoint.
*
* @param oidcClientRegistrationEndpoint the OpenID Connect 1.0 Client Registration endpoint
* @return the {@link Builder} for further configuration
*/
public Builder oidcClientRegistrationEndpoint(String oidcClientRegistrationEndpoint) {
return setting(OIDC_CLIENT_REGISTRATION_ENDPOINT, oidcClientRegistrationEndpoint);
}
/**
* Builds the {@link ProviderSettings}.
*
* @return the {@link ProviderSettings}
*/
@Override
public ProviderSettings build() {
return new ProviderSettings(getSettings());
}
}
}

View File

@@ -1,104 +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.server.authorization.config;
import org.springframework.security.oauth2.core.Version;
import org.springframework.util.Assert;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
/**
* A facility for configuration settings.
*
* @author Joe Grandja
* @since 0.0.2
*/
public class Settings implements Serializable {
private static final long serialVersionUID = Version.SERIAL_VERSION_UID;
private final Map<String, Object> settings;
/**
* Constructs a {@code Settings}.
*/
public Settings() {
this.settings = new HashMap<>();
}
/**
* Constructs a {@code Settings} using the provided parameters.
*
* @param settings the initial settings
*/
public Settings(Map<String, Object> settings) {
Assert.notNull(settings, "settings cannot be null");
this.settings = new HashMap<>(settings);
}
/**
* Returns a configuration setting.
*
* @param name the name of the setting
* @param <T> the type of the setting
* @return the value of the setting, or {@code null} if not available
*/
@SuppressWarnings("unchecked")
public <T> T setting(String name) {
Assert.hasText(name, "name cannot be empty");
return (T) this.settings.get(name);
}
/**
* Sets a configuration setting.
*
* @param name the name of the setting
* @param value the value of the setting
* @param <T> the type of the {@link Settings}
* @return the {@link Settings}
*/
@SuppressWarnings("unchecked")
public <T extends Settings> T setting(String name, Object value) {
Assert.hasText(name, "name cannot be empty");
Assert.notNull(value, "value cannot be null");
this.settings.put(name, value);
return (T) this;
}
/**
* Returns a {@code Map} of the configuration settings.
*
* @return a {@code Map} of the configuration settings
*/
public Map<String, Object> settings() {
return this.settings;
}
/**
* A {@code Consumer} of the configuration settings {@code Map}
* allowing the ability to add, replace, or remove.
*
* @param settingsConsumer a {@link Consumer} of the configuration settings {@code Map}
* @param <T> the type of the {@link Settings}
* @return the {@link Settings}
*/
@SuppressWarnings("unchecked")
public <T extends Settings> T settings(Consumer<Map<String, Object>> settingsConsumer) {
settingsConsumer.accept(this.settings);
return (T) this;
}
}

View File

@@ -16,7 +16,6 @@
package org.springframework.security.oauth2.server.authorization.config;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
@@ -28,28 +27,16 @@ import org.springframework.util.Assert;
*
* @author Joe Grandja
* @since 0.0.2
* @see Settings
* @see AbstractSettings
*/
public class TokenSettings extends Settings {
public final class TokenSettings extends AbstractSettings {
private static final String TOKEN_SETTING_BASE = "setting.token.";
public static final String ACCESS_TOKEN_TIME_TO_LIVE = TOKEN_SETTING_BASE.concat("access-token-time-to-live");
public static final String REUSE_REFRESH_TOKENS = TOKEN_SETTING_BASE.concat("reuse-refresh-tokens");
public static final String REFRESH_TOKEN_TIME_TO_LIVE = TOKEN_SETTING_BASE.concat("refresh-token-time-to-live");
public static final String ID_TOKEN_SIGNATURE_ALGORITHM = TOKEN_SETTING_BASE.concat("id-token-signature-algorithm");
/**
* Constructs a {@code TokenSettings}.
*/
public TokenSettings() {
this(defaultSettings());
}
/**
* Constructs a {@code TokenSettings} using the provided parameters.
*
* @param settings the initial settings
*/
public TokenSettings(Map<String, Object> settings) {
private TokenSettings(Map<String, Object> settings) {
super(settings);
}
@@ -58,41 +45,16 @@ public class TokenSettings extends Settings {
*
* @return the time-to-live for an access token
*/
public Duration accessTokenTimeToLive() {
return setting(ACCESS_TOKEN_TIME_TO_LIVE);
}
/**
* Set the time-to-live for an access token. Must be greater than {@code Duration.ZERO}.
*
* @param accessTokenTimeToLive the time-to-live for an access token
* @return the {@link TokenSettings}
*/
public TokenSettings accessTokenTimeToLive(Duration accessTokenTimeToLive) {
Assert.notNull(accessTokenTimeToLive, "accessTokenTimeToLive cannot be null");
Assert.isTrue(accessTokenTimeToLive.getSeconds() > 0, "accessTokenTimeToLive must be greater than Duration.ZERO");
setting(ACCESS_TOKEN_TIME_TO_LIVE, accessTokenTimeToLive);
return this;
public Duration getAccessTokenTimeToLive() {
return getSetting(ACCESS_TOKEN_TIME_TO_LIVE);
}
/**
* Returns {@code true} if refresh tokens are reused when returning the access token response,
* or {@code false} if a new refresh token is issued. The default is {@code true}.
*/
public boolean reuseRefreshTokens() {
return setting(REUSE_REFRESH_TOKENS);
}
/**
* Set to {@code true} if refresh tokens are reused when returning the access token response,
* or {@code false} if a new refresh token is issued.
*
* @param reuseRefreshTokens {@code true} to reuse refresh tokens, {@code false} to issue new refresh tokens
* @return the {@link TokenSettings}
*/
public TokenSettings reuseRefreshTokens(boolean reuseRefreshTokens) {
setting(REUSE_REFRESH_TOKENS, reuseRefreshTokens);
return this;
public boolean isReuseRefreshTokens() {
return getSetting(REUSE_REFRESH_TOKENS);
}
/**
@@ -100,21 +62,8 @@ public class TokenSettings extends Settings {
*
* @return the time-to-live for a refresh token
*/
public Duration refreshTokenTimeToLive() {
return setting(REFRESH_TOKEN_TIME_TO_LIVE);
}
/**
* Set the time-to-live for a refresh token. Must be greater than {@code Duration.ZERO}.
*
* @param refreshTokenTimeToLive the time-to-live for a refresh token
* @return the {@link TokenSettings}
*/
public TokenSettings refreshTokenTimeToLive(Duration refreshTokenTimeToLive) {
Assert.notNull(refreshTokenTimeToLive, "refreshTokenTimeToLive cannot be null");
Assert.isTrue(refreshTokenTimeToLive.getSeconds() > 0, "refreshTokenTimeToLive must be greater than Duration.ZERO");
setting(REFRESH_TOKEN_TIME_TO_LIVE, refreshTokenTimeToLive);
return this;
public Duration getRefreshTokenTimeToLive() {
return getSetting(REFRESH_TOKEN_TIME_TO_LIVE);
}
/**
@@ -123,29 +72,99 @@ public class TokenSettings extends Settings {
*
* @return the {@link SignatureAlgorithm JWS} algorithm for signing the {@link OidcIdToken ID Token}
*/
public SignatureAlgorithm idTokenSignatureAlgorithm() {
return setting(ID_TOKEN_SIGNATURE_ALGORITHM);
public SignatureAlgorithm getIdTokenSignatureAlgorithm() {
return getSetting(ID_TOKEN_SIGNATURE_ALGORITHM);
}
/**
* Sets the {@link SignatureAlgorithm JWS} algorithm for signing the {@link OidcIdToken ID Token}.
* Constructs a new {@link Builder} with the default settings.
*
* @param idTokenSignatureAlgorithm the {@link SignatureAlgorithm JWS} algorithm for signing the {@link OidcIdToken ID Token}
* @return the {@link TokenSettings}
* @return the {@link Builder}
*/
public TokenSettings idTokenSignatureAlgorithm(SignatureAlgorithm idTokenSignatureAlgorithm) {
Assert.notNull(idTokenSignatureAlgorithm, "idTokenSignatureAlgorithm cannot be null");
setting(ID_TOKEN_SIGNATURE_ALGORITHM, idTokenSignatureAlgorithm);
return this;
public static Builder builder() {
return new Builder()
.accessTokenTimeToLive(Duration.ofMinutes(5))
.reuseRefreshTokens(true)
.refreshTokenTimeToLive(Duration.ofMinutes(60))
.idTokenSignatureAlgorithm(SignatureAlgorithm.RS256);
}
protected static Map<String, Object> defaultSettings() {
Map<String, Object> settings = new HashMap<>();
settings.put(ACCESS_TOKEN_TIME_TO_LIVE, Duration.ofMinutes(5));
settings.put(REUSE_REFRESH_TOKENS, true);
settings.put(REFRESH_TOKEN_TIME_TO_LIVE, Duration.ofMinutes(60));
settings.put(ID_TOKEN_SIGNATURE_ALGORITHM, SignatureAlgorithm.RS256);
return settings;
/**
* Constructs a new {@link Builder} with the provided settings.
*
* @param settings the settings to initialize the builder
* @return the {@link Builder}
*/
public static Builder withSettings(Map<String, Object> settings) {
Assert.notEmpty(settings, "settings cannot be empty");
return new Builder()
.settings(s -> s.putAll(settings));
}
/**
* A builder for {@link TokenSettings}.
*/
public static class Builder extends AbstractBuilder<TokenSettings, Builder> {
private Builder() {
}
/**
* Set the time-to-live for an access token. Must be greater than {@code Duration.ZERO}.
*
* @param accessTokenTimeToLive the time-to-live for an access token
* @return the {@link Builder} for further configuration
*/
public Builder accessTokenTimeToLive(Duration accessTokenTimeToLive) {
Assert.notNull(accessTokenTimeToLive, "accessTokenTimeToLive cannot be null");
Assert.isTrue(accessTokenTimeToLive.getSeconds() > 0, "accessTokenTimeToLive must be greater than Duration.ZERO");
return setting(ACCESS_TOKEN_TIME_TO_LIVE, accessTokenTimeToLive);
}
/**
* Set to {@code true} if refresh tokens are reused when returning the access token response,
* or {@code false} if a new refresh token is issued.
*
* @param reuseRefreshTokens {@code true} to reuse refresh tokens, {@code false} to issue new refresh tokens
* @return the {@link Builder} for further configuration
*/
public Builder reuseRefreshTokens(boolean reuseRefreshTokens) {
return setting(REUSE_REFRESH_TOKENS, reuseRefreshTokens);
}
/**
* Set the time-to-live for a refresh token. Must be greater than {@code Duration.ZERO}.
*
* @param refreshTokenTimeToLive the time-to-live for a refresh token
* @return the {@link Builder} for further configuration
*/
public Builder refreshTokenTimeToLive(Duration refreshTokenTimeToLive) {
Assert.notNull(refreshTokenTimeToLive, "refreshTokenTimeToLive cannot be null");
Assert.isTrue(refreshTokenTimeToLive.getSeconds() > 0, "refreshTokenTimeToLive must be greater than Duration.ZERO");
return setting(REFRESH_TOKEN_TIME_TO_LIVE, refreshTokenTimeToLive);
}
/**
* Sets the {@link SignatureAlgorithm JWS} algorithm for signing the {@link OidcIdToken ID Token}.
*
* @param idTokenSignatureAlgorithm the {@link SignatureAlgorithm JWS} algorithm for signing the {@link OidcIdToken ID Token}
* @return the {@link Builder} for further configuration
*/
public Builder idTokenSignatureAlgorithm(SignatureAlgorithm idTokenSignatureAlgorithm) {
Assert.notNull(idTokenSignatureAlgorithm, "idTokenSignatureAlgorithm cannot be null");
return setting(ID_TOKEN_SIGNATURE_ALGORITHM, idTokenSignatureAlgorithm);
}
/**
* Builds the {@link TokenSettings}.
*
* @return the {@link TokenSettings}
*/
@Override
public TokenSettings build() {
return new TokenSettings(getSettings());
}
}
}

View File

@@ -40,6 +40,8 @@ import org.springframework.security.oauth2.server.authorization.OAuth2Authorizat
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.config.ClientSettings;
import org.springframework.security.oauth2.server.authorization.config.TokenSettings;
import org.springframework.security.oauth2.server.resource.authentication.AbstractOAuth2TokenAuthenticationToken;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
@@ -169,13 +171,13 @@ public final class OidcClientRegistrationAuthenticationProvider implements Authe
}
builder
.clientSettings(clientSettings ->
clientSettings
.requireProofKey(true)
.requireAuthorizationConsent(true))
.tokenSettings(tokenSettings ->
tokenSettings
.idTokenSignatureAlgorithm(SignatureAlgorithm.RS256));
.clientSettings(ClientSettings.builder()
.requireProofKey(true)
.requireAuthorizationConsent(true)
.build())
.tokenSettings(TokenSettings.builder()
.idTokenSignatureAlgorithm(SignatureAlgorithm.RS256)
.build());
return builder.build();
// @formatter:on
@@ -207,7 +209,7 @@ public final class OidcClientRegistrationAuthenticationProvider implements Authe
builder
.tokenEndpointAuthenticationMethod(registeredClient.getClientAuthenticationMethods().iterator().next().getValue())
.idTokenSignedResponseAlgorithm(registeredClient.getTokenSettings().idTokenSignatureAlgorithm().getName());
.idTokenSignedResponseAlgorithm(registeredClient.getTokenSettings().getIdTokenSignatureAlgorithm().getName());
return builder.build();
// @formatter:on

View File

@@ -77,12 +77,12 @@ public final class OidcProviderConfigurationEndpointFilter extends OncePerReques
}
OidcProviderConfiguration providerConfiguration = OidcProviderConfiguration.builder()
.issuer(this.providerSettings.issuer())
.authorizationEndpoint(asUrl(this.providerSettings.issuer(), this.providerSettings.authorizationEndpoint()))
.tokenEndpoint(asUrl(this.providerSettings.issuer(), this.providerSettings.tokenEndpoint()))
.issuer(this.providerSettings.getIssuer())
.authorizationEndpoint(asUrl(this.providerSettings.getIssuer(), this.providerSettings.getAuthorizationEndpoint()))
.tokenEndpoint(asUrl(this.providerSettings.getIssuer(), this.providerSettings.getTokenEndpoint()))
.tokenEndpointAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue())
.tokenEndpointAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST.getValue())
.jwkSetUrl(asUrl(this.providerSettings.issuer(), this.providerSettings.jwkSetEndpoint()))
.jwkSetUrl(asUrl(this.providerSettings.getIssuer(), this.providerSettings.getJwkSetEndpoint()))
.responseType(OAuth2AuthorizationResponseType.CODE.getValue())
.grantType(AuthorizationGrantType.AUTHORIZATION_CODE.getValue())
.grantType(AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())

View File

@@ -78,18 +78,18 @@ public final class OAuth2AuthorizationServerMetadataEndpointFilter extends OnceP
}
OAuth2AuthorizationServerMetadata authorizationServerMetadata = OAuth2AuthorizationServerMetadata.builder()
.issuer(this.providerSettings.issuer())
.authorizationEndpoint(asUrl(this.providerSettings.issuer(), this.providerSettings.authorizationEndpoint()))
.tokenEndpoint(asUrl(this.providerSettings.issuer(), this.providerSettings.tokenEndpoint()))
.issuer(this.providerSettings.getIssuer())
.authorizationEndpoint(asUrl(this.providerSettings.getIssuer(), this.providerSettings.getAuthorizationEndpoint()))
.tokenEndpoint(asUrl(this.providerSettings.getIssuer(), this.providerSettings.getTokenEndpoint()))
.tokenEndpointAuthenticationMethods(clientAuthenticationMethods())
.jwkSetUrl(asUrl(this.providerSettings.issuer(), this.providerSettings.jwkSetEndpoint()))
.jwkSetUrl(asUrl(this.providerSettings.getIssuer(), this.providerSettings.getJwkSetEndpoint()))
.responseType(OAuth2AuthorizationResponseType.CODE.getValue())
.grantType(AuthorizationGrantType.AUTHORIZATION_CODE.getValue())
.grantType(AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
.grantType(AuthorizationGrantType.REFRESH_TOKEN.getValue())
.tokenRevocationEndpoint(asUrl(this.providerSettings.issuer(), this.providerSettings.tokenRevocationEndpoint()))
.tokenRevocationEndpoint(asUrl(this.providerSettings.getIssuer(), this.providerSettings.getTokenRevocationEndpoint()))
.tokenRevocationEndpointAuthenticationMethods(clientAuthenticationMethods())
.tokenIntrospectionEndpoint(asUrl(this.providerSettings.issuer(), this.providerSettings.tokenIntrospectionEndpoint()))
.tokenIntrospectionEndpoint(asUrl(this.providerSettings.getIssuer(), this.providerSettings.getTokenIntrospectionEndpoint()))
.tokenIntrospectionEndpointAuthenticationMethods(clientAuthenticationMethods())
.codeChallengeMethod("plain")
.codeChallengeMethod("S256")

View File

@@ -76,7 +76,7 @@ public class JwkSetTests {
public static void init() {
JWKSet jwkSet = new JWKSet(TestJwks.DEFAULT_RSA_JWK);
jwkSource = (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
providerSettings = new ProviderSettings().jwkSetEndpoint("/test/jwks");
providerSettings = ProviderSettings.builder().jwkSetEndpoint("/test/jwks").build();
db = new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(EmbeddedDatabaseType.HSQL)
@@ -108,7 +108,7 @@ public class JwkSetTests {
public void requestWhenJwkSetCustomEndpointThenReturnKeys() throws Exception {
this.spring.register(AuthorizationServerConfigurationCustomEndpoints.class).autowire();
assertJwkSetRequestThenReturnKeys(providerSettings.jwkSetEndpoint());
assertJwkSetRequestThenReturnKeys(providerSettings.getJwkSetEndpoint());
}
private void assertJwkSetRequestThenReturnKeys(String jwkSetEndpointUri) throws Exception {

View File

@@ -86,6 +86,7 @@ import org.springframework.security.oauth2.server.authorization.client.JdbcRegis
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
import org.springframework.security.oauth2.server.authorization.config.ClientSettings;
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
import org.springframework.security.oauth2.server.authorization.jackson2.TestingAuthenticationTokenMixin;
import org.springframework.security.web.SecurityFilterChain;
@@ -167,9 +168,10 @@ public class OAuth2AuthorizationCodeGrantTests {
JWKSet jwkSet = new JWKSet(TestJwks.DEFAULT_RSA_JWK);
jwkSource = (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
jwtEncoder = new NimbusJwsEncoder(jwkSource);
providerSettings = new ProviderSettings()
providerSettings = ProviderSettings.builder()
.authorizationEndpoint("/test/authorize")
.tokenEndpoint("/test/token");
.tokenEndpoint("/test/token")
.build();
authorizationRequestConverter = mock(AuthenticationConverter.class);
authorizationRequestAuthenticationProvider = mock(AuthenticationProvider.class);
authorizationResponseHandler = mock(AuthenticationSuccessHandler.class);
@@ -232,7 +234,7 @@ public class OAuth2AuthorizationCodeGrantTests {
public void requestWhenAuthorizationRequestCustomEndpointThenRedirectToClient() throws Exception {
this.spring.register(AuthorizationServerConfigurationCustomEndpoints.class).autowire();
assertAuthorizationRequestRedirectsToClient(providerSettings.authorizationEndpoint());
assertAuthorizationRequestRedirectsToClient(providerSettings.getAuthorizationEndpoint());
}
private void assertAuthorizationRequestRedirectsToClient(String authorizationEndpointUri) throws Exception {
@@ -287,7 +289,7 @@ public class OAuth2AuthorizationCodeGrantTests {
this.authorizationService.save(authorization);
assertTokenRequestReturnsAccessTokenResponse(
registeredClient, authorization, providerSettings.tokenEndpoint());
registeredClient, authorization, providerSettings.getTokenEndpoint());
}
private OAuth2AccessTokenResponse assertTokenRequestReturnsAccessTokenResponse(RegisteredClient registeredClient,
@@ -389,7 +391,7 @@ public class OAuth2AuthorizationCodeGrantTests {
scopes.add("message.read");
scopes.add("message.write");
})
.clientSettings(settings -> settings.requireAuthorizationConsent(true))
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
.build();
this.registeredClientRepository.save(registeredClient);
@@ -416,7 +418,7 @@ public class OAuth2AuthorizationCodeGrantTests {
scopes.add("message.read");
scopes.add("message.write");
})
.clientSettings(settings -> settings.requireAuthorizationConsent(true))
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
.build();
this.registeredClientRepository.save(registeredClient);
@@ -464,7 +466,7 @@ public class OAuth2AuthorizationCodeGrantTests {
scopes.add("message.read");
scopes.add("message.write");
})
.clientSettings(settings -> settings.requireAuthorizationConsent(true))
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
.build();
this.registeredClientRepository.save(registeredClient);

View File

@@ -125,7 +125,7 @@ public class OAuth2AuthorizationServerMetadataTests {
@Bean
ProviderSettings providerSettings() {
return new ProviderSettings().issuer(issuerUrl);
return ProviderSettings.builder().issuer(issuerUrl).build();
}
}

View File

@@ -109,7 +109,7 @@ public class OAuth2TokenIntrospectionTests {
public static void init() {
JWKSet jwkSet = new JWKSet(TestJwks.DEFAULT_RSA_JWK);
jwkSource = (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
providerSettings = new ProviderSettings().tokenIntrospectionEndpoint("/test/introspect");
providerSettings = ProviderSettings.builder().tokenIntrospectionEndpoint("/test/introspect").build();
db = new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(EmbeddedDatabaseType.HSQL)
@@ -152,7 +152,7 @@ public class OAuth2TokenIntrospectionTests {
this.authorizationService.save(authorization);
// @formatter:off
MvcResult mvcResult = this.mvc.perform(post(providerSettings.tokenIntrospectionEndpoint())
MvcResult mvcResult = this.mvc.perform(post(providerSettings.getTokenIntrospectionEndpoint())
.params(getTokenIntrospectionRequestParameters(accessToken, OAuth2TokenType.ACCESS_TOKEN))
.with(httpBasic(introspectRegisteredClient.getClientId(), introspectRegisteredClient.getClientSecret())))
.andExpect(status().isOk())
@@ -192,7 +192,7 @@ public class OAuth2TokenIntrospectionTests {
this.authorizationService.save(authorization);
// @formatter:off
MvcResult mvcResult = this.mvc.perform(post(providerSettings.tokenIntrospectionEndpoint())
MvcResult mvcResult = this.mvc.perform(post(providerSettings.getTokenIntrospectionEndpoint())
.params(getTokenIntrospectionRequestParameters(refreshToken, OAuth2TokenType.REFRESH_TOKEN))
.with(httpBasic(introspectRegisteredClient.getClientId(), introspectRegisteredClient.getClientSecret())))
.andExpect(status().isOk())

View File

@@ -97,7 +97,7 @@ public class OAuth2TokenRevocationTests {
public static void init() {
JWKSet jwkSet = new JWKSet(TestJwks.DEFAULT_RSA_JWK);
jwkSource = (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
providerSettings = new ProviderSettings().tokenRevocationEndpoint("/test/revoke");
providerSettings = ProviderSettings.builder().tokenRevocationEndpoint("/test/revoke").build();
db = new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(EmbeddedDatabaseType.HSQL)
@@ -154,7 +154,7 @@ public class OAuth2TokenRevocationTests {
public void requestWhenRevokeAccessTokenCustomEndpointThenRevoked() throws Exception {
this.spring.register(AuthorizationServerConfigurationCustomEndpoints.class).autowire();
assertRevokeAccessTokenThenRevoked(providerSettings.tokenRevocationEndpoint());
assertRevokeAccessTokenThenRevoked(providerSettings.getTokenRevocationEndpoint());
}
private void assertRevokeAccessTokenThenRevoked(String tokenRevocationEndpointUri) throws Exception {

View File

@@ -333,7 +333,7 @@ public class OidcTests {
@Bean
ProviderSettings providerSettings() {
return new ProviderSettings().issuer(ISSUER_URL);
return ProviderSettings.builder().issuer(ISSUER_URL).build();
}
}
@@ -343,7 +343,7 @@ public class OidcTests {
@Bean
ProviderSettings providerSettings() {
return new ProviderSettings().issuer("urn:example");
return ProviderSettings.builder().issuer("urn:example").build();
}
}
@@ -353,7 +353,7 @@ public class OidcTests {
@Bean
ProviderSettings providerSettings() {
return new ProviderSettings().issuer("https://not a valid uri");
return ProviderSettings.builder().issuer("https://not a valid uri").build();
}
}
}

View File

@@ -53,6 +53,7 @@ import org.springframework.security.oauth2.server.authorization.OAuth2TokenCusto
import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
import org.springframework.security.oauth2.server.authorization.config.TokenSettings;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -377,8 +378,10 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
Duration accessTokenTTL = Duration.ofHours(2);
Duration refreshTokenTTL = Duration.ofDays(1);
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.tokenSettings(tokenSettings ->
tokenSettings.accessTokenTimeToLive(accessTokenTTL).refreshTokenTimeToLive(refreshTokenTTL))
.tokenSettings(TokenSettings.builder()
.accessTokenTimeToLive(accessTokenTTL)
.refreshTokenTimeToLive(refreshTokenTTL)
.build())
.build();
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).build();

View File

@@ -46,6 +46,7 @@ import org.springframework.security.oauth2.server.authorization.TestOAuth2Author
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
import org.springframework.security.oauth2.server.authorization.config.ClientSettings;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -309,7 +310,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
@Test
public void authenticateWhenPkceRequiredAndMissingCodeChallengeThenThrowOAuth2AuthorizationCodeRequestAuthenticationException() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.clientSettings(clientSettings -> clientSettings.requireProofKey(true))
.clientSettings(ClientSettings.builder().requireProofKey(true).build())
.build();
when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.thenReturn(registeredClient);
@@ -365,7 +366,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
@Test
public void authenticateWhenRequireAuthorizationConsentThenReturnAuthorizationConsent() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.clientSettings(clientSettings -> clientSettings.requireAuthorizationConsent(true))
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
.build();
when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.thenReturn(registeredClient);
@@ -412,7 +413,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
@Test
public void authenticateWhenRequireAuthorizationConsentAndOnlyOpenidScopeRequestedThenAuthorizationConsentNotRequired() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.clientSettings(clientSettings -> clientSettings.requireAuthorizationConsent(true))
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
.scopes(scopes -> {
scopes.clear();
scopes.add(OidcScopes.OPENID);
@@ -434,7 +435,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
@Test
public void authenticateWhenRequireAuthorizationConsentAndAllPreviouslyApprovedThenAuthorizationConsentNotRequired() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.clientSettings(clientSettings -> clientSettings.requireAuthorizationConsent(true))
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
.build();
when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.thenReturn(registeredClient);

View File

@@ -36,6 +36,7 @@ import org.springframework.security.oauth2.server.authorization.TestOAuth2Author
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
import org.springframework.security.oauth2.server.authorization.config.ClientSettings;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -209,7 +210,7 @@ public class OAuth2ClientAuthenticationProviderTests {
@Test
public void authenticateWhenPkceAndRequireProofKeyAndMissingCodeChallengeThenThrowOAuth2AuthenticationException() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.clientSettings(clientSettings -> clientSettings.requireProofKey(true))
.clientSettings(ClientSettings.builder().requireProofKey(true).build())
.build();
when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId())))
.thenReturn(registeredClient);

View File

@@ -52,6 +52,7 @@ import org.springframework.security.oauth2.server.authorization.OAuth2TokenCusto
import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
import org.springframework.security.oauth2.server.authorization.config.TokenSettings;
import static org.assertj.core.api.Assertions.entry;
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
@@ -233,7 +234,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
@Test
public void authenticateWhenReuseRefreshTokensFalseThenReturnNewRefreshToken() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
.tokenSettings(tokenSettings -> tokenSettings.reuseRefreshTokens(false))
.tokenSettings(TokenSettings.builder().reuseRefreshTokens(false).build())
.build();
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).build();
when(this.authorizationService.findByToken(

View File

@@ -42,6 +42,8 @@ import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.security.jackson2.SecurityJackson2Modules;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.server.authorization.config.ClientSettings;
import org.springframework.security.oauth2.server.authorization.config.TokenSettings;
import org.springframework.security.oauth2.server.authorization.jackson2.OAuth2AuthorizationServerJackson2Module;
import org.springframework.util.StringUtils;
@@ -322,12 +324,10 @@ public class JdbcRegisteredClientRepositoryTests {
// @formatter:on
Map<String, Object> clientSettingsMap = parseMap(rs.getString("clientSettings"));
builder.clientSettings(clientSettings ->
clientSettings.settings().putAll(clientSettingsMap));
builder.clientSettings(ClientSettings.withSettings(clientSettingsMap).build());
Map<String, Object> tokenSettingsMap = parseMap(rs.getString("tokenSettings"));
builder.tokenSettings(tokenSettings ->
tokenSettings.settings().putAll(tokenSettingsMap));
builder.tokenSettings(TokenSettings.withSettings(tokenSettingsMap).build());
return builder.build();
}

View File

@@ -347,9 +347,9 @@ public class RegisteredClientTests {
assertThat(registration.getRedirectUris()).isNotSameAs(updated.getRedirectUris());
assertThat(registration.getScopes()).isEqualTo(updated.getScopes());
assertThat(registration.getScopes()).isNotSameAs(updated.getScopes());
assertThat(registration.getClientSettings().settings()).isEqualTo(updated.getClientSettings().settings());
assertThat(registration.getClientSettings()).isEqualTo(updated.getClientSettings());
assertThat(registration.getClientSettings()).isNotSameAs(updated.getClientSettings());
assertThat(registration.getTokenSettings().settings()).isEqualTo(updated.getTokenSettings().settings());
assertThat(registration.getTokenSettings()).isEqualTo(updated.getTokenSettings());
assertThat(registration.getTokenSettings()).isNotSameAs(updated.getTokenSettings());
}

View File

@@ -20,6 +20,7 @@ import java.time.temporal.ChronoUnit;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.server.authorization.config.ClientSettings;
/**
* @author Anoop Garlapati
@@ -61,6 +62,6 @@ public class TestRegisteredClients {
.clientAuthenticationMethod(ClientAuthenticationMethod.NONE)
.redirectUri("https://example.com")
.scope("scope1")
.clientSettings(clientSettings -> clientSettings.requireProofKey(true));
.clientSettings(ClientSettings.builder().requireProofKey(true).build());
}
}

View File

@@ -18,7 +18,6 @@ package org.springframework.security.oauth2.server.authorization.config;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
/**
* Tests for {@link ClientSettings}.
@@ -28,43 +27,38 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
public class ClientSettingsTests {
@Test
public void constructorWhenDefaultThenDefaultsAreSet() {
ClientSettings clientSettings = new ClientSettings();
assertThat(clientSettings.settings()).hasSize(2);
assertThat(clientSettings.requireProofKey()).isFalse();
assertThat(clientSettings.requireAuthorizationConsent()).isFalse();
}
@Test
public void constructorWhenNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> new ClientSettings(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("settings cannot be null");
public void buildWhenDefaultThenDefaultsAreSet() {
ClientSettings clientSettings = ClientSettings.builder().build();
assertThat(clientSettings.getSettings()).hasSize(2);
assertThat(clientSettings.isRequireProofKey()).isFalse();
assertThat(clientSettings.isRequireAuthorizationConsent()).isFalse();
}
@Test
public void requireProofKeyWhenTrueThenSet() {
ClientSettings clientSettings = new ClientSettings().requireProofKey(true);
assertThat(clientSettings.requireProofKey()).isTrue();
ClientSettings clientSettings = ClientSettings.builder()
.requireProofKey(true)
.build();
assertThat(clientSettings.isRequireProofKey()).isTrue();
}
@Test
public void requireAuthorizationConsentWhenTrueThenSet() {
ClientSettings clientSettings = new ClientSettings().requireAuthorizationConsent(true);
assertThat(clientSettings.requireAuthorizationConsent()).isTrue();
ClientSettings clientSettings = ClientSettings.builder()
.requireAuthorizationConsent(true)
.build();
assertThat(clientSettings.isRequireAuthorizationConsent()).isTrue();
}
@Test
public void settingWhenCalledThenReturnClientSettings() {
ClientSettings clientSettings = new ClientSettings()
.<ClientSettings>setting("name1", "value1")
.requireProofKey(true)
.<ClientSettings>settings(settings -> settings.put("name2", "value2"))
.requireAuthorizationConsent(true);
assertThat(clientSettings.settings()).hasSize(4);
assertThat(clientSettings.requireProofKey()).isTrue();
assertThat(clientSettings.requireAuthorizationConsent()).isTrue();
assertThat(clientSettings.<String>setting("name1")).isEqualTo("value1");
assertThat(clientSettings.<String>setting("name2")).isEqualTo("value2");
public void settingWhenCustomThenSet() {
ClientSettings clientSettings = ClientSettings.builder()
.setting("name1", "value1")
.settings(settings -> settings.put("name2", "value2"))
.build();
assertThat(clientSettings.getSettings()).hasSize(4);
assertThat(clientSettings.<String>getSetting("name1")).isEqualTo("value1");
assertThat(clientSettings.<String>getSetting("name2")).isEqualTo("value2");
}
}

View File

@@ -28,20 +28,20 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
public class ProviderSettingsTests {
@Test
public void constructorWhenDefaultThenDefaultsAreSet() {
ProviderSettings providerSettings = new ProviderSettings();
public void buildWhenDefaultThenDefaultsAreSet() {
ProviderSettings providerSettings = ProviderSettings.builder().build();
assertThat(providerSettings.issuer()).isNull();
assertThat(providerSettings.authorizationEndpoint()).isEqualTo("/oauth2/authorize");
assertThat(providerSettings.tokenEndpoint()).isEqualTo("/oauth2/token");
assertThat(providerSettings.jwkSetEndpoint()).isEqualTo("/oauth2/jwks");
assertThat(providerSettings.tokenRevocationEndpoint()).isEqualTo("/oauth2/revoke");
assertThat(providerSettings.tokenIntrospectionEndpoint()).isEqualTo("/oauth2/introspect");
assertThat(providerSettings.oidcClientRegistrationEndpoint()).isEqualTo("/connect/register");
assertThat(providerSettings.getIssuer()).isNull();
assertThat(providerSettings.getAuthorizationEndpoint()).isEqualTo("/oauth2/authorize");
assertThat(providerSettings.getTokenEndpoint()).isEqualTo("/oauth2/token");
assertThat(providerSettings.getJwkSetEndpoint()).isEqualTo("/oauth2/jwks");
assertThat(providerSettings.getTokenRevocationEndpoint()).isEqualTo("/oauth2/revoke");
assertThat(providerSettings.getTokenIntrospectionEndpoint()).isEqualTo("/oauth2/introspect");
assertThat(providerSettings.getOidcClientRegistrationEndpoint()).isEqualTo("/connect/register");
}
@Test
public void settingsWhenProvidedThenSet() {
public void buildWhenSettingsProvidedThenSet() {
String authorizationEndpoint = "/oauth2/v1/authorize";
String tokenEndpoint = "/oauth2/v1/token";
String jwkSetEndpoint = "/oauth2/v1/jwks";
@@ -50,7 +50,7 @@ public class ProviderSettingsTests {
String oidcClientRegistrationEndpoint = "/connect/v1/register";
String issuer = "https://example.com:9000";
ProviderSettings providerSettings = new ProviderSettings()
ProviderSettings providerSettings = ProviderSettings.builder()
.issuer(issuer)
.authorizationEndpoint(authorizationEndpoint)
.tokenEndpoint(tokenEndpoint)
@@ -58,81 +58,76 @@ public class ProviderSettingsTests {
.tokenRevocationEndpoint(tokenRevocationEndpoint)
.tokenIntrospectionEndpoint(tokenIntrospectionEndpoint)
.tokenRevocationEndpoint(tokenRevocationEndpoint)
.oidcClientRegistrationEndpoint(oidcClientRegistrationEndpoint);
.oidcClientRegistrationEndpoint(oidcClientRegistrationEndpoint)
.build();
assertThat(providerSettings.issuer()).isEqualTo(issuer);
assertThat(providerSettings.authorizationEndpoint()).isEqualTo(authorizationEndpoint);
assertThat(providerSettings.tokenEndpoint()).isEqualTo(tokenEndpoint);
assertThat(providerSettings.jwkSetEndpoint()).isEqualTo(jwkSetEndpoint);
assertThat(providerSettings.tokenRevocationEndpoint()).isEqualTo(tokenRevocationEndpoint);
assertThat(providerSettings.tokenIntrospectionEndpoint()).isEqualTo(tokenIntrospectionEndpoint);
assertThat(providerSettings.oidcClientRegistrationEndpoint()).isEqualTo(oidcClientRegistrationEndpoint);
assertThat(providerSettings.getIssuer()).isEqualTo(issuer);
assertThat(providerSettings.getAuthorizationEndpoint()).isEqualTo(authorizationEndpoint);
assertThat(providerSettings.getTokenEndpoint()).isEqualTo(tokenEndpoint);
assertThat(providerSettings.getJwkSetEndpoint()).isEqualTo(jwkSetEndpoint);
assertThat(providerSettings.getTokenRevocationEndpoint()).isEqualTo(tokenRevocationEndpoint);
assertThat(providerSettings.getTokenIntrospectionEndpoint()).isEqualTo(tokenIntrospectionEndpoint);
assertThat(providerSettings.getOidcClientRegistrationEndpoint()).isEqualTo(oidcClientRegistrationEndpoint);
}
@Test
public void settingWhenCustomThenReturnAllSettings() {
ProviderSettings providerSettings = new ProviderSettings()
public void settingWhenCustomThenSet() {
ProviderSettings providerSettings = ProviderSettings.builder()
.setting("name1", "value1")
.settings(settings -> settings.put("name2", "value2"));
.settings(settings -> settings.put("name2", "value2"))
.build();
assertThat(providerSettings.settings()).hasSize(8);
assertThat(providerSettings.<String>setting("name1")).isEqualTo("value1");
assertThat(providerSettings.<String>setting("name2")).isEqualTo("value2");
assertThat(providerSettings.getSettings()).hasSize(8);
assertThat(providerSettings.<String>getSetting("name1")).isEqualTo("value1");
assertThat(providerSettings.<String>getSetting("name2")).isEqualTo("value2");
}
@Test
public void issuerWhenNullThenThrowIllegalArgumentException() {
ProviderSettings settings = new ProviderSettings();
assertThatIllegalArgumentException()
.isThrownBy(() -> settings.issuer(null))
.isThrownBy(() -> ProviderSettings.builder().issuer(null))
.withMessage("value cannot be null");
}
@Test
public void authorizationEndpointWhenNullThenThrowIllegalArgumentException() {
ProviderSettings settings = new ProviderSettings();
assertThatIllegalArgumentException()
.isThrownBy(() -> settings.authorizationEndpoint(null))
.isThrownBy(() -> ProviderSettings.builder().authorizationEndpoint(null))
.withMessage("value cannot be null");
}
@Test
public void tokenEndpointWhenNullThenThrowIllegalArgumentException() {
ProviderSettings settings = new ProviderSettings();
assertThatIllegalArgumentException()
.isThrownBy(() -> settings.tokenEndpoint(null))
.isThrownBy(() -> ProviderSettings.builder().tokenEndpoint(null))
.withMessage("value cannot be null");
}
@Test
public void tokenRevocationEndpointWhenNullThenThrowIllegalArgumentException() {
ProviderSettings settings = new ProviderSettings();
assertThatIllegalArgumentException()
.isThrownBy(() -> settings.tokenRevocationEndpoint(null))
.isThrownBy(() -> ProviderSettings.builder().tokenRevocationEndpoint(null))
.withMessage("value cannot be null");
}
@Test
public void tokenIntrospectionEndpointWhenNullThenThrowIllegalArgumentException() {
ProviderSettings settings = new ProviderSettings();
assertThatIllegalArgumentException()
.isThrownBy(() -> settings.tokenIntrospectionEndpoint(null))
.isThrownBy(() -> ProviderSettings.builder().tokenIntrospectionEndpoint(null))
.withMessage("value cannot be null");
}
@Test
public void oidcClientRegistrationEndpointWhenNullThenThrowIllegalArgumentException() {
ProviderSettings settings = new ProviderSettings();
assertThatIllegalArgumentException()
.isThrownBy(() -> settings.oidcClientRegistrationEndpoint(null))
.isThrownBy(() -> ProviderSettings.builder().oidcClientRegistrationEndpoint(null))
.withMessage("value cannot be null");
}
@Test
public void jwksEndpointWhenNullThenThrowIllegalArgumentException() {
ProviderSettings settings = new ProviderSettings();
assertThatIllegalArgumentException()
.isThrownBy(() -> settings.jwkSetEndpoint(null))
.isThrownBy(() -> ProviderSettings.builder().jwkSetEndpoint(null))
.withMessage("value cannot be null");
}

View File

@@ -1,78 +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.server.authorization.config;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.entry;
/**
* Tests for {@link Settings}.
*
* @author Joe Grandja
*/
public class SettingsTests {
@Test
public void constructorWhenNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> new Settings(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("settings cannot be null");
}
@Test
public void constructorWhenSettingsProvidedThenSettingsAreSet() {
Map<String, Object> initialSettings = new HashMap<>();
initialSettings.put("setting1", "value1");
initialSettings.put("setting2", "value2");
Settings settings = new Settings(initialSettings)
.setting("setting3", "value3")
.settings(s -> s.put("setting4", "value4"));
assertThat(settings.settings()).contains(
entry("setting1", "value1"),
entry("setting2", "value2"),
entry("setting3", "value3"),
entry("setting4", "value4"));
}
@Test
public void getSettingWhenNameNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> new Settings().setting(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("name cannot be empty");
}
@Test
public void setSettingWhenNameNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> new Settings().setting(null, "value"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("name cannot be empty");
}
@Test
public void setSettingWhenValueNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> new Settings().setting("setting", null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("value cannot be null");
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020 the original author or authors.
* Copyright 2020-2021 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.
@@ -32,42 +32,37 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
public class TokenSettingsTests {
@Test
public void constructorWhenDefaultThenDefaultsAreSet() {
TokenSettings tokenSettings = new TokenSettings();
assertThat(tokenSettings.settings()).hasSize(4);
assertThat(tokenSettings.accessTokenTimeToLive()).isEqualTo(Duration.ofMinutes(5));
assertThat(tokenSettings.reuseRefreshTokens()).isTrue();
assertThat(tokenSettings.refreshTokenTimeToLive()).isEqualTo(Duration.ofMinutes(60));
assertThat(tokenSettings.idTokenSignatureAlgorithm()).isEqualTo(SignatureAlgorithm.RS256);
}
@Test
public void constructorWhenNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> new TokenSettings(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("settings cannot be null");
public void buildWhenDefaultThenDefaultsAreSet() {
TokenSettings tokenSettings = TokenSettings.builder().build();
assertThat(tokenSettings.getSettings()).hasSize(4);
assertThat(tokenSettings.getAccessTokenTimeToLive()).isEqualTo(Duration.ofMinutes(5));
assertThat(tokenSettings.isReuseRefreshTokens()).isTrue();
assertThat(tokenSettings.getRefreshTokenTimeToLive()).isEqualTo(Duration.ofMinutes(60));
assertThat(tokenSettings.getIdTokenSignatureAlgorithm()).isEqualTo(SignatureAlgorithm.RS256);
}
@Test
public void accessTokenTimeToLiveWhenProvidedThenSet() {
Duration accessTokenTimeToLive = Duration.ofMinutes(10);
TokenSettings tokenSettings = new TokenSettings().accessTokenTimeToLive(accessTokenTimeToLive);
assertThat(tokenSettings.accessTokenTimeToLive()).isEqualTo(accessTokenTimeToLive);
TokenSettings tokenSettings = TokenSettings.builder()
.accessTokenTimeToLive(accessTokenTimeToLive)
.build();
assertThat(tokenSettings.getAccessTokenTimeToLive()).isEqualTo(accessTokenTimeToLive);
}
@Test
public void accessTokenTimeToLiveWhenNullOrZeroOrNegativeThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> new TokenSettings().accessTokenTimeToLive(null))
assertThatThrownBy(() -> TokenSettings.builder().accessTokenTimeToLive(null))
.isInstanceOf(IllegalArgumentException.class)
.extracting(Throwable::getMessage)
.isEqualTo("accessTokenTimeToLive cannot be null");
assertThatThrownBy(() -> new TokenSettings().accessTokenTimeToLive(Duration.ZERO))
assertThatThrownBy(() -> TokenSettings.builder().accessTokenTimeToLive(Duration.ZERO))
.isInstanceOf(IllegalArgumentException.class)
.extracting(Throwable::getMessage)
.isEqualTo("accessTokenTimeToLive must be greater than Duration.ZERO");
assertThatThrownBy(() -> new TokenSettings().accessTokenTimeToLive(Duration.ofSeconds(-10)))
assertThatThrownBy(() -> TokenSettings.builder().accessTokenTimeToLive(Duration.ofSeconds(-10)))
.isInstanceOf(IllegalArgumentException.class)
.extracting(Throwable::getMessage)
.isEqualTo("accessTokenTimeToLive must be greater than Duration.ZERO");
@@ -75,30 +70,34 @@ public class TokenSettingsTests {
@Test
public void reuseRefreshTokensWhenFalseThenSet() {
TokenSettings tokenSettings = new TokenSettings().reuseRefreshTokens(false);
assertThat(tokenSettings.reuseRefreshTokens()).isFalse();
TokenSettings tokenSettings = TokenSettings.builder()
.reuseRefreshTokens(false)
.build();
assertThat(tokenSettings.isReuseRefreshTokens()).isFalse();
}
@Test
public void refreshTokenTimeToLiveWhenProvidedThenSet() {
Duration refreshTokenTimeToLive = Duration.ofDays(10);
TokenSettings tokenSettings = new TokenSettings().refreshTokenTimeToLive(refreshTokenTimeToLive);
assertThat(tokenSettings.refreshTokenTimeToLive()).isEqualTo(refreshTokenTimeToLive);
TokenSettings tokenSettings = TokenSettings.builder()
.refreshTokenTimeToLive(refreshTokenTimeToLive)
.build();
assertThat(tokenSettings.getRefreshTokenTimeToLive()).isEqualTo(refreshTokenTimeToLive);
}
@Test
public void refreshTokenTimeToLiveWhenNullOrZeroOrNegativeThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> new TokenSettings().refreshTokenTimeToLive(null))
assertThatThrownBy(() -> TokenSettings.builder().refreshTokenTimeToLive(null))
.isInstanceOf(IllegalArgumentException.class)
.extracting(Throwable::getMessage)
.isEqualTo("refreshTokenTimeToLive cannot be null");
assertThatThrownBy(() -> new TokenSettings().refreshTokenTimeToLive(Duration.ZERO))
assertThatThrownBy(() -> TokenSettings.builder().refreshTokenTimeToLive(Duration.ZERO))
.isInstanceOf(IllegalArgumentException.class)
.extracting(Throwable::getMessage)
.isEqualTo("refreshTokenTimeToLive must be greater than Duration.ZERO");
assertThatThrownBy(() -> new TokenSettings().refreshTokenTimeToLive(Duration.ofSeconds(-10)))
assertThatThrownBy(() -> TokenSettings.builder().refreshTokenTimeToLive(Duration.ofSeconds(-10)))
.isInstanceOf(IllegalArgumentException.class)
.extracting(Throwable::getMessage)
.isEqualTo("refreshTokenTimeToLive must be greater than Duration.ZERO");
@@ -107,23 +106,21 @@ public class TokenSettingsTests {
@Test
public void idTokenSignatureAlgorithmWhenProvidedThenSet() {
SignatureAlgorithm idTokenSignatureAlgorithm = SignatureAlgorithm.RS512;
TokenSettings tokenSettings = new TokenSettings().idTokenSignatureAlgorithm(idTokenSignatureAlgorithm);
assertThat(tokenSettings.idTokenSignatureAlgorithm()).isEqualTo(idTokenSignatureAlgorithm);
TokenSettings tokenSettings = TokenSettings.builder()
.idTokenSignatureAlgorithm(idTokenSignatureAlgorithm)
.build();
assertThat(tokenSettings.getIdTokenSignatureAlgorithm()).isEqualTo(idTokenSignatureAlgorithm);
}
@Test
public void settingWhenCalledThenReturnTokenSettings() {
Duration accessTokenTimeToLive = Duration.ofMinutes(10);
TokenSettings tokenSettings = new TokenSettings()
.<TokenSettings>setting("name1", "value1")
.accessTokenTimeToLive(accessTokenTimeToLive)
.settings(settings -> settings.put("name2", "value2"));
assertThat(tokenSettings.settings()).hasSize(6);
assertThat(tokenSettings.accessTokenTimeToLive()).isEqualTo(accessTokenTimeToLive);
assertThat(tokenSettings.reuseRefreshTokens()).isTrue();
assertThat(tokenSettings.refreshTokenTimeToLive()).isEqualTo(Duration.ofMinutes(60));
assertThat(tokenSettings.idTokenSignatureAlgorithm()).isEqualTo(SignatureAlgorithm.RS256);
assertThat(tokenSettings.<String>setting("name1")).isEqualTo("value1");
assertThat(tokenSettings.<String>setting("name2")).isEqualTo("value2");
public void settingWhenCustomThenSet() {
TokenSettings tokenSettings = TokenSettings.builder()
.setting("name1", "value1")
.settings(settings -> settings.put("name2", "value2"))
.build();
assertThat(tokenSettings.getSettings()).hasSize(6);
assertThat(tokenSettings.<String>getSetting("name1")).isEqualTo("value1");
assertThat(tokenSettings.<String>getSetting("name2")).isEqualTo("value2");
}
}

View File

@@ -264,9 +264,9 @@ public class OidcClientRegistrationAuthenticationProviderTests {
assertThat(registeredClientResult.getAuthorizationGrantTypes())
.containsExactlyInAnyOrder(AuthorizationGrantType.AUTHORIZATION_CODE, AuthorizationGrantType.CLIENT_CREDENTIALS);
assertThat(registeredClientResult.getScopes()).containsExactlyInAnyOrder("scope1", "scope2");
assertThat(registeredClientResult.getClientSettings().requireProofKey()).isTrue();
assertThat(registeredClientResult.getClientSettings().requireAuthorizationConsent()).isTrue();
assertThat(registeredClientResult.getTokenSettings().idTokenSignatureAlgorithm()).isEqualTo(SignatureAlgorithm.RS256);
assertThat(registeredClientResult.getClientSettings().isRequireProofKey()).isTrue();
assertThat(registeredClientResult.getClientSettings().isRequireAuthorizationConsent()).isTrue();
assertThat(registeredClientResult.getTokenSettings().getIdTokenSignatureAlgorithm()).isEqualTo(SignatureAlgorithm.RS256);
OidcClientRegistration clientRegistrationResult = authenticationResult.getClientRegistration();
assertThat(clientRegistrationResult.getClientId()).isEqualTo(registeredClientResult.getClientId());
@@ -289,7 +289,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
assertThat(clientRegistrationResult.getTokenEndpointAuthenticationMethod())
.isEqualTo(registeredClientResult.getClientAuthenticationMethods().iterator().next().getValue());
assertThat(clientRegistrationResult.getIdTokenSignedResponseAlgorithm())
.isEqualTo(registeredClientResult.getTokenSettings().idTokenSignatureAlgorithm().getName());
.isEqualTo(registeredClientResult.getTokenSettings().getIdTokenSignatureAlgorithm().getName());
}
private static Jwt createJwt() {

View File

@@ -15,16 +15,17 @@
*/
package org.springframework.security.oauth2.server.authorization.oidc.web;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.junit.Test;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.ArgumentMatchers.any;
@@ -50,7 +51,7 @@ public class OidcProviderConfigurationEndpointFilterTests {
@Test
public void doFilterWhenNotConfigurationRequestThenNotProcessed() throws Exception {
OidcProviderConfigurationEndpointFilter filter =
new OidcProviderConfigurationEndpointFilter(new ProviderSettings());
new OidcProviderConfigurationEndpointFilter(ProviderSettings.builder().build());
String requestUri = "/path";
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
@@ -66,7 +67,7 @@ public class OidcProviderConfigurationEndpointFilterTests {
@Test
public void doFilterWhenConfigurationRequestPostThenNotProcessed() throws Exception {
OidcProviderConfigurationEndpointFilter filter =
new OidcProviderConfigurationEndpointFilter(new ProviderSettings());
new OidcProviderConfigurationEndpointFilter(ProviderSettings.builder().build());
String requestUri = DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI;
MockHttpServletRequest request = new MockHttpServletRequest("POST", requestUri);
@@ -85,11 +86,12 @@ public class OidcProviderConfigurationEndpointFilterTests {
String tokenEndpoint = "/oauth2/v1/token";
String jwkSetEndpoint = "/oauth2/v1/jwks";
ProviderSettings providerSettings = new ProviderSettings()
ProviderSettings providerSettings = ProviderSettings.builder()
.issuer("https://example.com/issuer1")
.authorizationEndpoint(authorizationEndpoint)
.tokenEndpoint(tokenEndpoint)
.jwkSetEndpoint(jwkSetEndpoint);
.jwkSetEndpoint(jwkSetEndpoint)
.build();
OidcProviderConfigurationEndpointFilter filter =
new OidcProviderConfigurationEndpointFilter(providerSettings);
@@ -119,8 +121,9 @@ public class OidcProviderConfigurationEndpointFilterTests {
@Test
public void doFilterWhenProviderSettingsWithInvalidIssuerThenThrowIllegalArgumentException() {
ProviderSettings providerSettings = new ProviderSettings()
.issuer("https://this is an invalid URL");
ProviderSettings providerSettings = ProviderSettings.builder()
.issuer("https://this is an invalid URL")
.build();
OidcProviderConfigurationEndpointFilter filter =
new OidcProviderConfigurationEndpointFilter(providerSettings);

View File

@@ -52,7 +52,7 @@ public class OAuth2AuthorizationServerMetadataEndpointFilterTests {
@Test
public void doFilterWhenNotAuthorizationServerMetadataRequestThenNotProcessed() throws Exception {
OAuth2AuthorizationServerMetadataEndpointFilter filter =
new OAuth2AuthorizationServerMetadataEndpointFilter(new ProviderSettings().issuer("https://example.com"));
new OAuth2AuthorizationServerMetadataEndpointFilter(ProviderSettings.builder().issuer("https://example.com").build());
String requestUri = "/path";
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
@@ -68,7 +68,7 @@ public class OAuth2AuthorizationServerMetadataEndpointFilterTests {
@Test
public void doFilterWhenAuthorizationServerMetadataRequestPostThenNotProcessed() throws Exception {
OAuth2AuthorizationServerMetadataEndpointFilter filter =
new OAuth2AuthorizationServerMetadataEndpointFilter(new ProviderSettings().issuer("https://example.com"));
new OAuth2AuthorizationServerMetadataEndpointFilter(ProviderSettings.builder().issuer("https://example.com").build());
String requestUri = DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI;
MockHttpServletRequest request = new MockHttpServletRequest("POST", requestUri);
@@ -89,13 +89,14 @@ public class OAuth2AuthorizationServerMetadataEndpointFilterTests {
String tokenRevocationEndpoint = "/oauth2/v1/revoke";
String tokenIntrospectionEndpoint = "/oauth2/v1/introspect";
ProviderSettings providerSettings = new ProviderSettings()
ProviderSettings providerSettings = ProviderSettings.builder()
.issuer("https://example.com/issuer1")
.authorizationEndpoint(authorizationEndpoint)
.tokenEndpoint(tokenEndpoint)
.jwkSetEndpoint(jwkSetEndpoint)
.tokenRevocationEndpoint(tokenRevocationEndpoint)
.tokenIntrospectionEndpoint(tokenIntrospectionEndpoint);
.tokenIntrospectionEndpoint(tokenIntrospectionEndpoint)
.build();
OAuth2AuthorizationServerMetadataEndpointFilter filter =
new OAuth2AuthorizationServerMetadataEndpointFilter(providerSettings);
@@ -127,8 +128,9 @@ public class OAuth2AuthorizationServerMetadataEndpointFilterTests {
@Test
public void doFilterWhenProviderSettingsWithInvalidIssuerThenThrowIllegalArgumentException() {
ProviderSettings providerSettings = new ProviderSettings()
.issuer("https://this is an invalid URL");
ProviderSettings providerSettings = ProviderSettings.builder()
.issuer("https://this is an invalid URL")
.build();
OAuth2AuthorizationServerMetadataEndpointFilter filter =
new OAuth2AuthorizationServerMetadataEndpointFilter(providerSettings);

View File

@@ -38,6 +38,7 @@ import org.springframework.security.oauth2.server.authorization.OAuth2Authorizat
import org.springframework.security.oauth2.server.authorization.client.InMemoryRegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.config.ClientSettings;
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.RequestMatcher;
@@ -86,7 +87,7 @@ public class AuthorizationServerConfig {
.scope(OidcScopes.OPENID)
.scope("message.read")
.scope("message.write")
.clientSettings(clientSettings -> clientSettings.requireAuthorizationConsent(true))
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
.build();
return new InMemoryRegisteredClientRepository(registeredClient);
}
@@ -101,7 +102,7 @@ public class AuthorizationServerConfig {
@Bean
public ProviderSettings providerSettings() {
return new ProviderSettings().issuer("http://auth-server:9000");
return ProviderSettings.builder().issuer("http://auth-server:9000").build();
}
@Bean

View File

@@ -45,6 +45,7 @@ import org.springframework.security.oauth2.server.authorization.OAuth2Authorizat
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.config.ClientSettings;
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
import org.springframework.security.web.SecurityFilterChain;
@@ -77,7 +78,7 @@ public class AuthorizationServerConfig {
.scope(OidcScopes.OPENID)
.scope("message.read")
.scope("message.write")
.clientSettings(clientSettings -> clientSettings.requireAuthorizationConsent(true))
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
.build();
// Save registered client in db as if in-memory
@@ -112,7 +113,7 @@ public class AuthorizationServerConfig {
@Bean
public ProviderSettings providerSettings() {
return new ProviderSettings().issuer("http://auth-server:9000");
return ProviderSettings.builder().issuer("http://auth-server:9000").build();
}
@Bean