Merge pull request #2 from gresham-computing/client-secret-security
DWN-27040: Changes when the client secret is given to the UIpull/1601/head
commit
12f91b1901
|
@ -150,12 +150,16 @@ public class DefaultOAuth2ClientDetailsEntityService implements ClientDetailsEnt
|
||||||
|
|
||||||
ensureNoReservedScopes(client);
|
ensureNoReservedScopes(client);
|
||||||
|
|
||||||
|
String plaintextSecret = client.getClientSecret();
|
||||||
|
|
||||||
if(!Strings.isNullOrEmpty(client.getClientSecret())) {
|
if(!Strings.isNullOrEmpty(client.getClientSecret())) {
|
||||||
client.setClientSecret(this.passwordEncoder.encode(client.getClientSecret()));
|
client.setClientSecret(this.passwordEncoder.encode(client.getClientSecret()));
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientDetailsEntity c = clientRepository.saveClient(client);
|
ClientDetailsEntity c = clientRepository.saveClient(client);
|
||||||
|
|
||||||
|
c.setClientSecret(plaintextSecret);
|
||||||
|
|
||||||
statsService.resetCache();
|
statsService.resetCache();
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
|
@ -432,9 +436,11 @@ public class DefaultOAuth2ClientDetailsEntityService implements ClientDetailsEnt
|
||||||
// make sure a client doesn't get any special system scopes
|
// make sure a client doesn't get any special system scopes
|
||||||
ensureNoReservedScopes(newClient);
|
ensureNoReservedScopes(newClient);
|
||||||
|
|
||||||
if(!Strings.isNullOrEmpty(newClient.getClientSecret())) {
|
if (Strings.isNullOrEmpty(newClient.getClientSecret())){
|
||||||
|
newClient.setClientSecret(oldClient.getClientSecret());
|
||||||
|
}else{
|
||||||
newClient.setClientSecret(this.passwordEncoder.encode(newClient.getClientSecret()));
|
newClient.setClientSecret(this.passwordEncoder.encode(newClient.getClientSecret()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return clientRepository.updateClient(oldClient.getId(), newClient);
|
return clientRepository.updateClient(oldClient.getId(), newClient);
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,6 +229,9 @@ public class ClientAPI {
|
||||||
public String apiGetAllClients(Model model, Authentication auth) {
|
public String apiGetAllClients(Model model, Authentication auth) {
|
||||||
|
|
||||||
Collection<ClientDetailsEntity> clients = clientService.getAllClients();
|
Collection<ClientDetailsEntity> clients = clientService.getAllClients();
|
||||||
|
|
||||||
|
clients.forEach(client -> client.setClientSecret(null));
|
||||||
|
|
||||||
model.addAttribute(JsonEntityView.ENTITY, clients);
|
model.addAttribute(JsonEntityView.ENTITY, clients);
|
||||||
|
|
||||||
if (AuthenticationUtilities.isAdmin(auth)) {
|
if (AuthenticationUtilities.isAdmin(auth)) {
|
||||||
|
@ -320,6 +323,8 @@ public class ClientAPI {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ClientDetailsEntity newClient = clientService.saveNewClient(client);
|
ClientDetailsEntity newClient = clientService.saveNewClient(client);
|
||||||
|
|
||||||
|
//Set the client secret to the plaintext from the request
|
||||||
m.addAttribute(JsonEntityView.ENTITY, newClient);
|
m.addAttribute(JsonEntityView.ENTITY, newClient);
|
||||||
|
|
||||||
if (AuthenticationUtilities.isAdmin(auth)) {
|
if (AuthenticationUtilities.isAdmin(auth)) {
|
||||||
|
@ -385,6 +390,7 @@ public class ClientAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientDetailsEntity oldClient = clientService.getClientById(id);
|
ClientDetailsEntity oldClient = clientService.getClientById(id);
|
||||||
|
String plaintextSecret = client.getClientSecret();
|
||||||
|
|
||||||
if (oldClient == null) {
|
if (oldClient == null) {
|
||||||
logger.error("apiUpdateClient failed; client with id " + id + " could not be found.");
|
logger.error("apiUpdateClient failed; client with id " + id + " could not be found.");
|
||||||
|
@ -408,10 +414,10 @@ public class ClientAPI {
|
||||||
|| client.getTokenEndpointAuthMethod().equals(AuthMethod.SECRET_POST)
|
|| client.getTokenEndpointAuthMethod().equals(AuthMethod.SECRET_POST)
|
||||||
|| client.getTokenEndpointAuthMethod().equals(AuthMethod.SECRET_JWT)) {
|
|| client.getTokenEndpointAuthMethod().equals(AuthMethod.SECRET_JWT)) {
|
||||||
|
|
||||||
// if they've asked for us to generate a client secret (or they left it blank but require one), do so here
|
// Once a client has been created, we only update the secret when asked to
|
||||||
if (json.has("generateClientSecret") && json.get("generateClientSecret").getAsBoolean()
|
if (json.has("generateClientSecret") && json.get("generateClientSecret").getAsBoolean()) {
|
||||||
|| Strings.isNullOrEmpty(client.getClientSecret())) {
|
|
||||||
client = clientService.generateClientSecret(client);
|
client = clientService.generateClientSecret(client);
|
||||||
|
plaintextSecret = client.getClientSecret();
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (client.getTokenEndpointAuthMethod().equals(AuthMethod.PRIVATE_KEY)) {
|
} else if (client.getTokenEndpointAuthMethod().equals(AuthMethod.PRIVATE_KEY)) {
|
||||||
|
@ -438,6 +444,10 @@ public class ClientAPI {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ClientDetailsEntity newClient = clientService.updateClient(oldClient, client);
|
ClientDetailsEntity newClient = clientService.updateClient(oldClient, client);
|
||||||
|
|
||||||
|
//Set the client secret to the plaintext from the request
|
||||||
|
newClient.setClientSecret(plaintextSecret);
|
||||||
|
|
||||||
m.addAttribute(JsonEntityView.ENTITY, newClient);
|
m.addAttribute(JsonEntityView.ENTITY, newClient);
|
||||||
|
|
||||||
if (AuthenticationUtilities.isAdmin(auth)) {
|
if (AuthenticationUtilities.isAdmin(auth)) {
|
||||||
|
@ -497,6 +507,9 @@ public class ClientAPI {
|
||||||
return JsonErrorView.VIEWNAME;
|
return JsonErrorView.VIEWNAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//We don't want the UI to get the secret
|
||||||
|
client.setClientSecret(null);
|
||||||
|
|
||||||
model.addAttribute(JsonEntityView.ENTITY, client);
|
model.addAttribute(JsonEntityView.ENTITY, client);
|
||||||
|
|
||||||
if (AuthenticationUtilities.isAdmin(auth)) {
|
if (AuthenticationUtilities.isAdmin(auth)) {
|
||||||
|
|
|
@ -242,6 +242,7 @@ public class DynamicClientRegistrationEndpoint {
|
||||||
// send it all out to the view
|
// send it all out to the view
|
||||||
|
|
||||||
RegisteredClient registered = new RegisteredClient(savedClient, token.getValue(), config.getIssuer() + "register/" + UriUtils.encodePathSegment(savedClient.getClientId(), "UTF-8"));
|
RegisteredClient registered = new RegisteredClient(savedClient, token.getValue(), config.getIssuer() + "register/" + UriUtils.encodePathSegment(savedClient.getClientId(), "UTF-8"));
|
||||||
|
|
||||||
m.addAttribute("client", registered);
|
m.addAttribute("client", registered);
|
||||||
m.addAttribute(HttpCodeView.CODE, HttpStatus.CREATED); // http 201
|
m.addAttribute(HttpCodeView.CODE, HttpStatus.CREATED); // http 201
|
||||||
|
|
||||||
|
@ -377,6 +378,9 @@ public class DynamicClientRegistrationEndpoint {
|
||||||
|
|
||||||
RegisteredClient registered = new RegisteredClient(savedClient, token.getValue(), config.getIssuer() + "register/" + UriUtils.encodePathSegment(savedClient.getClientId(), "UTF-8"));
|
RegisteredClient registered = new RegisteredClient(savedClient, token.getValue(), config.getIssuer() + "register/" + UriUtils.encodePathSegment(savedClient.getClientId(), "UTF-8"));
|
||||||
|
|
||||||
|
// We don't want the UI to receive the client secret
|
||||||
|
registered.setClientSecret(null);
|
||||||
|
|
||||||
// send it all out to the view
|
// send it all out to the view
|
||||||
m.addAttribute("client", registered);
|
m.addAttribute("client", registered);
|
||||||
m.addAttribute(HttpCodeView.CODE, HttpStatus.OK); // http 200
|
m.addAttribute(HttpCodeView.CODE, HttpStatus.OK); // http 200
|
||||||
|
|
Loading…
Reference in New Issue