Merge pull request #3024 from stianst/KEYCLOAK-3267

KEYCLOAK-3267 Fix identity broker login with brute force enabled
This commit is contained in:
Stian Thorgersen 2016-07-13 07:37:52 +02:00 committed by GitHub
commit d7649c2547
3 changed files with 86 additions and 2 deletions

View file

@ -55,6 +55,7 @@ import org.keycloak.provider.ProviderFactory;
import org.keycloak.representations.AccessToken;
import org.keycloak.services.managers.AppAuthManager;
import org.keycloak.services.managers.AuthenticationManager.AuthResult;
import org.keycloak.services.managers.BruteForceProtector;
import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.ErrorResponse;
@ -338,8 +339,10 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
return ErrorPage.error(session, Messages.ACCOUNT_DISABLED);
}
if (realm.isBruteForceProtected()) {
event.error(Errors.USER_TEMPORARILY_DISABLED);
return ErrorPage.error(session, Messages.ACCOUNT_DISABLED);
if (session.getProvider(BruteForceProtector.class).isTemporarilyDisabled(session, realm, user)) {
event.error(Errors.USER_TEMPORARILY_DISABLED);
return ErrorPage.error(session, Messages.ACCOUNT_DISABLED);
}
}
return null;
}

View file

@ -9,15 +9,21 @@ import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.messages.Messages;
import org.keycloak.testsuite.AbstractKeycloakTest;
import org.keycloak.testsuite.Assert;
import org.keycloak.testsuite.pages.AccountPasswordPage;
import org.keycloak.testsuite.pages.ErrorPage;
import org.keycloak.testsuite.pages.LoginPage;
import org.keycloak.testsuite.pages.UpdateAccountInformationPage;
import org.keycloak.testsuite.util.RealmBuilder;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import static org.jgroups.util.Util.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.keycloak.testsuite.admin.ApiUtil.createUserWithAdminClient;
import static org.keycloak.testsuite.admin.ApiUtil.resetUserPassword;
@ -42,9 +48,16 @@ public abstract class AbstractBrokerTest extends AbstractKeycloakTest {
@Page
protected LoginPage accountLoginPage;
@Page
protected UpdateAccountInformationPage updateAccountInformationPage;
@Page
protected AccountPasswordPage accountPasswordPage;
@Page
protected ErrorPage errorPage;
@Override
public void addTestRealms(List<RealmRepresentation> testRealms) {
RealmRepresentation providerRealm = createProviderRealm();
@ -171,6 +184,60 @@ public abstract class AbstractBrokerTest extends AbstractKeycloakTest {
testSingleLogout();
}
@Test
public void loginWithExistingUser() {
logInAsUserInIDP();
Integer userCount = adminClient.realm(consumerRealmName()).users().count();
driver.navigate().to(getAccountUrl(consumerRealmName()));
log.debug("Clicking social " + getIDPAlias());
accountLoginPage.clickSocial(getIDPAlias());
Assert.assertTrue("Driver should be on the provider realm page right now", driver.getCurrentUrl().contains("/auth/realms/" + providerRealmName() + "/"));
accountLoginPage.login(getUserLogin(), getUserPassword());
System.out.println(driver.getPageSource());
assertEquals(accountPage.buildUri().toASCIIString().replace("master", "consumer") + "/", driver.getCurrentUrl());
assertEquals(userCount, adminClient.realm(consumerRealmName()).users().count());
}
// KEYCLOAK-3267
@Test
public void loginWithExistingUserWithBruteForceEnabled() {
adminClient.realm(consumerRealmName()).update(RealmBuilder.create().bruteForceProtected(true).failureFactor(2).build());
loginWithExistingUser();
driver.navigate().to(getAccountPasswordUrl(consumerRealmName()));
accountPasswordPage.changePassword("password", "password");
driver.navigate().to(getAuthRoot()
+ "/auth/realms/" + providerRealmName()
+ "/protocol/" + "openid-connect"
+ "/logout");
driver.navigate().to(getAccountUrl(consumerRealmName()));
accountLoginPage.login(getUserLogin(), "invalid");
accountLoginPage.login(getUserLogin(), "invalid");
accountLoginPage.login(getUserLogin(), "invalid");
assertEquals("Invalid username or password.", accountLoginPage.getError());
accountLoginPage.clickSocial(getIDPAlias());
Assert.assertTrue("Driver should be on the provider realm page right now", driver.getCurrentUrl().contains("/auth/realms/" + providerRealmName() + "/"));
accountLoginPage.login(getUserLogin(), getUserPassword());
assertEquals("Account is disabled, contact admin.", errorPage.getError());
}
protected void testSingleLogout() {
log.debug("Testing single log out");
@ -203,4 +270,8 @@ public abstract class AbstractBrokerTest extends AbstractKeycloakTest {
private String getAccountUrl(String realmName) {
return getAuthRoot() + "/auth/realms/" + realmName + "/account";
}
private String getAccountPasswordUrl(String realmName) {
return getAuthRoot() + "/auth/realms/" + realmName + "/account/password";
}
}

View file

@ -137,6 +137,16 @@ public class RealmBuilder {
return this;
}
public RealmBuilder bruteForceProtected(boolean bruteForceProtected) {
rep.setBruteForceProtected(bruteForceProtected);
return this;
}
public RealmBuilder failureFactor(int failureFactor) {
rep.setFailureFactor(failureFactor);
return this;
}
public RealmBuilder otpDigits(int i) {
rep.setOtpPolicyDigits(i);
return this;