return proper error message for admin users endpoint

closes #28416

Signed-off-by: etiksouma <al@mouskite.com>
This commit is contained in:
etiksouma 2024-04-19 15:15:09 +02:00 committed by Alexander Schwartz
parent 750ff41691
commit 1afd20e4c3
4 changed files with 27 additions and 4 deletions

View file

@ -756,7 +756,9 @@ public class RepresentationToModel {
session.getContext().setRealm(realm);
user.credentialManager().updateCredential(UserCredentialModel.password(cred.getValue(), false));
} catch (ModelException ex) {
throw new PasswordPolicyNotMetException(ex.getMessage(), user.getUsername(), ex);
PasswordPolicyNotMetException passwordPolicyNotMetException = new PasswordPolicyNotMetException(ex.getMessage(), user.getUsername(), ex);
passwordPolicyNotMetException.setParameters(ex.getParameters());
throw passwordPolicyNotMetException;
} finally {
session.getContext().setRealm(origRealm);
}

View file

@ -59,6 +59,7 @@ import org.keycloak.models.light.LightweightUserAdapter;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.models.utils.RoleUtils;
import org.keycloak.policy.PasswordPolicyNotMetException;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.protocol.oidc.utils.RedirectUtils;
import org.keycloak.provider.ProviderFactory;
@ -222,6 +223,12 @@ public class UserResource {
} catch (ReadOnlyException re) {
session.getTransactionManager().setRollbackOnly();
throw ErrorResponse.error("User is read only!", Status.BAD_REQUEST);
} catch (PasswordPolicyNotMetException e) {
logger.warn("Password policy not met for user " + e.getUsername(), e);
session.getTransactionManager().setRollbackOnly();
Properties messages = AdminRoot.getMessages(session, realm, auth.adminAuth().getToken().getLocale());
throw new ErrorResponseException(e.getMessage(), MessageFormat.format(messages.getProperty(e.getMessage(), e.getMessage()), e.getParameters()),
Status.BAD_REQUEST);
} catch (ModelException me) {
logger.warn("Could not update user!", me);
session.getTransactionManager().setRollbackOnly();
@ -684,6 +691,11 @@ public class UserResource {
throw new BadRequestException("Resetting to N old passwords is not allowed.");
} catch (ReadOnlyException mre) {
throw new BadRequestException("Can't reset password as account is read only");
} catch (PasswordPolicyNotMetException e) {
logger.warn("Password policy not met for user " + e.getUsername(), e);
Properties messages = AdminRoot.getMessages(session, realm, auth.adminAuth().getToken().getLocale());
throw new ErrorResponseException(e.getMessage(), MessageFormat.format(messages.getProperty(e.getMessage(), e.getMessage()), e.getParameters()),
Status.BAD_REQUEST);
} catch (ModelException e) {
logger.warn("Could not update user password.", e);
Properties messages = AdminRoot.getMessages(session, realm, auth.adminAuth().getToken().getLocale());

View file

@ -40,6 +40,7 @@ import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.policy.PasswordPolicyNotMetException;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.ErrorResponse;
import org.keycloak.services.ErrorResponseException;
import org.keycloak.services.resources.KeycloakOpenAPI;
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.services.resources.admin.permissions.UserPermissionEvaluator;
@ -59,12 +60,15 @@ import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -156,7 +160,10 @@ public class UsersResource {
} catch (ModelDuplicateException e) {
throw ErrorResponse.exists("User exists with same username or email");
} catch (PasswordPolicyNotMetException e) {
throw ErrorResponse.error("Password policy not met", Response.Status.BAD_REQUEST);
logger.warn("Password policy not met for user " + e.getUsername(), e);
Properties messages = AdminRoot.getMessages(session, realm, auth.adminAuth().getToken().getLocale());
throw new ErrorResponseException(e.getMessage(), MessageFormat.format(messages.getProperty(e.getMessage(), e.getMessage()), e.getParameters()),
Response.Status.BAD_REQUEST);
} catch (ModelException me){
logger.warn("Could not create user", me);
throw ErrorResponse.error("Could not create user", Response.Status.BAD_REQUEST);

View file

@ -61,6 +61,7 @@ import org.keycloak.representations.idm.FederatedIdentityRepresentation;
import org.keycloak.representations.idm.GroupRepresentation;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.keycloak.representations.idm.MappingsRepresentation;
import org.keycloak.representations.idm.OAuth2ErrorRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RequiredActionProviderRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
@ -738,8 +739,9 @@ public class UserTest extends AbstractAdminTest {
try (Response response = realm.users().create(user)) {
assertEquals(400, response.getStatus());
ErrorRepresentation error = response.readEntity(ErrorRepresentation.class);
Assert.assertEquals("Password policy not met", error.getErrorMessage());
OAuth2ErrorRepresentation error = response.readEntity(OAuth2ErrorRepresentation.class);
Assert.assertEquals("invalidPasswordMinLengthMessage", error.getError());
Assert.assertEquals("Invalid password: minimum length 8.", error.getErrorDescription());
rep.setPasswordPolicy(passwordPolicy);
assertAdminEvents.assertEmpty();
realm.update(rep);