Skip to content

Commit f2fc0dc

Browse files
committed
Set PasswordEncoder in RegisteredClientParameters mapper and hash the client secret before saving it
Closes gh-378
1 parent 41f8c9c commit f2fc0dc

File tree

9 files changed

+106
-18
lines changed

9 files changed

+106
-18
lines changed

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

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
import org.springframework.jdbc.core.PreparedStatementSetter;
3737
import org.springframework.jdbc.core.RowMapper;
3838
import org.springframework.jdbc.core.SqlParameterValue;
39+
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
40+
import org.springframework.security.crypto.password.PasswordEncoder;
3941
import org.springframework.security.jackson2.SecurityJackson2Modules;
4042
import org.springframework.security.oauth2.core.AuthorizationGrantType;
4143
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
@@ -291,6 +293,7 @@ private static ClientAuthenticationMethod resolveClientAuthenticationMethod(Stri
291293
*/
292294
public static class RegisteredClientParametersMapper implements Function<RegisteredClient, List<SqlParameterValue>> {
293295
private ObjectMapper objectMapper = new ObjectMapper();
296+
private PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
294297

295298
public RegisteredClientParametersMapper() {
296299
ClassLoader classLoader = JdbcRegisteredClientRepository.class.getClassLoader();
@@ -319,7 +322,7 @@ public List<SqlParameterValue> apply(RegisteredClient registeredClient) {
319322
new SqlParameterValue(Types.VARCHAR, registeredClient.getId()),
320323
new SqlParameterValue(Types.VARCHAR, registeredClient.getClientId()),
321324
new SqlParameterValue(Types.TIMESTAMP, clientIdIssuedAt),
322-
new SqlParameterValue(Types.VARCHAR, registeredClient.getClientSecret()),
325+
new SqlParameterValue(Types.VARCHAR, encode(registeredClient.getClientSecret())),
323326
new SqlParameterValue(Types.TIMESTAMP, clientSecretExpiresAt),
324327
new SqlParameterValue(Types.VARCHAR, registeredClient.getClientName()),
325328
new SqlParameterValue(Types.VARCHAR, StringUtils.collectionToCommaDelimitedString(clientAuthenticationMethods)),
@@ -335,6 +338,12 @@ public final void setObjectMapper(ObjectMapper objectMapper) {
335338
this.objectMapper = objectMapper;
336339
}
337340

341+
342+
public final void setPasswordEncoder(PasswordEncoder passwordEncoder) {
343+
Assert.notNull(passwordEncoder, "passwordEncoder cannot be null");
344+
this.passwordEncoder = passwordEncoder;
345+
}
346+
338347
protected final ObjectMapper getObjectMapper() {
339348
return this.objectMapper;
340349
}
@@ -347,6 +356,13 @@ private String writeMap(Map<String, Object> data) {
347356
}
348357
}
349358

359+
private String encode(String value) {
360+
if (value != null) {
361+
return this.passwordEncoder.encode(value);
362+
}
363+
return null;
364+
}
365+
350366
}
351367

352368
}

oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2AuthorizationCodeGrantTests.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
8484
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationToken;
8585
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
86+
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository.RegisteredClientParametersMapper;
8687
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
8788
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
8889
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
@@ -582,8 +583,12 @@ OAuth2AuthorizationConsentService authorizationConsentService(JdbcOperations jdb
582583
}
583584

584585
@Bean
585-
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
586-
return new JdbcRegisteredClientRepository(jdbcOperations);
586+
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations, PasswordEncoder passwordEncoder) {
587+
JdbcRegisteredClientRepository jdbcRegisteredClientRepository = new JdbcRegisteredClientRepository(jdbcOperations);
588+
RegisteredClientParametersMapper registeredClientParametersMapper = new RegisteredClientParametersMapper();
589+
registeredClientParametersMapper.setPasswordEncoder(passwordEncoder);
590+
jdbcRegisteredClientRepository.setRegisteredClientParametersMapper(registeredClientParametersMapper);
591+
return jdbcRegisteredClientRepository;
587592
}
588593

589594
@Bean

oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2ClientCredentialsGrantTests.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken;
6868
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientCredentialsAuthenticationToken;
6969
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
70+
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository.RegisteredClientParametersMapper;
7071
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
7172
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
7273
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
@@ -279,8 +280,12 @@ OAuth2AuthorizationService authorizationService(JdbcOperations jdbcOperations, R
279280
}
280281

281282
@Bean
282-
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
283-
return new JdbcRegisteredClientRepository(jdbcOperations);
283+
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations, PasswordEncoder passwordEncoder) {
284+
JdbcRegisteredClientRepository jdbcRegisteredClientRepository = new JdbcRegisteredClientRepository(jdbcOperations);
285+
RegisteredClientParametersMapper registeredClientParametersMapper = new RegisteredClientParametersMapper();
286+
registeredClientParametersMapper.setPasswordEncoder(passwordEncoder);
287+
jdbcRegisteredClientRepository.setRegisteredClientParametersMapper(registeredClientParametersMapper);
288+
return jdbcRegisteredClientRepository;
284289
}
285290

286291
@Bean

oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2RefreshTokenGrantTests.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer;
6969
import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
7070
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
71+
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository.RegisteredClientParametersMapper;
7172
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
7273
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
7374
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
@@ -207,8 +208,12 @@ OAuth2AuthorizationService authorizationService(JdbcOperations jdbcOperations, R
207208
}
208209

209210
@Bean
210-
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
211-
return new JdbcRegisteredClientRepository(jdbcOperations);
211+
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations, PasswordEncoder passwordEncoder) {
212+
JdbcRegisteredClientRepository jdbcRegisteredClientRepository = new JdbcRegisteredClientRepository(jdbcOperations);
213+
RegisteredClientParametersMapper registeredClientParametersMapper = new RegisteredClientParametersMapper();
214+
registeredClientParametersMapper.setPasswordEncoder(passwordEncoder);
215+
jdbcRegisteredClientRepository.setRegisteredClientParametersMapper(registeredClientParametersMapper);
216+
return jdbcRegisteredClientRepository;
212217
}
213218

214219
@Bean

oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2TokenIntrospectionTests.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
6363
import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
6464
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
65+
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository.RegisteredClientParametersMapper;
6566
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
6667
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
6768
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
@@ -244,8 +245,12 @@ OAuth2AuthorizationService authorizationService(JdbcOperations jdbcOperations, R
244245
}
245246

246247
@Bean
247-
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
248-
return new JdbcRegisteredClientRepository(jdbcOperations);
248+
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations, PasswordEncoder passwordEncoder) {
249+
JdbcRegisteredClientRepository jdbcRegisteredClientRepository = new JdbcRegisteredClientRepository(jdbcOperations);
250+
RegisteredClientParametersMapper registeredClientParametersMapper = new RegisteredClientParametersMapper();
251+
registeredClientParametersMapper.setPasswordEncoder(passwordEncoder);
252+
jdbcRegisteredClientRepository.setRegisteredClientParametersMapper(registeredClientParametersMapper);
253+
return jdbcRegisteredClientRepository;
249254
}
250255

251256
@Bean

oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2TokenRevocationTests.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
5555
import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
5656
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
57+
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository.RegisteredClientParametersMapper;
5758
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
5859
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
5960
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
@@ -207,8 +208,12 @@ OAuth2AuthorizationService authorizationService(JdbcOperations jdbcOperations, R
207208
}
208209

209210
@Bean
210-
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
211-
return new JdbcRegisteredClientRepository(jdbcOperations);
211+
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations, PasswordEncoder passwordEncoder) {
212+
JdbcRegisteredClientRepository jdbcRegisteredClientRepository = new JdbcRegisteredClientRepository(jdbcOperations);
213+
RegisteredClientParametersMapper registeredClientParametersMapper = new RegisteredClientParametersMapper();
214+
registeredClientParametersMapper.setPasswordEncoder(passwordEncoder);
215+
jdbcRegisteredClientRepository.setRegisteredClientParametersMapper(registeredClientParametersMapper);
216+
return jdbcRegisteredClientRepository;
212217
}
213218

214219
@Bean

oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OidcClientRegistrationTests.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import org.springframework.security.oauth2.jose.TestJwks;
6161
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
6262
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
63+
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository.RegisteredClientParametersMapper;
6364
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
6465
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
6566
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
@@ -226,9 +227,12 @@ private static OidcClientRegistration readClientRegistrationResponse(MockHttpSer
226227
static class AuthorizationServerConfiguration {
227228

228229
@Bean
229-
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
230+
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations, PasswordEncoder passwordEncoder) {
230231
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
232+
RegisteredClientParametersMapper registeredClientParametersMapper = new RegisteredClientParametersMapper();
233+
registeredClientParametersMapper.setPasswordEncoder(passwordEncoder);
231234
JdbcRegisteredClientRepository registeredClientRepository = new JdbcRegisteredClientRepository(jdbcOperations);
235+
registeredClientRepository.setRegisteredClientParametersMapper(registeredClientParametersMapper);
232236
registeredClientRepository.save(registeredClient);
233237
return registeredClientRepository;
234238
}

oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OidcTests.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
7474
import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer;
7575
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
76+
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository.RegisteredClientParametersMapper;
7677
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
7778
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
7879
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
@@ -275,8 +276,12 @@ OAuth2AuthorizationService authorizationService(JdbcOperations jdbcOperations, R
275276
}
276277

277278
@Bean
278-
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
279-
return new JdbcRegisteredClientRepository(jdbcOperations);
279+
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations, PasswordEncoder passwordEncoder) {
280+
JdbcRegisteredClientRepository jdbcRegisteredClientRepository = new JdbcRegisteredClientRepository(jdbcOperations);
281+
RegisteredClientParametersMapper registeredClientParametersMapper = new RegisteredClientParametersMapper();
282+
registeredClientParametersMapper.setPasswordEncoder(passwordEncoder);
283+
jdbcRegisteredClientRepository.setRegisteredClientParametersMapper(registeredClientParametersMapper);
284+
return jdbcRegisteredClientRepository;
280285
}
281286

282287
@Bean

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

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,13 @@
4040
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
4141
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
4242
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
43+
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
44+
import org.springframework.security.crypto.password.PasswordEncoder;
4345
import org.springframework.security.jackson2.SecurityJackson2Modules;
4446
import org.springframework.security.oauth2.core.AuthorizationGrantType;
4547
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
48+
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository.RegisteredClientParametersMapper;
49+
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository.RegisteredClientRowMapper;
4650
import org.springframework.security.oauth2.server.authorization.config.ClientSettings;
4751
import org.springframework.security.oauth2.server.authorization.config.TokenSettings;
4852
import org.springframework.security.oauth2.server.authorization.jackson2.OAuth2AuthorizationServerJackson2Module;
@@ -52,7 +56,9 @@
5256
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
5357
import static org.mockito.ArgumentMatchers.any;
5458
import static org.mockito.ArgumentMatchers.anyInt;
59+
import static org.mockito.ArgumentMatchers.anyString;
5560
import static org.mockito.Mockito.spy;
61+
import static org.mockito.Mockito.times;
5662
import static org.mockito.Mockito.verify;
5763

5864
/**
@@ -69,12 +75,27 @@ public class JdbcRegisteredClientRepositoryTests {
6975
private EmbeddedDatabase db;
7076
private JdbcOperations jdbcOperations;
7177
private JdbcRegisteredClientRepository registeredClientRepository;
78+
private PasswordEncoder passwordEncoder;
7279

7380
@Before
7481
public void setUp() {
7582
this.db = createDb(OAUTH2_REGISTERED_CLIENT_SCHEMA_SQL_RESOURCE);
7683
this.jdbcOperations = new JdbcTemplate(this.db);
7784
this.registeredClientRepository = new JdbcRegisteredClientRepository(this.jdbcOperations);
85+
this.passwordEncoder = spy(new PasswordEncoder() {
86+
@Override
87+
public String encode(CharSequence rawPassword) {
88+
return NoOpPasswordEncoder.getInstance().encode(rawPassword);
89+
}
90+
91+
@Override
92+
public boolean matches(CharSequence rawPassword, String encodedPassword) {
93+
return NoOpPasswordEncoder.getInstance().matches(rawPassword, encodedPassword);
94+
}
95+
});
96+
RegisteredClientParametersMapper registeredClientParametersMapper = new RegisteredClientParametersMapper();
97+
registeredClientParametersMapper.setPasswordEncoder(this.passwordEncoder);
98+
this.registeredClientRepository.setRegisteredClientParametersMapper(registeredClientParametersMapper);
7899
}
79100

80101
@After
@@ -144,15 +165,28 @@ public void saveWhenNewThenSaved() {
144165
this.registeredClientRepository.save(expectedRegisteredClient);
145166
RegisteredClient registeredClient = this.registeredClientRepository.findById(expectedRegisteredClient.getId());
146167
assertThat(registeredClient).isEqualTo(expectedRegisteredClient);
168+
verify(this.passwordEncoder).encode(anyString());
169+
}
170+
171+
@Test
172+
public void saveWhenClientSecretNullThenSaved() {
173+
RegisteredClient expectedRegisteredClient = TestRegisteredClients.registeredClient()
174+
.clientSecret(null).build();
175+
this.registeredClientRepository.save(expectedRegisteredClient);
176+
RegisteredClient registeredClient = this.registeredClientRepository.findById(expectedRegisteredClient.getId());
177+
assertThat(registeredClient).isEqualTo(expectedRegisteredClient);
178+
verify(this.passwordEncoder, times(0)).encode(anyString());
147179
}
148180

149181
@Test
150182
public void saveLoadRegisteredClientWhenCustomStrategiesSetThenCalled() throws Exception {
151183
RowMapper<RegisteredClient> registeredClientRowMapper = spy(
152-
new JdbcRegisteredClientRepository.RegisteredClientRowMapper());
184+
new RegisteredClientRowMapper());
153185
this.registeredClientRepository.setRegisteredClientRowMapper(registeredClientRowMapper);
186+
RegisteredClientParametersMapper clientParametersMapper = new RegisteredClientParametersMapper();
187+
clientParametersMapper.setPasswordEncoder(this.passwordEncoder);
154188
Function<RegisteredClient, List<SqlParameterValue>> registeredClientParametersMapper = spy(
155-
new JdbcRegisteredClientRepository.RegisteredClientParametersMapper());
189+
clientParametersMapper);
156190
this.registeredClientRepository.setRegisteredClientParametersMapper(registeredClientParametersMapper);
157191

158192
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
@@ -161,6 +195,7 @@ public void saveLoadRegisteredClientWhenCustomStrategiesSetThenCalled() throws E
161195
assertThat(result).isEqualTo(registeredClient);
162196
verify(registeredClientRowMapper).mapRow(any(), anyInt());
163197
verify(registeredClientParametersMapper).apply(any());
198+
verify(this.passwordEncoder).encode(anyString());
164199
}
165200

166201
@Test
@@ -212,14 +247,17 @@ public void findByClientIdWhenNotExistsThenNotFound() {
212247
@Test
213248
public void tableDefinitionWhenCustomThenAbleToOverride() {
214249
EmbeddedDatabase db = createDb(OAUTH2_CUSTOM_REGISTERED_CLIENT_SCHEMA_SQL_RESOURCE);
215-
RegisteredClientRepository registeredClientRepository =
216-
new CustomJdbcRegisteredClientRepository(new JdbcTemplate(db));
250+
RegisteredClientParametersMapper registeredClientParametersMapper = new RegisteredClientParametersMapper();
251+
registeredClientParametersMapper.setPasswordEncoder(this.passwordEncoder);
252+
CustomJdbcRegisteredClientRepository registeredClientRepository = new CustomJdbcRegisteredClientRepository(new JdbcTemplate(db));
253+
registeredClientRepository.setRegisteredClientParametersMapper(registeredClientParametersMapper);
217254
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
218255
registeredClientRepository.save(registeredClient);
219256
RegisteredClient foundRegisteredClient1 = registeredClientRepository.findById(registeredClient.getId());
220257
assertThat(foundRegisteredClient1).isEqualTo(registeredClient);
221258
RegisteredClient foundRegisteredClient2 = registeredClientRepository.findByClientId(registeredClient.getClientId());
222259
assertThat(foundRegisteredClient2).isEqualTo(registeredClient);
260+
verify(this.passwordEncoder).encode(anyString());
223261
db.shutdown();
224262
}
225263

0 commit comments

Comments
 (0)