Browse Source

JDBC implementation of RegisteredClientRepository

Closes gh-265
pull/321/head
Rafal Lewczuk 5 years ago committed by Steve Riesenberg
parent
commit
769cf8fac7
  1. 335
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/client/JdbcRegisteredClientRepository.java
  2. 14
      oauth2-authorization-server/src/main/resources/org/springframework/security/oauth2/server/authorization/client/oauth2_registered_client.sql
  3. 291
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/client/JdbcRegisteredClientRepositoryTests.java

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

@ -0,0 +1,335 @@ @@ -0,0 +1,335 @@
/*
* 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.client;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.jdbc.core.*;
import org.springframework.jdbc.support.lob.DefaultLobHandler;
import org.springframework.jdbc.support.lob.LobCreator;
import org.springframework.jdbc.support.lob.LobHandler;
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.util.Assert;
import java.nio.charset.StandardCharsets;
import java.sql.*;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* JDBC-backed registered client repository
*
* @author Rafal Lewczuk
* @since 0.1.2
*/
public class JdbcRegisteredClientRepository implements RegisteredClientRepository {
private static final Map<String, AuthorizationGrantType> AUTHORIZATION_GRANT_TYPE_MAP;
private static final Map<String, ClientAuthenticationMethod> CLIENT_AUTHENTICATION_METHOD_MAP;
private static final String COLUMN_NAMES = "id, "
+ "client_id, "
+ "client_id_issued_at, "
+ "client_secret, "
+ "client_secret_expires_at, "
+ "client_name, "
+ "client_authentication_methods, "
+ "authorization_grant_types, "
+ "redirect_uris, "
+ "scopes, "
+ "client_settings,"
+ "token_settings";
private static final String TABLE_NAME = "oauth2_registered_client";
private static final String LOAD_REGISTERED_CLIENT_SQL = "SELECT " + COLUMN_NAMES + " FROM " + TABLE_NAME + " WHERE ";
private static final String INSERT_REGISTERED_CLIENT_SQL = "INSERT INTO " + TABLE_NAME
+ "(" + COLUMN_NAMES + ") values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
private RowMapper<RegisteredClient> registeredClientRowMapper;
private Function<RegisteredClient, List<SqlParameterValue>> registeredClientParametersMapper;
private final JdbcOperations jdbcOperations;
private final LobHandler lobHandler = new DefaultLobHandler();
private final ObjectMapper objectMapper;
public JdbcRegisteredClientRepository(JdbcOperations jdbcOperations, ObjectMapper objectMapper) {
Assert.notNull(jdbcOperations, "jdbcOperations cannot be null");
Assert.notNull(objectMapper, "objectMapper cannot be null");
this.jdbcOperations = jdbcOperations;
this.objectMapper = objectMapper;
this.registeredClientRowMapper = new DefaultRegisteredClientRowMapper();
this.registeredClientParametersMapper = new DefaultRegisteredClientParametersMapper();
}
/**
* Allows changing of {@link RegisteredClient} row mapper implementation
*
* @param registeredClientRowMapper mapper implementation
*/
public void setRegisteredClientRowMapper(RowMapper<RegisteredClient> registeredClientRowMapper) {
Assert.notNull(registeredClientRowMapper, "registeredClientRowMapper cannot be null");
this.registeredClientRowMapper = registeredClientRowMapper;
}
/**
* Allows changing of SQL parameter mapper for {@link RegisteredClient}
*
* @param registeredClientParametersMapper mapper implementation
*/
public void setRegisteredClientParametersMapper(Function<RegisteredClient, List<SqlParameterValue>> registeredClientParametersMapper) {
Assert.notNull(registeredClientParametersMapper, "registeredClientParameterMapper cannot be null");
this.registeredClientParametersMapper = registeredClientParametersMapper;
}
@Override
public void save(RegisteredClient registeredClient) {
Assert.notNull(registeredClient, "registeredClient cannot be null");
RegisteredClient foundClient = this.findBy("id = ? OR client_id = ? OR client_secret = ?",
registeredClient.getId(), registeredClient.getClientId(),
registeredClient.getClientSecret().getBytes(StandardCharsets.UTF_8));
if (null != foundClient) {
Assert.isTrue(!foundClient.getId().equals(registeredClient.getId()),
"Registered client must be unique. Found duplicate identifier: " + registeredClient.getId());
Assert.isTrue(!foundClient.getClientId().equals(registeredClient.getClientId()),
"Registered client must be unique. Found duplicate client identifier: " + registeredClient.getClientId());
Assert.isTrue(!foundClient.getClientSecret().equals(registeredClient.getClientSecret()),
"Registered client must be unique. Found duplicate client secret for identifier: " + registeredClient.getId());
}
List<SqlParameterValue> parameters = this.registeredClientParametersMapper.apply(registeredClient);
try (LobCreator lobCreator = this.lobHandler.getLobCreator()) {
PreparedStatementSetter pss = new LobCreatorArgumentPreparedStatementSetter(lobCreator, parameters.toArray());
jdbcOperations.update(INSERT_REGISTERED_CLIENT_SQL, pss);
}
}
@Override
public RegisteredClient findById(String id) {
Assert.hasText(id, "id cannot be empty");
return findBy("id = ?", id);
}
@Override
public RegisteredClient findByClientId(String clientId) {
Assert.hasText(clientId, "clientId cannot be empty");
return findBy("client_id = ?", clientId);
}
private RegisteredClient findBy(String condStr, Object...args) {
List<RegisteredClient> lst = jdbcOperations.query(
LOAD_REGISTERED_CLIENT_SQL + condStr,
registeredClientRowMapper, args);
return !lst.isEmpty() ? lst.get(0) : null;
}
private class DefaultRegisteredClientRowMapper implements RowMapper<RegisteredClient> {
private final LobHandler lobHandler = new DefaultLobHandler();
private Collection<String> parseList(String s) {
return s != null ? Arrays.asList(s.split("\\|")) : Collections.emptyList();
}
@Override
@SuppressWarnings("unchecked")
public RegisteredClient mapRow(ResultSet rs, int rowNum) throws SQLException {
Collection<String> scopes = parseList(rs.getString("scopes"));
List<AuthorizationGrantType> authGrantTypes = parseList(rs.getString("authorization_grant_types"))
.stream().map(AUTHORIZATION_GRANT_TYPE_MAP::get).collect(Collectors.toList());
List<ClientAuthenticationMethod> clientAuthMethods = parseList(rs.getString("client_authentication_methods"))
.stream().map(CLIENT_AUTHENTICATION_METHOD_MAP::get).collect(Collectors.toList());
Collection<String> redirectUris = parseList(rs.getString("redirect_uris"));
Timestamp clientIssuedAt = rs.getTimestamp("client_id_issued_at");
Timestamp clientSecretExpiresAt = rs.getTimestamp("client_secret_expires_at");
byte[] clientSecretBytes = this.lobHandler.getBlobAsBytes(rs, "client_secret");
String clientSecret = clientSecretBytes != null ? new String(clientSecretBytes, StandardCharsets.UTF_8) : null;
RegisteredClient.Builder builder = RegisteredClient
.withId(rs.getString("id"))
.clientId(rs.getString("client_id"))
.clientIdIssuedAt(clientIssuedAt != null ? clientIssuedAt.toInstant() : null)
.clientSecret(clientSecret)
.clientSecretExpiresAt(clientSecretExpiresAt != null ? clientSecretExpiresAt.toInstant() : null)
.clientName(rs.getString("client_name"))
.clientAuthenticationMethods(coll -> coll.addAll(clientAuthMethods))
.authorizationGrantTypes(coll -> coll.addAll(authGrantTypes))
.redirectUris(coll -> coll.addAll(redirectUris))
.scopes(coll -> coll.addAll(scopes));
RegisteredClient rc = builder.build();
TokenSettings ts = rc.getTokenSettings();
ClientSettings cs = rc.getClientSettings();
try {
String tokenSettingsJson = rs.getString("token_settings");
if (tokenSettingsJson != null) {
Map<String, Object> m = JdbcRegisteredClientRepository.this.objectMapper.readValue(tokenSettingsJson, Map.class);
Number accessTokenTTL = (Number) m.get("access_token_ttl");
if (accessTokenTTL != null) {
ts.accessTokenTimeToLive(Duration.ofMillis(accessTokenTTL.longValue()));
}
Number refreshTokenTTL = (Number) m.get("refresh_token_ttl");
if (refreshTokenTTL != null) {
ts.refreshTokenTimeToLive(Duration.ofMillis(refreshTokenTTL.longValue()));
}
Boolean reuseRefreshTokens = (Boolean) m.get("reuse_refresh_tokens");
if (reuseRefreshTokens != null) {
ts.reuseRefreshTokens(reuseRefreshTokens);
}
}
String clientSettingsJson = rs.getString("client_settings");
if (clientSettingsJson != null) {
Map<String, Object> m = JdbcRegisteredClientRepository.this.objectMapper.readValue(clientSettingsJson, Map.class);
Boolean requireProofKey = (Boolean) m.get("require_proof_key");
if (requireProofKey != null) {
cs.requireProofKey(requireProofKey);
}
Boolean requireUserConsent = (Boolean) m.get("require_user_consent");
if (requireUserConsent != null) {
cs.requireUserConsent(requireUserConsent);
}
}
} catch (JsonProcessingException e) {
throw new IllegalArgumentException(e.getMessage(), e);
}
return rc;
}
}
private class DefaultRegisteredClientParametersMapper implements Function<RegisteredClient, List<SqlParameterValue>> {
@Override
public List<SqlParameterValue> apply(RegisteredClient registeredClient) {
try {
List<String> clientAuthenticationMethodNames = new ArrayList<>(registeredClient.getClientAuthenticationMethods().size());
for (ClientAuthenticationMethod clientAuthenticationMethod : registeredClient.getClientAuthenticationMethods()) {
clientAuthenticationMethodNames.add(clientAuthenticationMethod.getValue());
}
List<String> authorizationGrantTypeNames = new ArrayList<>(registeredClient.getAuthorizationGrantTypes().size());
for (AuthorizationGrantType authorizationGrantType : registeredClient.getAuthorizationGrantTypes()) {
authorizationGrantTypeNames.add(authorizationGrantType.getValue());
}
Instant issuedAt = registeredClient.getClientIdIssuedAt() != null ?
registeredClient.getClientIdIssuedAt() : Instant.now();
Timestamp clientSecretExpiresAt = registeredClient.getClientSecretExpiresAt() != null ?
Timestamp.from(registeredClient.getClientSecretExpiresAt()) : null;
Map<String, Object> clientSettings = new HashMap<>();
clientSettings.put("require_proof_key", registeredClient.getClientSettings().requireProofKey());
clientSettings.put("require_user_consent", registeredClient.getClientSettings().requireUserConsent());
String clientSettingsJson = JdbcRegisteredClientRepository.this.objectMapper.writeValueAsString(clientSettings);
Map<String, Object> tokenSettings = new HashMap<>();
tokenSettings.put("access_token_ttl", registeredClient.getTokenSettings().accessTokenTimeToLive().toMillis());
tokenSettings.put("reuse_refresh_tokens", registeredClient.getTokenSettings().reuseRefreshTokens());
tokenSettings.put("refresh_token_ttl", registeredClient.getTokenSettings().refreshTokenTimeToLive().toMillis());
String tokenSettingsJson = JdbcRegisteredClientRepository.this.objectMapper.writeValueAsString(tokenSettings);
return Arrays.asList(
new SqlParameterValue(Types.VARCHAR, registeredClient.getId()),
new SqlParameterValue(Types.VARCHAR, registeredClient.getClientId()),
new SqlParameterValue(Types.TIMESTAMP, Timestamp.from(issuedAt)),
new SqlParameterValue(Types.BLOB, registeredClient.getClientSecret().getBytes(StandardCharsets.UTF_8)),
new SqlParameterValue(Types.TIMESTAMP, clientSecretExpiresAt),
new SqlParameterValue(Types.VARCHAR, registeredClient.getClientName()),
new SqlParameterValue(Types.VARCHAR, String.join("|", clientAuthenticationMethodNames)),
new SqlParameterValue(Types.VARCHAR, String.join("|", authorizationGrantTypeNames)),
new SqlParameterValue(Types.VARCHAR, String.join("|", registeredClient.getRedirectUris())),
new SqlParameterValue(Types.VARCHAR, String.join("|", registeredClient.getScopes())),
new SqlParameterValue(Types.VARCHAR, clientSettingsJson),
new SqlParameterValue(Types.VARCHAR, tokenSettingsJson));
} catch (JsonProcessingException e) {
throw new IllegalArgumentException(e.getMessage(), e);
}
}
}
private static final class LobCreatorArgumentPreparedStatementSetter extends ArgumentPreparedStatementSetter {
protected final LobCreator lobCreator;
private LobCreatorArgumentPreparedStatementSetter(LobCreator lobCreator, Object[] args) {
super(args);
this.lobCreator = lobCreator;
}
@Override
protected void doSetValue(PreparedStatement ps, int parameterPosition, Object argValue) throws SQLException {
if (argValue instanceof SqlParameterValue) {
SqlParameterValue paramValue = (SqlParameterValue) argValue;
if (paramValue.getSqlType() == Types.BLOB) {
if (paramValue.getValue() != null) {
Assert.isInstanceOf(byte[].class, paramValue.getValue(),
"Value of blob parameter must be byte[]");
}
byte[] valueBytes = (byte[]) paramValue.getValue();
this.lobCreator.setBlobAsBytes(ps, parameterPosition, valueBytes);
return;
}
}
super.doSetValue(ps, parameterPosition, argValue);
}
}
static {
Map<String, AuthorizationGrantType> am = new HashMap<>();
for (AuthorizationGrantType a : Arrays.asList(
AuthorizationGrantType.AUTHORIZATION_CODE,
AuthorizationGrantType.REFRESH_TOKEN,
AuthorizationGrantType.CLIENT_CREDENTIALS,
AuthorizationGrantType.PASSWORD,
AuthorizationGrantType.IMPLICIT)) {
am.put(a.getValue(), a);
}
AUTHORIZATION_GRANT_TYPE_MAP = Collections.unmodifiableMap(am);
Map<String, ClientAuthenticationMethod> cm = new HashMap<>();
for (ClientAuthenticationMethod c : Arrays.asList(
ClientAuthenticationMethod.NONE,
ClientAuthenticationMethod.BASIC,
ClientAuthenticationMethod.POST)) {
cm.put(c.getValue(), c);
}
CLIENT_AUTHENTICATION_METHOD_MAP = Collections.unmodifiableMap(cm);
}
}

14
oauth2-authorization-server/src/main/resources/org/springframework/security/oauth2/server/authorization/client/oauth2_registered_client.sql

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
CREATE TABLE oauth2_registered_client (
id varchar(100) NOT NULL,
client_id varchar(100) NOT NULL,
client_id_issued_at timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL,
client_secret blob NOT NULL,
client_secret_expires_at timestamp DEFAULT NULL,
client_name varchar(200),
client_authentication_methods varchar(1000) NOT NULL,
authorization_grant_types varchar(1000) NOT NULL,
redirect_uris varchar(1000) NOT NULL,
scopes varchar(1000) NOT NULL,
client_settings varchar(1000) DEFAULT NULL,
token_settings varchar(1000) DEFAULT NULL,
PRIMARY KEY (id));

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

@ -0,0 +1,291 @@ @@ -0,0 +1,291 @@
/*
* 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.client;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.util.StreamUtils;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.time.Duration;
import java.time.Instant;
import static org.assertj.core.api.Assertions.*;
/**
* JDBC-backed registered client repository tests
*
* @author Rafal Lewczuk
* @since 0.1.2
*/
public class JdbcRegisteredClientRepositoryTests {
private final String SCRIPT = "/org/springframework/security/oauth2/server/authorization/client/oauth2_registered_client.sql";
private DriverManagerDataSource dataSource;
private JdbcRegisteredClientRepository clients;
private RegisteredClient registration;
private JdbcTemplate jdbc;
@Before
public void setup() throws Exception {
this.dataSource = new DriverManagerDataSource();
this.dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
this.dataSource.setUrl("jdbc:hsqldb:mem:oauthtest");
this.dataSource.setUsername("sa");
this.dataSource.setPassword("");
this.jdbc = new JdbcTemplate(this.dataSource);
// execute scripts
try (InputStream is = JdbcRegisteredClientRepositoryTests.class.getResourceAsStream(SCRIPT)) {
assertThat(is).isNotNull().describedAs("Cannot open resource file: " + SCRIPT);
String ddls = StreamUtils.copyToString(is, Charset.defaultCharset());
for (String ddl : ddls.split(";\n")) {
if (!ddl.trim().isEmpty()) {
this.jdbc.execute(ddl.trim());
}
}
}
this.clients = new JdbcRegisteredClientRepository(this.jdbc, new ObjectMapper());
this.registration = TestRegisteredClients.registeredClient().build();
this.clients.save(this.registration);
}
@After
public void destroyDatabase() {
this.jdbc.update("truncate table oauth2_registered_client");
new JdbcTemplate(this.dataSource).execute("SHUTDOWN");
}
@Test
public void whenJdbcOperationsNullThenThrow() {
// @formatter:off
assertThatIllegalArgumentException()
.isThrownBy(() -> new JdbcRegisteredClientRepository(null, new ObjectMapper()))
.withMessage("jdbcOperations cannot be null");
// @formatter:on
}
@Test
public void whenObjectMapperNullThenThrow() {
// @formatter:off
assertThatIllegalArgumentException()
.isThrownBy(() -> new JdbcRegisteredClientRepository(this.jdbc, null))
.withMessage("objectMapper cannot be null");
// @formatter:on
}
@Test
public void whenSetNullRegisteredClientRowMapperThenThrow() {
// @formatter:off
assertThatIllegalArgumentException()
.isThrownBy(() -> this.clients.setRegisteredClientRowMapper(null))
.withMessage("registeredClientRowMapper cannot be null");
// @formatter:on
}
@Test
public void whenSetNullRegisteredClientParameterMapperThenThrow() {
// @formatter:off
assertThatIllegalArgumentException()
.isThrownBy(() -> this.clients.setRegisteredClientParametersMapper(null))
.withMessage("registeredClientParameterMapper cannot be null");
// @formatter:on
}
@Test
public void findByIdWhenFoundThenFound() {
String id = this.registration.getId();
assertRegisteredClientIsEqualTo(this.clients.findById(id), this.registration);
}
@Test
public void findByIdWhenNotFoundThenNull() {
RegisteredClient client = this.clients.findById("noooope");
assertThat(client).isNull();
}
@Test
public void findByIdWhenNullThenThrowIllegalArgumentException() {
// @formatter:off
assertThatIllegalArgumentException()
.isThrownBy(() -> this.clients.findById(null))
.withMessage("id cannot be empty");
// @formatter:on
}
@Test
public void findByClientIdWhenFoundThenFound() {
String id = this.registration.getClientId();
assertRegisteredClientIsEqualTo(this.clients.findByClientId(id), this.registration);
}
@Test
public void findByClientIdWhenNotFoundThenNull() {
RegisteredClient client = this.clients.findByClientId("noooope");
assertThat(client).isNull();
}
@Test
public void findByClientIdWhenNullThenThrowIllegalArgumentException() {
// @formatter:off
assertThatIllegalArgumentException()
.isThrownBy(() -> this.clients.findByClientId(null))
.withMessage("clientId cannot be empty");
// @formatter:on
}
@Test
public void saveWhenNullThenThrowIllegalArgumentException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.clients.save(null))
.withMessageContaining("registeredClient cannot be null");
}
@Test
public void saveWhenExistingIdThenThrowIllegalArgumentException() {
RegisteredClient registeredClient = createRegisteredClient(
this.registration.getId(), "client-id-2", "client-secret-2");
assertThatIllegalArgumentException()
.isThrownBy(() -> this.clients.save(registeredClient))
.withMessage("Registered client must be unique. Found duplicate identifier: " + registeredClient.getId());
}
@Test
public void saveWhenExistingClientIdThenThrowIllegalArgumentException() {
RegisteredClient registeredClient = createRegisteredClient(
"client-2", this.registration.getClientId(), "client-secret-2");
assertThatIllegalArgumentException()
.isThrownBy(() -> this.clients.save(registeredClient))
.withMessage("Registered client must be unique. Found duplicate client identifier: " + registeredClient.getClientId());
}
@Test
public void saveWhenExistingClientSecretThenThrowIllegalArgumentException() {
RegisteredClient registeredClient = createRegisteredClient(
"client-2", "client-id-2", this.registration.getClientSecret());
assertThatIllegalArgumentException()
.isThrownBy(() -> this.clients.save(registeredClient))
.withMessage("Registered client must be unique. Found duplicate client secret for identifier: " + registeredClient.getId());
}
@Test
public void saveWhenSavedAndFindByIdThenFound() {
RegisteredClient registeredClient = createRegisteredClient();
this.clients.save(registeredClient);
RegisteredClient savedClient = this.clients.findById(registeredClient.getId());
assertRegisteredClientIsEqualTo(savedClient, registeredClient);
}
@Test
public void saveWhenSavedAndFindByClientIdThenFound() {
RegisteredClient registeredClient = createRegisteredClient();
this.clients.save(registeredClient);
RegisteredClient savedClient = this.clients.findByClientId(registeredClient.getClientId());
assertRegisteredClientIsEqualTo(savedClient, registeredClient);
}
@Test
public void whenSaveRegistrationWithAllAttrsThenSaved() {
Instant issuedAt = Instant.now(), expiresAt = issuedAt.plus(Duration.ofDays(30));
RegisteredClient client = TestRegisteredClients.registeredClient2()
.clientIdIssuedAt(issuedAt)
.clientSecretExpiresAt(expiresAt)
.clientSecret("secret2")
.clientName("some_client_name")
.redirectUri("https://example2.com")
.clientSettings(cs -> {
cs.requireProofKey(true);
cs.requireUserConsent(true);
})
.tokenSettings(ts -> {
ts.accessTokenTimeToLive(Duration.ofMinutes(3));
ts.reuseRefreshTokens(true);
ts.refreshTokenTimeToLive(Duration.ofMinutes(300));
})
.build();
this.clients.save(client);
RegisteredClient retrievedClient = this.clients.findById(client.getId());
assertRegisteredClientIsEqualTo(retrievedClient, client);
}
private void assertRegisteredClientIsEqualTo(RegisteredClient rc, RegisteredClient ref) {
assertThat(rc).isNotNull();
assertThat(rc.getId()).isEqualTo(ref.getId());
assertThat(rc.getClientId()).isEqualTo(ref.getClientId());
if (ref.getClientIdIssuedAt() != null) {
// This can be set to default value
Instant inst = ref.getClientIdIssuedAt();
assertThat(rc.getClientIdIssuedAt()).isBetween(inst.minusMillis(1), inst.plusMillis(1));
}
assertThat(rc.getClientSecret()).isEqualTo(ref.getClientSecret());
if (ref.getClientSecretExpiresAt() != null) {
Instant inst = ref.getClientSecretExpiresAt();
assertThat(rc.getClientSecretExpiresAt()).isBetween(inst.minusMillis(1), inst.plusMillis(1));
} else {
assertThat(rc.getClientSecretExpiresAt()).isNull();
}
assertThat(rc.getClientName()).isEqualTo(ref.getClientName());
assertThat(rc.getClientAuthenticationMethods()).isEqualTo(ref.getClientAuthenticationMethods());
assertThat(rc.getAuthorizationGrantTypes()).isEqualTo(ref.getAuthorizationGrantTypes());
assertThat(rc.getRedirectUris()).isEqualTo(ref.getRedirectUris());
assertThat(rc.getScopes()).isEqualTo(ref.getScopes());
assertThat(rc.getClientSettings().requireUserConsent()).isEqualTo(ref.getClientSettings().requireUserConsent());
assertThat(rc.getClientSettings().requireProofKey()).isEqualTo(ref.getClientSettings().requireProofKey());
assertThat(rc.getTokenSettings().reuseRefreshTokens()).isEqualTo(ref.getTokenSettings().reuseRefreshTokens());
assertThat(rc.getTokenSettings().accessTokenTimeToLive()).isEqualTo(ref.getTokenSettings().accessTokenTimeToLive());
assertThat(rc.getTokenSettings().refreshTokenTimeToLive()).isEqualTo(ref.getTokenSettings().refreshTokenTimeToLive());
}
private static RegisteredClient createRegisteredClient() {
return createRegisteredClient("client-2", "client-id-2", "client-secret-2");
}
private static RegisteredClient createRegisteredClient(String id, String clientId, String clientSecret) {
// @formatter:off
return RegisteredClient.withId(id)
.clientId(clientId)
.clientSecret(clientSecret)
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.clientAuthenticationMethod(ClientAuthenticationMethod.BASIC)
.redirectUri("https://client.example.com")
.scope("scope1")
.build();
// @formatter:on
}
}
Loading…
Cancel
Save