Description
Expected Behavior
The RegisteredClientRepository
should have the ability to change the client secret of an existing client.
Current Behavior
In version 0.2.1 the ability was removed because in prior versions the secret was encoded twice. The Bug and PR are reported in issue #389.
Context
I have a adminstration UI for the clients where it should be possible to edit the secret without deleting and adding the client again especially because there is no delete method on default.
Solution Proposal
The following is a proposal of my solution which is based on the "old" authroization server where changing the client secret is an extra method.
public class CustomJdbcRegisteredClientRepository extends JdbcRegisteredClientRepository {
private final PasswordEncoder passwordEncoder;
private static final String TABLE_NAME = "oauth2_registered_client";
private static final String PK_FILTER = "id = ?";
// @formatter:off
private static final String UPDATE_REGISTERED_CLIENT_CLIENT_SECRET_SQL = "UPDATE " + TABLE_NAME
+ " SET client_secret = ?, client_secret_expires_at = ?,"
+ " WHERE " + PK_FILTER;
// @formatter:on
public CustomJdbcRegisteredClientRepository(JdbcOperations jdbcOperations, PasswordEncoder passwordEncoder) {
super(jdbcOperations);
this.passwordEncoder = passwordEncoder;
}
public void updateRegisteredClientClientSecret(String newClientSecret, Instant newClientSecretExpiresAt, String id) {
Timestamp clientSecretExpiresAt = newClientSecretExpiresAt != null ?
Timestamp.from(newClientSecretExpiresAt) : null;
String encodedClientSecret = passwordEncoder.encode(newClientSecret);
List<SqlParameterValue> parameters = Arrays.asList(
new SqlParameterValue(Types.VARCHAR, encodedClientSecret),
new SqlParameterValue(Types.TIMESTAMP, clientSecretExpiresAt),
new SqlParameterValue(Types.VARCHAR, id)
);
PreparedStatementSetter pss = new ArgumentPreparedStatementSetter(parameters.toArray());
getJdbcOperations().update(UPDATE_REGISTERED_CLIENT_CLIENT_SECRET_SQL, pss);
}
}
As you can see the secret will be encoded in this solution. If its already encoded it will be encoded twice. But, because this is an extra method the calling method can decide to not call it.
Example of usage:
private final CustomJdbcRegisteredClientRepository clientRegistrationService;
...
public void updateClient(RegisteredClient updatedClient) {
clientRegistrationService.save(updatedClient);
RegisteredClient existingRegisteredClient = clientRegistrationService.findByClientId(updatedClient.getClientId()));
if (!Objects.equals(updatedClient.getClientSecret(), existingRegisteredClient.getClientSecret())) {
clientRegistrationService.updateRegisteredClientClientSecret(updatedClient.getClientSecret(), null, existingRegisteredClient.getId());
}
}
Whould be nice if something like that will be in one of the further implementations.