[KEYCLOAK-12044] Fix messages in the UsernameForm (#6548)
This commit is contained in:
parent
05493371ca
commit
2cf6483cdf
8 changed files with 109 additions and 5 deletions
|
@ -104,7 +104,7 @@ public abstract class AbstractUsernameFormAuthenticator extends AbstractFormAuth
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
dummyHash(context);
|
dummyHash(context);
|
||||||
context.getEvent().error(Errors.USER_NOT_FOUND);
|
context.getEvent().error(Errors.USER_NOT_FOUND);
|
||||||
Response challengeResponse = challenge(context, Messages.INVALID_USER);
|
Response challengeResponse = challenge(context, getDefaultChallengeMessage(context));
|
||||||
context.failureChallenge(AuthenticationFlowError.INVALID_USER, challengeResponse);
|
context.failureChallenge(AuthenticationFlowError.INVALID_USER, challengeResponse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,7 @@ public abstract class AbstractUsernameFormAuthenticator extends AbstractFormAuth
|
||||||
String username = inputData.getFirst(AuthenticationManager.FORM_USERNAME);
|
String username = inputData.getFirst(AuthenticationManager.FORM_USERNAME);
|
||||||
if (username == null) {
|
if (username == null) {
|
||||||
context.getEvent().error(Errors.USER_NOT_FOUND);
|
context.getEvent().error(Errors.USER_NOT_FOUND);
|
||||||
Response challengeResponse = challenge(context, Messages.INVALID_USER);
|
Response challengeResponse = challenge(context, getDefaultChallengeMessage(context));
|
||||||
context.failureChallenge(AuthenticationFlowError.INVALID_USER, challengeResponse);
|
context.failureChallenge(AuthenticationFlowError.INVALID_USER, challengeResponse);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,7 @@ public abstract class AbstractUsernameFormAuthenticator extends AbstractFormAuth
|
||||||
if (password == null || password.isEmpty()) {
|
if (password == null || password.isEmpty()) {
|
||||||
context.getEvent().user(user);
|
context.getEvent().user(user);
|
||||||
context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
|
context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
|
||||||
Response challengeResponse = challenge(context, Messages.INVALID_USER);
|
Response challengeResponse = challenge(context, getDefaultChallengeMessage(context));
|
||||||
context.forceChallenge(challengeResponse);
|
context.forceChallenge(challengeResponse);
|
||||||
context.clearUser();
|
context.clearUser();
|
||||||
return false;
|
return false;
|
||||||
|
@ -206,7 +206,7 @@ public abstract class AbstractUsernameFormAuthenticator extends AbstractFormAuth
|
||||||
} else {
|
} else {
|
||||||
context.getEvent().user(user);
|
context.getEvent().user(user);
|
||||||
context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
|
context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
|
||||||
Response challengeResponse = challenge(context, Messages.INVALID_USER);
|
Response challengeResponse = challenge(context, getDefaultChallengeMessage(context));
|
||||||
context.failureChallenge(AuthenticationFlowError.INVALID_CREDENTIALS, challengeResponse);
|
context.failureChallenge(AuthenticationFlowError.INVALID_CREDENTIALS, challengeResponse);
|
||||||
if (clearUser) {
|
if (clearUser) {
|
||||||
context.clearUser();
|
context.clearUser();
|
||||||
|
@ -228,4 +228,8 @@ public abstract class AbstractUsernameFormAuthenticator extends AbstractFormAuth
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected String getDefaultChallengeMessage(AuthenticationFlowContext context) {
|
||||||
|
return Messages.INVALID_USER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.keycloak.forms.login.LoginFormsProvider;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.services.messages.Messages;
|
||||||
|
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
@ -53,4 +54,9 @@ public class PasswordForm extends UsernamePasswordForm {
|
||||||
protected Response createLoginForm(LoginFormsProvider form) {
|
protected Response createLoginForm(LoginFormsProvider form) {
|
||||||
return form.createLoginPassword();
|
return form.createLoginPassword();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getDefaultChallengeMessage(AuthenticationFlowContext context){
|
||||||
|
return Messages.INVALID_PASSWORD;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ package org.keycloak.authentication.authenticators.browser;
|
||||||
|
|
||||||
import org.keycloak.authentication.AuthenticationFlowContext;
|
import org.keycloak.authentication.AuthenticationFlowContext;
|
||||||
import org.keycloak.forms.login.LoginFormsProvider;
|
import org.keycloak.forms.login.LoginFormsProvider;
|
||||||
|
import org.keycloak.services.messages.Messages;
|
||||||
|
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
@ -43,4 +44,11 @@ public final class UsernameForm extends UsernamePasswordForm {
|
||||||
protected Response createLoginForm(LoginFormsProvider form) {
|
protected Response createLoginForm(LoginFormsProvider form) {
|
||||||
return form.createLoginUsername();
|
return form.createLoginUsername();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getDefaultChallengeMessage(AuthenticationFlowContext context) {
|
||||||
|
if (context.getRealm().isLoginWithEmailAllowed())
|
||||||
|
return Messages.INVALID_USERNAME_OR_EMAIL;
|
||||||
|
return Messages.INVALID_USERNAME;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||||
import org.keycloak.services.ServicesLogger;
|
import org.keycloak.services.ServicesLogger;
|
||||||
import org.keycloak.services.managers.AuthenticationManager;
|
import org.keycloak.services.managers.AuthenticationManager;
|
||||||
|
import org.keycloak.services.messages.Messages;
|
||||||
|
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
@ -111,4 +112,9 @@ public class UsernamePasswordForm extends AbstractUsernameFormAuthenticator impl
|
||||||
public PasswordCredentialProvider getCredentialProvider(KeycloakSession session) {
|
public PasswordCredentialProvider getCredentialProvider(KeycloakSession session) {
|
||||||
return (PasswordCredentialProvider)session.getProvider(CredentialProvider.class, "keycloak-password");
|
return (PasswordCredentialProvider)session.getProvider(CredentialProvider.class, "keycloak-password");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getDefaultChallengeMessage(AuthenticationFlowContext context){
|
||||||
|
return Messages.INVALID_USER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,12 @@ public class Messages {
|
||||||
|
|
||||||
public static final String INVALID_USER = "invalidUserMessage";
|
public static final String INVALID_USER = "invalidUserMessage";
|
||||||
|
|
||||||
|
public static final String INVALID_USERNAME = "invalidUsernameMessage";
|
||||||
|
|
||||||
|
public static final String INVALID_USERNAME_OR_EMAIL = "invalidUsernameOrEmailMessage";
|
||||||
|
|
||||||
|
public static final String INVALID_PASSWORD = "invalidPasswordMessage";
|
||||||
|
|
||||||
public static final String INVALID_EMAIL = "invalidEmailMessage";
|
public static final String INVALID_EMAIL = "invalidEmailMessage";
|
||||||
|
|
||||||
public static final String ACCOUNT_DISABLED = "accountDisabledMessage";
|
public static final String ACCOUNT_DISABLED = "accountDisabledMessage";
|
||||||
|
|
|
@ -55,7 +55,7 @@ public class KcOidcFirstBrokerLoginNewAuthTest extends AbstractInitializedBaseBr
|
||||||
|
|
||||||
// Try bad password first
|
// Try bad password first
|
||||||
passwordPage.login("bad-password");
|
passwordPage.login("bad-password");
|
||||||
Assert.assertEquals("Invalid username or password.", passwordPage.getError());
|
Assert.assertEquals("Invalid password.", passwordPage.getError());
|
||||||
|
|
||||||
// Try good password
|
// Try good password
|
||||||
passwordPage.login("password");
|
passwordPage.login("password");
|
||||||
|
|
|
@ -1010,6 +1010,77 @@ public class BrowserFlowTest extends AbstractTestRealmKeycloakTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test checks the error messages, when the credentials are invalid and UsernameForm and PasswordForm are separated.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testLoginWithWrongCredentialsMessage() {
|
||||||
|
UserRepresentation user = testRealm().users().search("test-user@localhost").get(0);
|
||||||
|
Assert.assertNotNull(user);
|
||||||
|
|
||||||
|
loginPage.open();
|
||||||
|
loginPage.assertCurrent();
|
||||||
|
loginPage.login(user.getUsername(), "wrong_password");
|
||||||
|
|
||||||
|
Assert.assertEquals("Invalid username or password.", loginPage.getError());
|
||||||
|
events.clear();
|
||||||
|
|
||||||
|
loginPage.assertCurrent();
|
||||||
|
loginPage.login(user.getUsername(), "password");
|
||||||
|
|
||||||
|
Assert.assertFalse(loginPage.isCurrent());
|
||||||
|
events.expectLogin()
|
||||||
|
.user(user)
|
||||||
|
.detail(Details.USERNAME, "test-user@localhost")
|
||||||
|
.assertEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test checks the error messages, when the credentials are invalid and UsernameForm and PasswordForm are separated.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testLoginMultiFactorWithWrongCredentialsMessage() {
|
||||||
|
UserRepresentation user = testRealm().users().search("test-user@localhost").get(0);
|
||||||
|
Assert.assertNotNull(user);
|
||||||
|
|
||||||
|
configureBrowserFlowWithAlternativeCredentials();
|
||||||
|
try {
|
||||||
|
RealmRepresentation realm = testRealm().toRepresentation();
|
||||||
|
realm.setLoginWithEmailAllowed(false);
|
||||||
|
testRealm().update(realm);
|
||||||
|
|
||||||
|
loginUsernameOnlyPage.open();
|
||||||
|
loginUsernameOnlyPage.assertCurrent();
|
||||||
|
loginUsernameOnlyPage.login("non_existing_user");
|
||||||
|
Assert.assertEquals("Invalid username.", loginUsernameOnlyPage.getError());
|
||||||
|
|
||||||
|
realm.setLoginWithEmailAllowed(true);
|
||||||
|
testRealm().update(realm);
|
||||||
|
loginUsernameOnlyPage.login("non_existing_user");
|
||||||
|
Assert.assertEquals("Invalid username or email.", loginUsernameOnlyPage.getError());
|
||||||
|
|
||||||
|
loginUsernameOnlyPage.login(user.getUsername());
|
||||||
|
|
||||||
|
passwordPage.assertCurrent();
|
||||||
|
passwordPage.login("wrong_password");
|
||||||
|
Assert.assertEquals("Invalid password.", passwordPage.getError());
|
||||||
|
|
||||||
|
passwordPage.assertCurrent();
|
||||||
|
events.clear();
|
||||||
|
passwordPage.login("password");
|
||||||
|
|
||||||
|
Assert.assertFalse(loginUsernameOnlyPage.isCurrent());
|
||||||
|
Assert.assertFalse(passwordPage.isCurrent());
|
||||||
|
|
||||||
|
events.expectLogin()
|
||||||
|
.user(user)
|
||||||
|
.detail(Details.USERNAME, "test-user@localhost")
|
||||||
|
.assertEvent();
|
||||||
|
} finally {
|
||||||
|
revertFlows("browser - alternative");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This flow contains:
|
* This flow contains:
|
||||||
* UsernameForm REQUIRED
|
* UsernameForm REQUIRED
|
||||||
|
|
|
@ -157,6 +157,9 @@ client_realm-management=Realm Management
|
||||||
client_broker=Broker
|
client_broker=Broker
|
||||||
|
|
||||||
invalidUserMessage=Invalid username or password.
|
invalidUserMessage=Invalid username or password.
|
||||||
|
invalidUsernameMessage=Invalid username.
|
||||||
|
invalidUsernameOrEmailMessage=Invalid username or email.
|
||||||
|
invalidPasswordMessage=Invalid password.
|
||||||
invalidEmailMessage=Invalid email address.
|
invalidEmailMessage=Invalid email address.
|
||||||
accountDisabledMessage=Account is disabled, contact your administrator.
|
accountDisabledMessage=Account is disabled, contact your administrator.
|
||||||
accountTemporarilyDisabledMessage=Account is temporarily disabled; contact your administrator or retry later.
|
accountTemporarilyDisabledMessage=Account is temporarily disabled; contact your administrator or retry later.
|
||||||
|
|
Loading…
Reference in a new issue