diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/AccountTotpPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/AccountTotpPage.java deleted file mode 100755 index ff7f5d1599..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/AccountTotpPage.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.testsuite.pages; - -import org.keycloak.services.resources.account.AccountFormService; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.support.FindBy; - -import javax.ws.rs.core.UriBuilder; - -/** - * @author Stian Thorgersen - */ -public class AccountTotpPage extends AbstractAccountPage { - - @FindBy(id = "totpSecret") - private WebElement totpSecret; - - @FindBy(id = "totp") - private WebElement totpInput; - - @FindBy(id = "userLabel") - private WebElement totpLabelInput; - - @FindBy(css = "button[type=\"submit\"]") - private WebElement submitButton; - - @FindBy(id = "remove-mobile") - private WebElement removeLink; - - @FindBy(id = "mode-barcode") - private WebElement barcodeLink; - - @FindBy(id = "mode-manual") - private WebElement manualLink; - - private String getPath() { - return AccountFormService.totpUrl(UriBuilder.fromUri(getAuthServerRoot())).build("test").toString(); - } - - public void configure(String totp) { - totpInput.sendKeys(totp); - submitButton.click(); - } - - public void configure(String totp, String userLabel) { - totpInput.sendKeys(totp); - totpLabelInput.sendKeys(userLabel); - submitButton.click(); - } - - public String getTotpSecret() { - return totpSecret.getAttribute("value"); - } - - public boolean isCurrent() { - return driver.getTitle().contains("Account Management") && driver.getCurrentUrl().split("\\?")[0].endsWith("/account/totp"); - } - - public void open() { - driver.navigate().to(getPath()); - } - - public void removeTotp() { - removeLink.click(); - } - - public void clickManual() { - manualLink.click(); - } - - public void clickBarcode() { - barcodeLink.click(); - } - -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractAuthTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractAuthTest.java index f00d06c809..e533520c26 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractAuthTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractAuthTest.java @@ -28,6 +28,8 @@ import org.keycloak.testsuite.auth.page.account.Account; import org.keycloak.testsuite.auth.page.login.OIDCLogin; import org.keycloak.testsuite.auth.page.login.SAMLPostLogin; import org.keycloak.testsuite.auth.page.login.SAMLRedirectLogin; +import org.keycloak.testsuite.util.ClientBuilder; +import org.keycloak.testsuite.util.RealmBuilder; import org.openqa.selenium.Cookie; import java.text.MessageFormat; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java index 9f3a56ca65..eb87079664 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java @@ -34,7 +34,6 @@ import org.keycloak.admin.client.resource.AuthenticationManagementResource; import org.keycloak.admin.client.resource.RealmsResource; import org.keycloak.admin.client.resource.UserResource; import org.keycloak.admin.client.resource.UsersResource; -import org.keycloak.common.Profile; import org.keycloak.common.util.KeycloakUriBuilder; import org.keycloak.common.util.Time; import org.keycloak.models.RealmProvider; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/AppInitiatedActionTotpSetupTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/AppInitiatedActionTotpSetupTest.java index 36dae497bb..e9c948a746 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/AppInitiatedActionTotpSetupTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/AppInitiatedActionTotpSetupTest.java @@ -24,7 +24,6 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.keycloak.admin.client.resource.RealmResource; -import org.keycloak.common.Profile; import org.keycloak.events.Details; import org.keycloak.events.EventType; import org.keycloak.models.AuthenticationExecutionModel; @@ -37,11 +36,10 @@ import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.testsuite.AssertEvents; import org.keycloak.testsuite.admin.ApiUtil; -import org.keycloak.testsuite.arquillian.annotation.DisableFeature; -import org.keycloak.testsuite.pages.AccountTotpPage; import org.keycloak.testsuite.pages.LoginConfigTotpPage; import org.keycloak.testsuite.pages.LoginTotpPage; import org.keycloak.testsuite.pages.RegisterPage; +import org.keycloak.testsuite.util.AccountHelper; import org.keycloak.testsuite.util.OAuthClient; import org.keycloak.testsuite.util.RealmBuilder; import org.keycloak.testsuite.util.UserBuilder; @@ -93,9 +91,6 @@ public class AppInitiatedActionTotpSetupTest extends AbstractAppInitiatedActionT @Page protected LoginConfigTotpPage totpPage; - @Page - protected AccountTotpPage accountTotpPage; - @Page protected RegisterPage registerPage; @@ -111,7 +106,7 @@ public class AppInitiatedActionTotpSetupTest extends AbstractAppInitiatedActionT doAIA(); - assertTrue(totpPage.isCurrent()); + totpPage.assertCurrent(); totpPage.configure(totp.generateTOTP(totpPage.getTotpSecret())); @@ -374,7 +369,6 @@ public class AppInitiatedActionTotpSetupTest extends AbstractAppInitiatedActionT } @Test - @DisableFeature(value = Profile.Feature.ACCOUNT2, skipRestart = true) // TODO remove this (KEYCLOAK-16228) public void setupTotpRegisteredAfterTotpRemoval() { // Register new user loginPage.open(); @@ -418,21 +412,11 @@ public class AppInitiatedActionTotpSetupTest extends AbstractAppInitiatedActionT // Login with one-time password loginTotpPage.login(totp.generateTOTP(totpCode)); + events.expectLogin().user(userId).detail(Details.USERNAME, "setupTotp2").assertEvent(); - loginEvent = events.expectLogin().user(userId).detail(Details.USERNAME, "setupTotp2").assertEvent(); - - // Open account page - accountTotpPage.open(); - accountTotpPage.assertCurrent(); - - // Remove google authentificator - accountTotpPage.removeTotp(); - - events.expectAccount(EventType.REMOVE_TOTP).user(userId).assertEvent(); - - // Logout - accountTotpPage.logout(); - events.expectLogout(loginEvent.getSessionId()).user(userId).detail(Details.REDIRECT_URI, oauth.AUTH_SERVER_ROOT + "/realms/test/account/totp").assertEvent(); + // Remove google authenticator + Assert.assertTrue(AccountHelper.deleteTotpAuthentication(testRealm(),"setupTotp2")); + AccountHelper.logout(testRealm(),"setupTotp2"); // Try to login loginPage.open(); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/RequiredActionTotpSetupTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/RequiredActionTotpSetupTest.java index 68660f0055..5cedb3c811 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/RequiredActionTotpSetupTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/RequiredActionTotpSetupTest.java @@ -23,7 +23,6 @@ import org.junit.Rule; import org.junit.Test; import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.admin.client.resource.UserResource; -import org.keycloak.common.Profile; import org.keycloak.events.Details; import org.keycloak.events.EventType; import org.keycloak.models.AuthenticationExecutionModel; @@ -38,8 +37,6 @@ import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.testsuite.AssertEvents; import org.keycloak.testsuite.AbstractTestRealmKeycloakTest; import org.keycloak.testsuite.admin.ApiUtil; -import org.keycloak.testsuite.arquillian.annotation.DisableFeature; -import org.keycloak.testsuite.pages.AccountTotpPage; import org.keycloak.testsuite.pages.AppPage; import org.keycloak.testsuite.pages.AppPage.RequestType; import org.keycloak.testsuite.pages.LanguageComboboxAwarePage; @@ -48,6 +45,7 @@ import org.keycloak.testsuite.pages.LoginPage; import org.keycloak.testsuite.pages.LoginTotpPage; import org.keycloak.testsuite.pages.RegisterPage; import org.keycloak.testsuite.updaters.RealmAttributeUpdater; +import org.keycloak.testsuite.util.AccountHelper; import org.keycloak.testsuite.util.OAuthClient; import org.keycloak.testsuite.util.RealmBuilder; import org.keycloak.testsuite.util.UserBuilder; @@ -64,7 +62,6 @@ import static org.junit.Assert.assertTrue; /** * @author Stian Thorgersen */ -@DisableFeature(value = Profile.Feature.ACCOUNT2, skipRestart = true) // TODO remove this (KEYCLOAK-16228) public class RequiredActionTotpSetupTest extends AbstractTestRealmKeycloakTest { @Override @@ -117,9 +114,6 @@ public class RequiredActionTotpSetupTest extends AbstractTestRealmKeycloakTest { @Page protected LoginConfigTotpPage totpPage; - @Page - protected AccountTotpPage accountTotpPage; - @Page protected RegisterPage registerPage; @@ -133,7 +127,7 @@ public class RequiredActionTotpSetupTest extends AbstractTestRealmKeycloakTest { String userId = events.expectRegister("setupTotp", "email@mail.com").assertEvent().getUserId(); - assertTrue(totpPage.isCurrent()); + totpPage.assertCurrent(); assertFalse(totpPage.isCancelDisplayed()); // assert attempted-username not shown when setup TOTP @@ -278,7 +272,7 @@ public class RequiredActionTotpSetupTest extends AbstractTestRealmKeycloakTest { String userId = events.expectRegister("setupTotpRegister", "setupTotpRegister@mail.com").assertEvent().getUserId(); - assertTrue(totpPage.isCurrent()); + totpPage.assertCurrent(); // KEYCLOAK-11753 - Verify OTP label element present on "Configure OTP" required action form driver.findElement(By.id("userLabel")); @@ -290,12 +284,9 @@ public class RequiredActionTotpSetupTest extends AbstractTestRealmKeycloakTest { // Set OTP label to a custom value totpPage.configure(totp.generateTOTP(totpPage.getTotpSecret()), customOtpLabel); - // Open account page & verify OTP authenticator with requested label was created - accountTotpPage.open(); - accountTotpPage.assertCurrent(); - - String pageSource = driver.getPageSource(); - assertTrue(pageSource.contains(customOtpLabel)); + // Check if OTP credential is present + Assert.assertTrue(AccountHelper.isTotpPresent(testRealm(), "setupTotpRegister")); + Assert.assertTrue(AccountHelper.totpUserLabelComparator(testRealm(), "setupTotpRegister", customOtpLabel)); } @Test @@ -450,18 +441,9 @@ public class RequiredActionTotpSetupTest extends AbstractTestRealmKeycloakTest { loginEvent = events.expectLogin().user(userId).detail(Details.USERNAME, "setupTotp2").assertEvent(); - // Open account page - accountTotpPage.open(); - accountTotpPage.assertCurrent(); - - // Remove google authentificator - accountTotpPage.removeTotp(); - - events.expectAccount(EventType.REMOVE_TOTP).user(userId).assertEvent(); - - // Logout - accountTotpPage.logout(); - events.expectLogout(loginEvent.getSessionId()).user(userId).detail(Details.REDIRECT_URI, oauth.AUTH_SERVER_ROOT + "/realms/test/account/totp").assertEvent(); + // Remove google authenticator + Assert.assertTrue(AccountHelper.deleteTotpAuthentication(testRealm(),"setupTotp2")); + AccountHelper.logout(testRealm(),"setupTotp2"); setOtpTimeOffset(TimeBasedOTP.DEFAULT_INTERVAL_SECONDS, totp); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserTotpTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserTotpTest.java deleted file mode 100644 index 9e92b6276a..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserTotpTest.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.keycloak.testsuite.admin; - -import org.jboss.arquillian.graphene.page.Page; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.keycloak.common.Profile; -import org.keycloak.events.Details; -import org.keycloak.events.EventType; -import org.keycloak.events.admin.OperationType; -import org.keycloak.models.credential.OTPCredentialModel; -import org.keycloak.models.utils.TimeBasedOTP; -import org.keycloak.representations.idm.AdminEventRepresentation; -import org.keycloak.representations.idm.CredentialRepresentation; -import org.keycloak.representations.idm.RealmRepresentation; -import org.keycloak.representations.idm.UserRepresentation; -import org.keycloak.testsuite.AssertEvents; -import org.keycloak.testsuite.AbstractTestRealmKeycloakTest; -import org.keycloak.testsuite.arquillian.annotation.DisableFeature; -import org.keycloak.testsuite.pages.AccountTotpPage; -import org.keycloak.testsuite.pages.AccountUpdateProfilePage; -import org.keycloak.testsuite.pages.LoginPage; - -import java.util.List; - - -/** - * @author Marko Strukelj - */ -@DisableFeature(value = Profile.Feature.ACCOUNT2, skipRestart = true) // TODO remove this (KEYCLOAK-16228) -public class UserTotpTest extends AbstractTestRealmKeycloakTest { - - @Rule - public AssertEvents events = new AssertEvents(this); - - @Page - protected AccountTotpPage totpPage; - - @Page - protected AccountUpdateProfilePage profilePage; - - @Page - protected LoginPage loginPage; - - private TimeBasedOTP totp = new TimeBasedOTP(); - - - @Override - public void configureTestRealm(RealmRepresentation testRealm) { - } - - @Test - public void setupTotp() { - totpPage.open(); - loginPage.login("test-user@localhost", "password"); - - events.expectLogin().client("account").detail(Details.REDIRECT_URI, getAccountRedirectUrl() + "?path=totp").assertEvent(); - - Assert.assertTrue(totpPage.isCurrent()); - - Assert.assertFalse(driver.getPageSource().contains("Remove Google")); - - totpPage.configure(totp.generateTOTP(totpPage.getTotpSecret())); - - Assert.assertEquals("Mobile authenticator configured.", profilePage.getSuccess()); - - events.expectAccount(EventType.UPDATE_TOTP).assertEvent(); - - Assert.assertTrue(driver.getPageSource().contains("pficon-delete")); - - List users = adminClient.realms().realm("test").users().search("test-user@localhost", null, null, null, 0, 1); - String userId = users.get(0).getId(); - testingClient.testing().clearAdminEventQueue(); - CredentialRepresentation totpCredential = adminClient.realms().realm("test").users().get(userId).credentials() - .stream().filter(c -> OTPCredentialModel.TYPE.equals(c.getType())).findFirst().get(); - adminClient.realms().realm("test").users().get(userId).removeCredential(totpCredential.getId()); - - totpPage.open(); - Assert.assertFalse(driver.getPageSource().contains("pficon-delete")); - - AdminEventRepresentation event = testingClient.testing().pollAdminEvent(); - Assert.assertNotNull(event); - Assert.assertEquals(OperationType.ACTION.name(), event.getOperationType()); - Assert.assertEquals("users/" + userId + "/credentials/" + totpCredential.getId(), event.getResourcePath()); - } -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/BackwardsCompatibilityUserStorageTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/BackwardsCompatibilityUserStorageTest.java index 76598f67e2..9e68fd61c2 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/BackwardsCompatibilityUserStorageTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/BackwardsCompatibilityUserStorageTest.java @@ -18,53 +18,50 @@ package org.keycloak.testsuite.federation.storage; +import org.jboss.arquillian.graphene.page.Page; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.keycloak.admin.client.resource.UserResource; +import org.keycloak.common.Profile.Feature; +import org.keycloak.common.util.MultivaluedHashMap; +import org.keycloak.credential.CredentialModel; +import org.keycloak.models.RealmModel; +import org.keycloak.models.UserModel; +import org.keycloak.models.credential.OTPCredentialModel; +import org.keycloak.models.utils.TimeBasedOTP; +import org.keycloak.representations.idm.ComponentRepresentation; +import org.keycloak.representations.idm.CredentialRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.representations.idm.UserRepresentation; +import org.keycloak.storage.StorageId; +import org.keycloak.storage.UserStorageProvider; +import org.keycloak.testsuite.AbstractTestRealmKeycloakTest; +import org.keycloak.testsuite.Assert; +import org.keycloak.testsuite.ProfileAssume; +import org.keycloak.testsuite.admin.ApiUtil; +import org.keycloak.testsuite.federation.BackwardsCompatibilityUserStorageFactory; +import org.keycloak.testsuite.pages.AppPage; +import org.keycloak.testsuite.pages.LoginConfigTotpPage; +import org.keycloak.testsuite.pages.LoginPage; +import org.keycloak.testsuite.pages.LoginTotpPage; +import org.keycloak.testsuite.util.TestAppHelper; + +import javax.ws.rs.core.Response; import java.io.IOException; import java.net.URISyntaxException; import java.util.Arrays; import java.util.Collections; import java.util.List; -import javax.ws.rs.core.Response; - -import org.jboss.arquillian.graphene.page.Page; -import org.junit.Before; -import org.junit.Test; -import org.keycloak.admin.client.resource.UserResource; -import org.keycloak.common.Profile; -import org.keycloak.common.Profile.Feature; -import org.keycloak.common.util.MultivaluedHashMap; -import org.keycloak.credential.CredentialModel; -import org.keycloak.models.RealmModel; -import org.keycloak.models.UserModel; -import org.keycloak.models.utils.TimeBasedOTP; -import org.keycloak.representations.idm.ComponentRepresentation; -import org.keycloak.representations.idm.CredentialRepresentation; -import org.keycloak.representations.idm.UserRepresentation; -import org.keycloak.storage.StorageId; -import org.keycloak.storage.UserStorageProvider; -import org.keycloak.testsuite.AbstractAuthTest; -import org.keycloak.testsuite.Assert; -import org.keycloak.testsuite.ProfileAssume; -import org.keycloak.testsuite.admin.ApiUtil; -import org.keycloak.testsuite.arquillian.annotation.DisableFeature; -import org.keycloak.testsuite.federation.BackwardsCompatibilityUserStorageFactory; -import org.keycloak.testsuite.pages.AccountTotpPage; -import org.keycloak.testsuite.pages.AppPage; -import org.keycloak.testsuite.pages.LoginConfigTotpPage; -import org.keycloak.testsuite.pages.LoginPage; -import org.keycloak.testsuite.pages.LoginTotpPage; - -import org.junit.BeforeClass; -import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlDoesntStartWith; -import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith; +import static org.wildfly.common.Assert.assertTrue; /** * Test that userStorage implementation created in previous version is still compatible with latest Keycloak version * * @author Marek Posolda */ -@DisableFeature(value = Profile.Feature.ACCOUNT2, skipRestart = true) // TODO remove this (KEYCLOAK-16228) -public class BackwardsCompatibilityUserStorageTest extends AbstractAuthTest { +public class BackwardsCompatibilityUserStorageTest extends AbstractTestRealmKeycloakTest { private String backwardsCompProviderId; @@ -77,15 +74,14 @@ public class BackwardsCompatibilityUserStorageTest extends AbstractAuthTest { @Page protected LoginTotpPage loginTotpPage; - @Page - protected AccountTotpPage accountTotpSetupPage; - @Page protected LoginConfigTotpPage configureTotpRequiredActionPage; private TimeBasedOTP totp = new TimeBasedOTP(); + + @BeforeClass public static void checkNotMapStorage() { ProfileAssume.assumeFeatureDisabled(Feature.MAP_STORAGE); @@ -105,27 +101,29 @@ public class BackwardsCompatibilityUserStorageTest extends AbstractAuthTest { } protected String addComponent(ComponentRepresentation component) { - Response resp = testRealmResource().components().add(component); + Response resp = testRealm().components().add(component); String id = ApiUtil.getCreatedId(resp); getCleanup().addComponentId(id); return id; } - private void loginSuccessAndLogout(String username, String password) { - testRealmAccountPage.navigateTo(); - loginPage.login(username, password); - assertCurrentUrlStartsWith(testRealmAccountPage); - testRealmAccountPage.logOut(); + private void loginSuccessAndLogout(String username, String password) throws URISyntaxException, IOException { + TestAppHelper testAppHelper = new TestAppHelper(oauth, loginPage, appPage); + + testAppHelper.login(username, password); + appPage.assertCurrent(); + + assertTrue(testAppHelper.logout()); } public void loginBadPassword(String username) { - testRealmAccountPage.navigateTo(); - testRealmLoginPage.form().login(username, "badpassword"); - assertCurrentUrlDoesntStartWith(testRealmAccountPage); + loginPage.open(); + loginPage.login(username, "badpassword"); + loginPage.assertCurrent(); } @Test - public void testLoginSuccess() { + public void testLoginSuccess() throws URISyntaxException, IOException { addUserAndResetPassword("tbrady", "goat"); addUserAndResetPassword("tbrady2", "goat2"); @@ -139,7 +137,7 @@ public class BackwardsCompatibilityUserStorageTest extends AbstractAuthTest { UserRepresentation user = new UserRepresentation(); user.setEnabled(true); user.setUsername(username); - Response response = testRealmResource().users().create(user); + Response response = testRealm().users().create(user); String userId = ApiUtil.getCreatedId(response); Assert.assertEquals(backwardsCompProviderId, new StorageId(userId).getProviderId()); @@ -150,14 +148,14 @@ public class BackwardsCompatibilityUserStorageTest extends AbstractAuthTest { passwordRep.setValue(password); passwordRep.setTemporary(false); - testRealmResource().users().get(userId).resetPassword(passwordRep); + testRealm().users().get(userId).resetPassword(passwordRep); return userId; } @Test - public void testOTPUpdateAndLogin() { + public void testOTPUpdateAndLogin() throws URISyntaxException, IOException { String userId = addUserAndResetPassword("otp1", "pass"); getCleanup().addUserId(userId); @@ -171,58 +169,55 @@ public class BackwardsCompatibilityUserStorageTest extends AbstractAuthTest { assertUserDontHaveDBCredentials(); assertUserHasOTPCredentialInUserStorage(true); - // Authenticate as the user with the hardcoded OTP. Should be supported - loginPage.login("otp1", "pass"); - loginTotpPage.assertCurrent(); - loginTotpPage.login("123456"); + TestAppHelper testAppHelper = new TestAppHelper(oauth, loginPage, appPage); - assertCurrentUrlStartsWith(testRealmAccountPage); - testRealmAccountPage.logOut(); + // Authenticate as the user with the hardcoded OTP. Should be supported + testAppHelper.startLogin("otp1", "pass"); + loginTotpPage.login("123456"); + testAppHelper.completeLogin(); + + appPage.assertCurrent(); + + testAppHelper.logout(); // Authenticate as the user with bad OTP - loginPage.login("otp1", "pass"); + testAppHelper.startLogin("otp1", "pass"); loginTotpPage.assertCurrent(); loginTotpPage.login("7123456"); - assertCurrentUrlDoesntStartWith(testRealmAccountPage); + loginTotpPage.assertCurrent(); Assert.assertNotNull(loginTotpPage.getInputError()); // Authenticate as the user with correct OTP loginTotpPage.login(totp.generateTOTP(totpSecret)); - assertCurrentUrlStartsWith(testRealmAccountPage); - testRealmAccountPage.logOut(); + testAppHelper.completeLogin(); + appPage.assertCurrent(); + + assertTrue(testAppHelper.logout()); } @Test - public void testOTPSetupThroughAccountMgmtAndLogin() { + public void testOTPSetupThroughAccountMgmtAndLogin() throws URISyntaxException, IOException { String userId = addUserAndResetPassword("otp1", "pass"); getCleanup().addUserId(userId); - // Login as user to account mgmt - accountTotpSetupPage.open(); - loginPage.login("otp1", "pass"); - // Setup OTP - String totpSecret = accountTotpSetupPage.getTotpSecret(); - accountTotpSetupPage.configure(totp.generateTOTP(totpSecret)); + String totpSecret = setupOTPForUserWithRequiredAction(userId); assertUserDontHaveDBCredentials(); assertUserHasOTPCredentialInUserStorage(true); - // Logout and assert user can login with hardcoded OTP - accountTotpSetupPage.logout(); - loginPage.login("otp1", "pass"); - loginTotpPage.login("123456"); - assertCurrentUrlStartsWith(testRealmAccountPage); + TestAppHelper testAppHelper = new TestAppHelper(oauth, loginPage, loginTotpPage, appPage); + + // Login as user to account mgmt + assertTrue(testAppHelper.login("otp1", "pass", "123456")); // Logout and assert user can login with valid credential - accountTotpSetupPage.logout(); - loginPage.login("otp1", "pass"); - loginTotpPage.login(totp.generateTOTP(totpSecret)); - assertCurrentUrlStartsWith(testRealmAccountPage); + testAppHelper.logout(); + assertTrue(testAppHelper.login("otp1", "pass", totp.generateTOTP(totpSecret))); + testAppHelper.logout(); - // Delete OTP credential in account console - accountTotpSetupPage.removeTotp(); - accountTotpSetupPage.logout(); + // Disable OTP credential in account console + testRealm().users().get(userId).disableCredentialType(Collections.singletonList(OTPCredentialModel.TYPE)); assertUserDontHaveDBCredentials(); assertUserHasOTPCredentialInUserStorage(false); @@ -232,7 +227,7 @@ public class BackwardsCompatibilityUserStorageTest extends AbstractAuthTest { } @Test - public void testDisableCredentialsInUserStorage() { + public void testDisableCredentialsInUserStorage() throws URISyntaxException, IOException { String userId = addUserAndResetPassword("otp1", "pass"); getCleanup().addUserId(userId); @@ -243,13 +238,13 @@ public class BackwardsCompatibilityUserStorageTest extends AbstractAuthTest { assertUserDontHaveDBCredentials(); assertUserHasOTPCredentialInUserStorage(true); - UserResource user = testRealmResource().users().get(userId); + UserResource user = testRealm().users().get(userId); // Disable OTP credential for the user through REST endpoint UserRepresentation userRep = user.toRepresentation(); - Assert.assertNames(userRep.getDisableableCredentialTypes(), CredentialModel.OTP); + Assert.assertNames(userRep.getDisableableCredentialTypes(), OTPCredentialModel.TYPE); - user.disableCredentialType(Collections.singletonList(CredentialModel.OTP)); + user.disableCredentialType(Collections.singletonList(OTPCredentialModel.TYPE)); // User don't have OTP credential in userStorage anymore assertUserDontHaveDBCredentials(); @@ -266,29 +261,32 @@ public class BackwardsCompatibilityUserStorageTest extends AbstractAuthTest { getCleanup().addUserId(userId); // Uses same parameters as admin console when searching users - List users = testRealmResource().users().search("searching", 0, 20, true); + List users = testRealm().users().search("searching", 0, 20, true); Assert.assertNames(users, "searching"); } // return created totpSecret - private String setupOTPForUserWithRequiredAction(String userId) { + private String setupOTPForUserWithRequiredAction(String userId) throws URISyntaxException, IOException { // Add required action to the user to reset OTP - UserResource user = testRealmResource().users().get(userId); + UserResource user = testRealm().users().get(userId); UserRepresentation userRep = user.toRepresentation(); userRep.setRequiredActions(Arrays.asList(UserModel.RequiredAction.CONFIGURE_TOTP.toString())); user.update(userRep); + TestAppHelper testAppHelper = new TestAppHelper(oauth, loginPage, appPage); + // Login as the user and setup OTP - testRealmAccountPage.navigateTo(); - loginPage.login("otp1", "pass"); + testAppHelper.startLogin("otp1", "pass"); configureTotpRequiredActionPage.assertCurrent(); String totpSecret = configureTotpRequiredActionPage.getTotpSecret(); configureTotpRequiredActionPage.configure(totp.generateTOTP(totpSecret)); - assertCurrentUrlStartsWith(testRealmAccountPage); + appPage.assertCurrent(); + + testAppHelper.completeLogin(); // Logout - testRealmAccountPage.logOut(); + assertTrue(testAppHelper.logout()); return totpSecret; } @@ -310,4 +308,9 @@ public class BackwardsCompatibilityUserStorageTest extends AbstractAuthTest { }, Boolean.class); Assert.assertEquals(expectedUserHasOTP, hasUserOTP); } + + @Override + public void configureTestRealm(RealmRepresentation testRealm) { + + } } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ResetCredentialsAlternativeFlowsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ResetCredentialsAlternativeFlowsTest.java index a1e0859c9a..bb29150dce 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ResetCredentialsAlternativeFlowsTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ResetCredentialsAlternativeFlowsTest.java @@ -18,14 +18,12 @@ package org.keycloak.testsuite.forms; -import org.hamcrest.Matchers; import org.jboss.arquillian.graphene.page.Page; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.keycloak.OAuth2Constants; -import org.keycloak.common.Profile; import org.keycloak.models.UserManager; import org.keycloak.models.UserModel; import org.keycloak.models.utils.DefaultAuthenticationFlows; @@ -34,11 +32,9 @@ import org.keycloak.representations.idm.AuthenticationFlowRepresentation; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RequiredActionProviderRepresentation; import org.keycloak.representations.idm.UserRepresentation; -import org.keycloak.testsuite.AbstractTestRealmKeycloakTest; +import org.keycloak.testsuite.actions.AbstractAppInitiatedActionTest; import org.keycloak.testsuite.admin.ApiUtil; import org.keycloak.testsuite.admin.authentication.AbstractAuthenticationTest; -import org.keycloak.testsuite.arquillian.annotation.DisableFeature; -import org.keycloak.testsuite.pages.AccountTotpPage; import org.keycloak.testsuite.pages.AppPage; import org.keycloak.testsuite.pages.ErrorPage; import org.keycloak.testsuite.pages.LoginConfigTotpPage; @@ -50,23 +46,13 @@ import org.keycloak.testsuite.pages.LoginUsernameOnlyPage; import org.keycloak.testsuite.pages.LogoutConfirmPage; import org.keycloak.testsuite.pages.PasswordPage; import org.keycloak.testsuite.pages.RegisterPage; -import org.keycloak.testsuite.util.FlowUtil; -import org.keycloak.testsuite.util.GreenMailRule; -import org.keycloak.testsuite.util.MailUtils; -import org.keycloak.testsuite.util.OAuthClient; -import org.keycloak.testsuite.util.URLUtils; -import org.keycloak.testsuite.util.UserBuilder; -import org.openqa.selenium.By; -import org.openqa.selenium.WebElement; +import org.keycloak.testsuite.util.*; import javax.mail.internet.MimeMessage; import java.util.Arrays; import java.util.List; -import java.util.regex.Pattern; -import java.util.stream.Collectors; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; /** * Test for the various alternatives of reset-credentials flow or browser flow (non-default setup of the flows) @@ -74,7 +60,7 @@ import static org.junit.Assert.assertThat; * @author Marek Posolda * @author Jan Lieskovsky */ -public class ResetCredentialsAlternativeFlowsTest extends AbstractTestRealmKeycloakTest { +public class ResetCredentialsAlternativeFlowsTest extends AbstractAppInitiatedActionTest { private String userId; @@ -99,9 +85,6 @@ public class ResetCredentialsAlternativeFlowsTest extends AbstractTestRealmKeycl @Page protected LoginPasswordUpdatePage updatePasswordPage; - @Page - protected AccountTotpPage accountTotpPage; - @Page protected LoginConfigTotpPage totpPage; @@ -136,6 +119,11 @@ public class ResetCredentialsAlternativeFlowsTest extends AbstractTestRealmKeycl getCleanup().addUserId(userId); } + @Override + public String getAiaAction() { + return UserModel.RequiredAction.CONFIGURE_TOTP.name(); + } + // Test with default reset-credentials flow and alternative browser flow with separate username and password screen. // @@ -236,7 +224,7 @@ public class ResetCredentialsAlternativeFlowsTest extends AbstractTestRealmKeycl loginUsernameOnlyPage.open(); loginUsernameOnlyPage.login("login-test"); - Assert.assertTrue(passwordPage.isCurrent()); + passwordPage.assertCurrent(); // Click "Forget password" passwordPage.clickResetPassword(); @@ -272,7 +260,7 @@ public class ResetCredentialsAlternativeFlowsTest extends AbstractTestRealmKeycl loginUsernameOnlyPage.open(); loginUsernameOnlyPage.login(username); - Assert.assertTrue(passwordPage.isCurrent()); + passwordPage.assertCurrent(); // Click "Forget password" passwordPage.clickResetPassword(); @@ -344,7 +332,6 @@ public class ResetCredentialsAlternativeFlowsTest extends AbstractTestRealmKeycl @Test - @DisableFeature(value = Profile.Feature.ACCOUNT2, skipRestart = true) // TODO remove this (KEYCLOAK-16228) public void resetCredentialsVerifyCustomOtpLabelSetProperly() { try { // Make a copy of the default Reset Credentials flow, but: @@ -358,14 +345,17 @@ public class ResetCredentialsAlternativeFlowsTest extends AbstractTestRealmKeycl // Login & set up the initial OTP code for the user loginPage.open(); - loginPage.login("login@test.com", "password"); + loginPage.login("login-test", "password"); String code = new OAuthClient.AuthorizationEndpointResponse(oauth).getCode(); OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password"); - accountTotpPage.open(); - Assert.assertTrue(accountTotpPage.isCurrent()); String customOtpLabel = "my-original-otp-label"; - accountTotpPage.configure(totp.generateTOTP(accountTotpPage.getTotpSecret()), customOtpLabel); + + // Setup OTP + doAIA(); + totpPage.assertCurrent(); + totpPage.configure(totp.generateTOTP(totpPage.getTotpSecret()), customOtpLabel); + assertKcActionStatus(SUCCESS); // Logout oauth.idTokenHint(response.getIdToken()).openLogout(); @@ -375,26 +365,18 @@ public class ResetCredentialsAlternativeFlowsTest extends AbstractTestRealmKeycl loginPage.resetPassword(); // Should be on reset password page now. Provide email of the user & click Submit button - Assert.assertTrue(resetPasswordPage.isCurrent()); - resetPasswordPage.changePassword("login@test.com"); - - // Since 'Send Reset Email' & 'Reset Password' authenticators got removed above, - // the next action should be 'Reset OTP' -- verify that - Assert.assertTrue(totpPage.isCurrent()); + resetPasswordPage.assertCurrent(); + resetPasswordPage.changePassword("login-test"); // Provide updated form of the OTP label, to be used within 'Reset OTP' (next) step customOtpLabel = "my-reset-otp-label"; // Reset OTP label to a custom value as part of Reset Credentials flow - totpPage.configure(totp.generateTOTP(totpPage.getTotpSecret()), customOtpLabel); + AccountHelper.updateTotpUserLabel(testRealm(), "login-test", customOtpLabel); // Open OTP Authenticator account page - accountTotpPage.open(); - Assert.assertTrue(accountTotpPage.isCurrent()); - - // Verify OTP authenticator with requested label was created - String pageSource = driver.getPageSource(); - Assert.assertTrue(pageSource.contains(customOtpLabel)); + // Check if OTP credential is present + Assert.assertTrue(AccountHelper.totpUserLabelComparator(testRealm(), "login-test", customOtpLabel)); // Undo setup changes performed within the test } finally { @@ -406,7 +388,6 @@ public class ResetCredentialsAlternativeFlowsTest extends AbstractTestRealmKeycl // KEYCLOAK-12168 Verify the 'Device Name' label is optional for the first OTP credential created // (either via Account page or by registering new user), but required for each next created OTP credential @Test - @DisableFeature(value = Profile.Feature.ACCOUNT2, skipRestart = true) // TODO remove this (KEYCLOAK-16228) public void deviceNameOptionalForFirstOTPCredentialButRequiredForEachNextOne() { // Enable 'Default Action' on 'Configure OTP' RA for the 'test' realm RequiredActionProviderRepresentation otpRequiredAction = testRealm().flows().getRequiredAction("CONFIGURE_TOTP"); @@ -428,29 +409,17 @@ public class ResetCredentialsAlternativeFlowsTest extends AbstractTestRealmKeycl // Login & set up the initial OTP code for the user loginPage.open(); loginPage.login("login@test.com", "password"); - accountTotpPage.open(); - Assert.assertTrue(accountTotpPage.isCurrent()); - - String pageSource = driver.getPageSource(); - // Check the One-time code label is followed by asterisk character (since always required) - final String oneTimeCodeLabelFollowedByAsterisk = "(?s)