Merge pull request #909 from pedroigor/master
[KEYCLOAK-928] - Validate duplicated emails when updating profile.
This commit is contained in:
commit
37d6a79205
3 changed files with 46 additions and 7 deletions
|
@ -22,7 +22,6 @@
|
||||||
package org.keycloak.services.resources;
|
package org.keycloak.services.resources;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.jboss.resteasy.spi.HttpRequest;
|
||||||
import org.keycloak.ClientConnection;
|
import org.keycloak.ClientConnection;
|
||||||
import org.keycloak.email.EmailException;
|
import org.keycloak.email.EmailException;
|
||||||
|
@ -45,7 +44,6 @@ import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
import org.keycloak.models.utils.TimeBasedOTP;
|
import org.keycloak.models.utils.TimeBasedOTP;
|
||||||
import org.keycloak.protocol.LoginProtocol;
|
import org.keycloak.protocol.LoginProtocol;
|
||||||
import org.keycloak.protocol.oidc.OpenIDConnect;
|
|
||||||
import org.keycloak.protocol.oidc.OpenIDConnectService;
|
import org.keycloak.protocol.oidc.OpenIDConnectService;
|
||||||
import org.keycloak.protocol.oidc.TokenManager;
|
import org.keycloak.protocol.oidc.TokenManager;
|
||||||
import org.keycloak.representations.PasswordToken;
|
import org.keycloak.representations.PasswordToken;
|
||||||
|
@ -63,7 +61,6 @@ import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.QueryParam;
|
import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.Cookie;
|
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
|
@ -73,7 +70,6 @@ import javax.ws.rs.core.UriInfo;
|
||||||
import javax.ws.rs.ext.Providers;
|
import javax.ws.rs.ext.Providers;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -605,16 +601,28 @@ public class LoginActionsService {
|
||||||
user.setLastName(formData.getFirst("lastName"));
|
user.setLastName(formData.getFirst("lastName"));
|
||||||
|
|
||||||
String email = formData.getFirst("email");
|
String email = formData.getFirst("email");
|
||||||
|
|
||||||
String oldEmail = user.getEmail();
|
String oldEmail = user.getEmail();
|
||||||
boolean emailChanged = oldEmail != null ? !oldEmail.equals(email) : email != null;
|
boolean emailChanged = oldEmail != null ? !oldEmail.equals(email) : email != null;
|
||||||
|
|
||||||
user.setEmail(email);
|
if (emailChanged) {
|
||||||
|
UserModel userByEmail = session.users().getUserByEmail(email, realm);
|
||||||
|
|
||||||
|
// check for duplicated email
|
||||||
|
if (userByEmail != null && !userByEmail.getId().equals(user.getId())) {
|
||||||
|
return Flows.forms(session, realm, null, uriInfo).setUser(user).setError(Messages.EMAIL_EXISTS)
|
||||||
|
.setClientSessionCode(accessCode.getCode())
|
||||||
|
.createResponse(RequiredAction.UPDATE_PROFILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
user.setEmail(email);
|
||||||
|
user.setEmailVerified(false);
|
||||||
|
}
|
||||||
|
|
||||||
user.removeRequiredAction(RequiredAction.UPDATE_PROFILE);
|
user.removeRequiredAction(RequiredAction.UPDATE_PROFILE);
|
||||||
|
|
||||||
event.clone().event(EventType.UPDATE_PROFILE).success();
|
event.clone().event(EventType.UPDATE_PROFILE).success();
|
||||||
|
|
||||||
if (emailChanged) {
|
if (emailChanged) {
|
||||||
user.setEmailVerified(false);
|
|
||||||
event.clone().event(EventType.UPDATE_EMAIL).detail(Details.PREVIOUS_EMAIL, oldEmail).detail(Details.UPDATED_EMAIL, email).success();
|
event.clone().event(EventType.UPDATE_EMAIL).detail(Details.PREVIOUS_EMAIL, oldEmail).detail(Details.UPDATED_EMAIL, email).success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -147,4 +147,21 @@ public class RequiredActionUpdateProfileTest {
|
||||||
events.assertEmpty();
|
events.assertEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateProfileDuplicatedEmail() {
|
||||||
|
loginPage.open();
|
||||||
|
|
||||||
|
loginPage.login("test-user@localhost", "password");
|
||||||
|
|
||||||
|
updateProfilePage.assertCurrent();
|
||||||
|
|
||||||
|
updateProfilePage.update("New first", "New last", "keycloak-user@localhost");
|
||||||
|
|
||||||
|
updateProfilePage.assertCurrent();
|
||||||
|
|
||||||
|
Assert.assertEquals("Email already exists", updateProfilePage.getError());
|
||||||
|
|
||||||
|
events.assertEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,20 @@
|
||||||
"test-app": [ "customer-user" ],
|
"test-app": [ "customer-user" ],
|
||||||
"account": [ "view-profile", "manage-account" ]
|
"account": [ "view-profile", "manage-account" ]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"username" : "keycloak-user@localhost",
|
||||||
|
"enabled": true,
|
||||||
|
"email" : "keycloak-user@localhost",
|
||||||
|
"credentials" : [
|
||||||
|
{ "type" : "password",
|
||||||
|
"value" : "password" }
|
||||||
|
],
|
||||||
|
"realmRoles": ["user"],
|
||||||
|
"applicationRoles": {
|
||||||
|
"test-app": [ "customer-user" ],
|
||||||
|
"account": [ "view-profile", "manage-account" ]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"oauthClients" : [
|
"oauthClients" : [
|
||||||
|
|
Loading…
Reference in a new issue