Using _system client when account client is disabled for email actions

Closes #17857

Signed-off-by: Giuseppe Graziano <g.graziano94@gmail.com>
This commit is contained in:
Giuseppe Graziano 2024-06-28 17:18:40 +02:00 committed by Alexander Schwartz
parent 20cedb84eb
commit 02d64d959c
3 changed files with 57 additions and 12 deletions

View file

@ -43,7 +43,7 @@ public class SystemClientUtil {
public static ClientModel getSystemClient(RealmModel realm) { public static ClientModel getSystemClient(RealmModel realm) {
// Try to return builtin "account" client first // Try to return builtin "account" client first
ClientModel client = realm.getClientByClientId(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID); ClientModel client = realm.getClientByClientId(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
if (client != null) { if (client != null && client.isEnabled()) {
return client; return client;
} }

View file

@ -60,6 +60,7 @@ import org.keycloak.models.light.LightweightUserAdapter;
import org.keycloak.models.utils.ModelToRepresentation; import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.RepresentationToModel; import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.models.utils.RoleUtils; import org.keycloak.models.utils.RoleUtils;
import org.keycloak.models.utils.SystemClientUtil;
import org.keycloak.policy.PasswordPolicyNotMetException; import org.keycloak.policy.PasswordPolicyNotMetException;
import org.keycloak.protocol.oidc.OIDCLoginProtocol; import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.protocol.oidc.utils.RedirectUtils; import org.keycloak.protocol.oidc.utils.RedirectUtils;
@ -1112,11 +1113,8 @@ public class UserResource {
throw ErrorResponse.error("Client id missing", Status.BAD_REQUEST); throw ErrorResponse.error("Client id missing", Status.BAD_REQUEST);
} }
if (clientId == null) {
clientId = Constants.ACCOUNT_MANAGEMENT_CLIENT_ID;
}
ClientModel client = realm.getClientByClientId(clientId); ClientModel client = clientId != null ? realm.getClientByClientId(clientId) : SystemClientUtil.getSystemClient(realm);
if (client == null) { if (client == null) {
logger.debugf("Client %s doesn't exist", clientId); logger.debugf("Client %s doesn't exist", clientId);
throw ErrorResponse.error("Client doesn't exist", Status.BAD_REQUEST); throw ErrorResponse.error("Client doesn't exist", Status.BAD_REQUEST);

View file

@ -52,6 +52,7 @@ import org.keycloak.models.credential.PasswordCredentialModel;
import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.models.utils.ModelToRepresentation; import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.StripSecretsUtils; import org.keycloak.models.utils.StripSecretsUtils;
import org.keycloak.models.utils.SystemClientUtil;
import org.keycloak.representations.AccessToken; import org.keycloak.representations.AccessToken;
import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ComponentRepresentation; import org.keycloak.representations.idm.ComponentRepresentation;
@ -1908,6 +1909,8 @@ public class UserTest extends AbstractAdminTest {
passwordUpdatePage.changePassword("new-pass", "new-pass"); passwordUpdatePage.changePassword("new-pass", "new-pass");
assertThat(driver.getCurrentUrl(), Matchers.containsString("client_id=" + Constants.ACCOUNT_MANAGEMENT_CLIENT_ID));
assertEquals("Your account has been updated.", PageUtils.getPageTitle(driver)); assertEquals("Your account has been updated.", PageUtils.getPageTitle(driver));
driver.navigate().to(link); driver.navigate().to(link);
@ -1915,6 +1918,50 @@ public class UserTest extends AbstractAdminTest {
assertEquals("We are sorry...", PageUtils.getPageTitle(driver)); assertEquals("We are sorry...", PageUtils.getPageTitle(driver));
} }
@Test
public void sendResetPasswordEmailSuccessWithAccountClientDisabled() throws IOException {
ClientRepresentation clientRepresentation = realm.clients().findByClientId(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID).get(0);
clientRepresentation.setEnabled(false);
realm.clients().get(clientRepresentation.getId()).update(clientRepresentation);
assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, AdminEventPaths.clientResourcePath(clientRepresentation.getId()), clientRepresentation, ResourceType.CLIENT);
UserRepresentation userRep = new UserRepresentation();
userRep.setEnabled(true);
userRep.setUsername("user1");
userRep.setEmail("user1@test.com");
String id = createUser(userRep);
UserResource user = realm.users().get(id);
List<String> actions = new LinkedList<>();
actions.add(UserModel.RequiredAction.UPDATE_PASSWORD.name());
user.executeActionsEmail(actions);
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.userResourcePath(id) + "/execute-actions-email", ResourceType.USER);
Assert.assertEquals(1, greenMail.getReceivedMessages().length);
MimeMessage message = greenMail.getReceivedMessages()[0];
MailUtils.EmailBody body = MailUtils.getBody(message);
String link = MailUtils.getPasswordResetEmailLink(body);
driver.navigate().to(link);
proceedPage.assertCurrent();
assertThat(proceedPage.getInfo(), Matchers.containsString("Update Password"));
proceedPage.clickProceedLink();
passwordUpdatePage.assertCurrent();
passwordUpdatePage.changePassword("new-pass", "new-pass");
assertThat(driver.getCurrentUrl(), Matchers.containsString("client_id=" + SystemClientUtil.SYSTEM_CLIENT_ID));
clientRepresentation.setEnabled(true);
realm.clients().get(clientRepresentation.getId()).update(clientRepresentation);
assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, AdminEventPaths.clientResourcePath(clientRepresentation.getId()), clientRepresentation, ResourceType.CLIENT);
}
@Test @Test
public void testEmailLinkBasedOnRealmFrontEndUrl() throws Exception { public void testEmailLinkBasedOnRealmFrontEndUrl() throws Exception {
try { try {