Skip to content

Commit c3b2545

Browse files
committed
Add client configuration settings
Closes gh-117
1 parent 22bf1eb commit c3b2545

File tree

8 files changed

+485
-14
lines changed

8 files changed

+485
-14
lines changed

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/client/RegisteredClient.java

+50
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import org.springframework.security.core.SpringSecurityCoreVersion2;
1919
import org.springframework.security.oauth2.core.AuthorizationGrantType;
2020
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
21+
import org.springframework.security.oauth2.server.authorization.config.ClientSettings;
22+
import org.springframework.security.oauth2.server.authorization.config.TokenSettings;
2123
import org.springframework.util.Assert;
2224
import org.springframework.util.CollectionUtils;
2325

@@ -46,6 +48,8 @@ public class RegisteredClient implements Serializable {
4648
private Set<AuthorizationGrantType> authorizationGrantTypes;
4749
private Set<String> redirectUris;
4850
private Set<String> scopes;
51+
private ClientSettings clientSettings;
52+
private TokenSettings tokenSettings;
4953

5054
protected RegisteredClient() {
5155
}
@@ -114,6 +118,24 @@ public Set<String> getScopes() {
114118
return this.scopes;
115119
}
116120

121+
/**
122+
* Returns the {@link ClientSettings client configuration settings}.
123+
*
124+
* @return the {@link ClientSettings}
125+
*/
126+
public ClientSettings getClientSettings() {
127+
return this.clientSettings;
128+
}
129+
130+
/**
131+
* Returns the {@link TokenSettings token configuration settings}.
132+
*
133+
* @return the {@link TokenSettings}
134+
*/
135+
public TokenSettings getTokenSettings() {
136+
return this.tokenSettings;
137+
}
138+
117139
@Override
118140
public String toString() {
119141
return "RegisteredClient{" +
@@ -160,6 +182,8 @@ public static class Builder implements Serializable {
160182
private Set<AuthorizationGrantType> authorizationGrantTypes = new LinkedHashSet<>();
161183
private Set<String> redirectUris = new LinkedHashSet<>();
162184
private Set<String> scopes = new LinkedHashSet<>();
185+
private ClientSettings clientSettings;
186+
private TokenSettings tokenSettings;
163187

164188
protected Builder(String id) {
165189
this.id = id;
@@ -181,6 +205,8 @@ protected Builder(RegisteredClient registeredClient) {
181205
if (!CollectionUtils.isEmpty(registeredClient.scopes)) {
182206
this.scopes.addAll(registeredClient.scopes);
183207
}
208+
this.clientSettings = new ClientSettings(registeredClient.clientSettings.settings());
209+
this.tokenSettings = new TokenSettings(registeredClient.tokenSettings.settings());
184210
}
185211

186212
/**
@@ -310,6 +336,28 @@ public Builder scopes(Consumer<Set<String>> scopesConsumer) {
310336
return this;
311337
}
312338

339+
/**
340+
* Sets the {@link ClientSettings client configuration settings}.
341+
*
342+
* @param clientSettings the client configuration settings
343+
* @return the {@link Builder}
344+
*/
345+
public Builder clientSettings(ClientSettings clientSettings) {
346+
this.clientSettings = clientSettings;
347+
return this;
348+
}
349+
350+
/**
351+
* Sets the {@link TokenSettings token configuration settings}.
352+
*
353+
* @param tokenSettings the token configuration settings
354+
* @return the {@link Builder}
355+
*/
356+
public Builder tokenSettings(TokenSettings tokenSettings) {
357+
this.tokenSettings = tokenSettings;
358+
return this;
359+
}
360+
313361
/**
314362
* Builds a new {@link RegisteredClient}.
315363
*
@@ -341,6 +389,8 @@ private RegisteredClient create() {
341389
registeredClient.authorizationGrantTypes = Collections.unmodifiableSet(this.authorizationGrantTypes);
342390
registeredClient.redirectUris = Collections.unmodifiableSet(this.redirectUris);
343391
registeredClient.scopes = Collections.unmodifiableSet(this.scopes);
392+
registeredClient.clientSettings = this.clientSettings != null ? this.clientSettings : new ClientSettings();
393+
registeredClient.tokenSettings = this.tokenSettings != null ? this.tokenSettings : new TokenSettings();
344394

345395
return registeredClient;
346396
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright 2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.security.oauth2.server.authorization.config;
17+
18+
import java.util.HashMap;
19+
import java.util.Map;
20+
21+
/**
22+
* A facility for client configuration settings.
23+
*
24+
* @author Joe Grandja
25+
* @since 0.0.2
26+
* @see Settings
27+
*/
28+
public class ClientSettings extends Settings {
29+
private static final String CLIENT_SETTING_BASE = "spring.security.oauth2.authorization-server.client.";
30+
public static final String REQUIRE_PROOF_KEY = CLIENT_SETTING_BASE.concat("require-proof-key");
31+
32+
/**
33+
* Constructs a {@code ClientSettings}.
34+
*/
35+
public ClientSettings() {
36+
this(defaultSettings());
37+
}
38+
39+
/**
40+
* Constructs a {@code ClientSettings} using the provided parameters.
41+
*
42+
* @param settings the initial settings
43+
*/
44+
public ClientSettings(Map<String, Object> settings) {
45+
super(settings);
46+
}
47+
48+
/**
49+
* Returns {@code true} if the client is required to provide a proof key challenge and verifier
50+
* when performing the Authorization Code Grant flow. The default is {@code false}.
51+
*
52+
* @return {@code true} if the client is required to provide a proof key challenge and verifier, {@code false} otherwise
53+
*/
54+
public boolean requireProofKey() {
55+
return setting(REQUIRE_PROOF_KEY);
56+
}
57+
58+
/**
59+
* Set to {@code true} if the client is required to provide a proof key challenge and verifier
60+
* when performing the Authorization Code Grant flow.
61+
*
62+
* @param requireProofKey {@code true} if the client is required to provide a proof key challenge and verifier, {@code false} otherwise
63+
* @return the {@link ClientSettings}
64+
*/
65+
public ClientSettings requireProofKey(boolean requireProofKey) {
66+
setting(REQUIRE_PROOF_KEY, requireProofKey);
67+
return this;
68+
}
69+
70+
protected static Map<String, Object> defaultSettings() {
71+
Map<String, Object> settings = new HashMap<>();
72+
settings.put(REQUIRE_PROOF_KEY, false);
73+
return settings;
74+
}
75+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* Copyright 2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.security.oauth2.server.authorization.config;
17+
18+
import org.springframework.security.core.SpringSecurityCoreVersion2;
19+
import org.springframework.util.Assert;
20+
21+
import java.io.Serializable;
22+
import java.util.HashMap;
23+
import java.util.Map;
24+
import java.util.function.Consumer;
25+
26+
/**
27+
* A facility for configuration settings.
28+
*
29+
* @author Joe Grandja
30+
* @since 0.0.2
31+
*/
32+
public class Settings implements Serializable {
33+
private static final long serialVersionUID = SpringSecurityCoreVersion2.SERIAL_VERSION_UID;
34+
private final Map<String, Object> settings;
35+
36+
/**
37+
* Constructs a {@code Settings}.
38+
*/
39+
public Settings() {
40+
this.settings = new HashMap<>();
41+
}
42+
43+
/**
44+
* Constructs a {@code Settings} using the provided parameters.
45+
*
46+
* @param settings the initial settings
47+
*/
48+
public Settings(Map<String, Object> settings) {
49+
Assert.notNull(settings, "settings cannot be null");
50+
this.settings = new HashMap<>(settings);
51+
}
52+
53+
/**
54+
* Returns a configuration setting.
55+
*
56+
* @param name the name of the setting
57+
* @param <T> the type of the setting
58+
* @return the value of the setting, or {@code null} if not available
59+
*/
60+
@SuppressWarnings("unchecked")
61+
public <T> T setting(String name) {
62+
Assert.hasText(name, "name cannot be empty");
63+
return (T) this.settings.get(name);
64+
}
65+
66+
/**
67+
* Sets a configuration setting.
68+
*
69+
* @param name the name of the setting
70+
* @param value the value of the setting
71+
* @return the {@link Settings}
72+
*/
73+
public Settings setting(String name, Object value) {
74+
Assert.hasText(name, "name cannot be empty");
75+
Assert.notNull(value, "value cannot be null");
76+
this.settings.put(name, value);
77+
return this;
78+
}
79+
80+
/**
81+
* Returns a {@code Map} of the configuration settings.
82+
*
83+
* @return a {@code Map} of the configuration settings
84+
*/
85+
public Map<String, Object> settings() {
86+
return this.settings;
87+
}
88+
89+
/**
90+
* A {@code Consumer} of the configuration settings {@code Map}
91+
* allowing the ability to add, replace, or remove.
92+
*
93+
* @param settingsConsumer a {@link Consumer} of the configuration settings {@code Map}
94+
* @return the {@link Settings}
95+
*/
96+
public Settings settings(Consumer<Map<String, Object>> settingsConsumer) {
97+
settingsConsumer.accept(this.settings);
98+
return this;
99+
}
100+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright 2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.security.oauth2.server.authorization.config;
17+
18+
import java.time.Duration;
19+
import java.util.HashMap;
20+
import java.util.Map;
21+
22+
/**
23+
* A facility for token configuration settings.
24+
*
25+
* @author Joe Grandja
26+
* @since 0.0.2
27+
* @see Settings
28+
*/
29+
public class TokenSettings extends Settings {
30+
private static final String TOKEN_SETTING_BASE = "spring.security.oauth2.authorization-server.token.";
31+
public static final String ACCESS_TOKEN_TIME_TO_LIVE = TOKEN_SETTING_BASE.concat("access-token-time-to-live");
32+
33+
/**
34+
* Constructs a {@code TokenSettings}.
35+
*/
36+
public TokenSettings() {
37+
this(defaultSettings());
38+
}
39+
40+
/**
41+
* Constructs a {@code TokenSettings} using the provided parameters.
42+
*
43+
* @param settings the initial settings
44+
*/
45+
public TokenSettings(Map<String, Object> settings) {
46+
super(settings);
47+
}
48+
49+
/**
50+
* Returns the time-to-live for an access token. The default is 5 minutes.
51+
*
52+
* @return the time-to-live for an access token
53+
*/
54+
public Duration accessTokenTimeToLive() {
55+
return setting(ACCESS_TOKEN_TIME_TO_LIVE);
56+
}
57+
58+
/**
59+
* Set the time-to-live for an access token.
60+
*
61+
* @param accessTokenTimeToLive the time-to-live for an access token
62+
* @return the {@link TokenSettings}
63+
*/
64+
public TokenSettings accessTokenTimeToLive(Duration accessTokenTimeToLive) {
65+
setting(ACCESS_TOKEN_TIME_TO_LIVE, accessTokenTimeToLive);
66+
return this;
67+
}
68+
69+
protected static Map<String, Object> defaultSettings() {
70+
Map<String, Object> settings = new HashMap<>();
71+
settings.put(ACCESS_TOKEN_TIME_TO_LIVE, Duration.ofMinutes(5));
72+
return settings;
73+
}
74+
}

oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/client/RegisteredClientTests.java

+7-14
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,9 @@ public void buildWhenRegisteredClientProvidedThenMakesACopy() {
322322
RegisteredClient registration = TestRegisteredClients.registeredClient().build();
323323
RegisteredClient updated = RegisteredClient.withRegisteredClient(registration).build();
324324

325+
assertThat(registration.getId()).isEqualTo(updated.getId());
326+
assertThat(registration.getClientId()).isEqualTo(updated.getClientId());
327+
assertThat(registration.getClientSecret()).isEqualTo(updated.getClientSecret());
325328
assertThat(registration.getClientAuthenticationMethods()).isEqualTo(updated.getClientAuthenticationMethods());
326329
assertThat(registration.getClientAuthenticationMethods()).isNotSameAs(updated.getClientAuthenticationMethods());
327330
assertThat(registration.getAuthorizationGrantTypes()).isEqualTo(updated.getAuthorizationGrantTypes());
@@ -330,20 +333,10 @@ public void buildWhenRegisteredClientProvidedThenMakesACopy() {
330333
assertThat(registration.getRedirectUris()).isNotSameAs(updated.getRedirectUris());
331334
assertThat(registration.getScopes()).isEqualTo(updated.getScopes());
332335
assertThat(registration.getScopes()).isNotSameAs(updated.getScopes());
333-
}
334-
335-
@Test
336-
public void buildWhenRegisteredClientProvidedThenEachPropertyMatches() {
337-
RegisteredClient registration = TestRegisteredClients.registeredClient().build();
338-
RegisteredClient updated = RegisteredClient.withRegisteredClient(registration).build();
339-
340-
assertThat(registration.getId()).isEqualTo(updated.getId());
341-
assertThat(registration.getClientId()).isEqualTo(updated.getClientId());
342-
assertThat(registration.getClientSecret()).isEqualTo(updated.getClientSecret());
343-
assertThat(registration.getClientAuthenticationMethods()).isEqualTo(updated.getClientAuthenticationMethods());
344-
assertThat(registration.getAuthorizationGrantTypes()).isEqualTo(updated.getAuthorizationGrantTypes());
345-
assertThat(registration.getRedirectUris()).isEqualTo(updated.getRedirectUris());
346-
assertThat(registration.getScopes()).isEqualTo(updated.getScopes());
336+
assertThat(registration.getClientSettings().settings()).isEqualTo(updated.getClientSettings().settings());
337+
assertThat(registration.getClientSettings()).isNotSameAs(updated.getClientSettings());
338+
assertThat(registration.getTokenSettings().settings()).isEqualTo(updated.getTokenSettings().settings());
339+
assertThat(registration.getTokenSettings()).isNotSameAs(updated.getTokenSettings());
347340
}
348341

349342
@Test

0 commit comments

Comments
 (0)