diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/drone/Different.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/drone/Different.java new file mode 100644 index 0000000000..dc78e30d5f --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/drone/Different.java @@ -0,0 +1,38 @@ +/* + * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @author tags. All rights reserved. + * + * 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.drone; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.jboss.arquillian.drone.api.annotation.Qualifier; + +/** + * Taken from Drone example https://docs.jboss.org/author/display/ARQ/Drone + * This allows you to have more than one instance of a Drone WebDriver. + * + * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. + */ + +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.FIELD, ElementType.PARAMETER }) +@Qualifier +public @interface Different { +} diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/AppPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/AppPage.java index 2badf74eb2..406ab08ecb 100755 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/AppPage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/AppPage.java @@ -30,7 +30,7 @@ import javax.ws.rs.core.UriBuilder; public class AppPage extends AbstractPage { public static final String AUTH_SERVER_URL = "http://localhost:8180/auth"; - public static final String baseUrl = "http://localhost:8180/auth/realms/master/app"; + public static final String baseUrl = "http://localhost:8180/auth/realms/master/app/auth"; @FindBy(id = "account") private WebElement accountLink; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/TestRealmKeycloakTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/TestRealmKeycloakTest.java index 55cf15b701..0e41cee957 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/TestRealmKeycloakTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/TestRealmKeycloakTest.java @@ -21,6 +21,8 @@ import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.RealmRepresentation; import java.util.List; +import org.keycloak.admin.client.resource.RealmResource; +import org.keycloak.representations.idm.UserRepresentation; import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson; @@ -32,6 +34,36 @@ import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson; */ public abstract class TestRealmKeycloakTest extends AbstractKeycloakTest { + protected UserRepresentation findUserInRealmRep(RealmRepresentation testRealm, String userName) { + for (UserRepresentation user : testRealm.getUsers()) { + if (user.getUsername().equals(userName)) return user; + } + + return null; + } + + protected ClientRepresentation findClientInRealmRep(RealmRepresentation testRealm, String clientId) { + for (ClientRepresentation client : testRealm.getClients()) { + if (client.getClientId().equals(clientId)) return client; + } + + return null; + } + + protected RealmResource testRealm() { + return adminClient.realm("test"); + } + + protected UserRepresentation findUser(String userNameOrEmail) { + List repList = testRealm().users().search(userNameOrEmail, -1, -1); + if (repList.size() != 1) throw new IllegalStateException("User search expected one result. Found " + repList.size() + " users."); + return repList.get(0); + } + + protected void updateUser(UserRepresentation user) { + testRealm().users().get(user.getId()).update(user); + } + protected ClientRepresentation findTestApp(RealmRepresentation testRealm) { for (ClientRepresentation client : testRealm.getClients()) { if (client.getClientId().equals("test-app")) return client; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ProvidersTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ProvidersTest.java index 9f679e35c2..0580062269 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ProvidersTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ProvidersTest.java @@ -74,6 +74,8 @@ public class ProvidersTest extends AbstractAuthenticationTest { "Validates client based on signed JWT issued by client and signed with the Client private key"); addProviderInfo(expected, "client-secret", "Client Id and Secret", "Validates client based on 'client_id' and " + "'client_secret' sent either in request parameters or in 'Authorization: Basic' header"); + addProviderInfo(expected, "testsuite-client-passthrough", "Testsuite Dummy Client Validation", "Testsuite dummy authenticator, " + + "which automatically authenticates hardcoded client (like 'test-app' )"); compareProviders(expected, result); } @@ -119,6 +121,10 @@ public class ProvidersTest extends AbstractAuthenticationTest { "Will also set it if execution is OPTIONAL and the OTP is currently configured for it."); addProviderInfo(result, "reset-password", "Reset Password", "Sets the Update Password required action if execution is REQUIRED. " + "Will also set it if execution is OPTIONAL and the password is currently configured for it."); + addProviderInfo(result, "testsuite-dummy-passthrough", "Testsuite Dummy Pass Thru", + "Testsuite Dummy authenticator. Just passes through and is hardcoded to a specific user"); + addProviderInfo(result, "testsuite-dummy-registration", "Testsuite Dummy Pass Thru", + "Testsuite Dummy authenticator. Just passes through and is hardcoded to a specific user"); return result; } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/AbstractFlowTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/AbstractFlowTest.java new file mode 100644 index 0000000000..f83104cd05 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/AbstractFlowTest.java @@ -0,0 +1,42 @@ +/* + * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @author tags. All rights reserved. + * + * 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.forms; + +import org.keycloak.representations.idm.AuthenticationFlowRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.testsuite.TestRealmKeycloakTest; + +/** + * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. + */ +public abstract class AbstractFlowTest extends TestRealmKeycloakTest { + + protected AuthenticationFlowRepresentation findFlowByAlias(String alias) { + for (AuthenticationFlowRepresentation rep : testRealm().flows().getFlows()) { + if (rep.getAlias().equals(alias)) return rep; + } + + return null; + } + + protected void setRegistrationFlow(AuthenticationFlowRepresentation flow) { + RealmRepresentation realm = testRealm().toRepresentation(); + realm.setRegistrationFlow(flow.getAlias()); + testRealm().update(realm); + } +} diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/BruteForceTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/BruteForceTest.java old mode 100755 new mode 100644 similarity index 89% rename from testsuite/integration/src/test/java/org/keycloak/testsuite/forms/BruteForceTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/BruteForceTest.java index 481ea40cb8..a22c359d59 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/BruteForceTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/BruteForceTest.java @@ -18,94 +18,78 @@ package org.keycloak.testsuite.forms; import org.junit.Assert; import org.junit.Before; -import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.keycloak.events.Details; import org.keycloak.events.Errors; import org.keycloak.models.Constants; -import org.keycloak.models.RealmModel; -import org.keycloak.models.UserCredentialModel; -import org.keycloak.models.UserModel; import org.keycloak.models.utils.TimeBasedOTP; import org.keycloak.representations.idm.CredentialRepresentation; -import org.keycloak.services.managers.RealmManager; import org.keycloak.testsuite.AssertEvents; -import org.keycloak.testsuite.OAuthClient; import org.keycloak.testsuite.pages.AppPage; import org.keycloak.testsuite.pages.AppPage.RequestType; import org.keycloak.testsuite.pages.LoginPage; import org.keycloak.testsuite.pages.LoginTotpPage; import org.keycloak.testsuite.pages.RegisterPage; -import org.keycloak.testsuite.rule.GreenMailRule; -import org.keycloak.testsuite.rule.KeycloakRule; -import org.keycloak.testsuite.rule.KeycloakRule.KeycloakSetup; -import org.keycloak.testsuite.rule.WebResource; -import org.keycloak.testsuite.rule.WebRule; -import org.openqa.selenium.WebDriver; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; import java.net.MalformedURLException; -import java.util.Collections; +import org.jboss.arquillian.graphene.page.Page; +import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.representations.idm.UserRepresentation; +import org.keycloak.testsuite.TestRealmKeycloakTest; +import org.keycloak.testsuite.util.GreenMailRule; +import org.keycloak.testsuite.util.OAuthClient; /** * @author Stian Thorgersen + * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. */ -public class BruteForceTest { +public class BruteForceTest extends TestRealmKeycloakTest { - @ClassRule - public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakSetup() { + @Override + public void configureTestRealm(RealmRepresentation testRealm) { + UserRepresentation user = findUserInRealmRep(testRealm, "test-user@localhost"); + CredentialRepresentation credRep = new CredentialRepresentation(); + credRep.setType(CredentialRepresentation.TOTP); + credRep.setValue("totpSecret"); + user.getCredentials().add(credRep); + user.setTotp(Boolean.TRUE); - @Override - public void config(RealmManager manager, RealmModel defaultRealm, RealmModel appRealm) { - UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm); + testRealm.setBruteForceProtected(true); + testRealm.setFailureFactor(2); - UserCredentialModel credentials = new UserCredentialModel(); - credentials.setType(CredentialRepresentation.TOTP); - credentials.setValue("totpSecret"); - user.updateCredential(credentials); + findClientInRealmRep(testRealm, "test-app").setDirectAccessGrantsEnabled(true); + } - user.setOtpEnabled(true); - appRealm.setEventsListeners(Collections.singleton("dummy")); + @Before + public void config() { - appRealm.setBruteForceProtected(true); - appRealm.setFailureFactor(2); + } - appRealm.getClientByClientId("test-app").setDirectAccessGrantsEnabled(true); - } - - }); @Rule - public AssertEvents events = new AssertEvents(keycloakRule); - - @Rule - public WebRule webRule = new WebRule(this); + public AssertEvents events = new AssertEvents(this); @Rule public GreenMailRule greenMail = new GreenMailRule(); - @WebResource - protected WebDriver driver; - - @WebResource + @Page protected AppPage appPage; - @WebResource + @Page protected LoginPage loginPage; - @WebResource + @Page private RegisterPage registerPage; - @WebResource + @Page protected LoginTotpPage loginTotpPage; - @WebResource - protected OAuthClient oauth; - private TimeBasedOTP totp = new TimeBasedOTP(); private int lifespan; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/CustomFlowTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/CustomFlowTest.java new file mode 100644 index 0000000000..8169835628 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/CustomFlowTest.java @@ -0,0 +1,272 @@ +/* + * 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.forms; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +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.admin.client.resource.AuthenticationManagementResource; +import org.keycloak.authentication.AuthenticationFlow; +import org.keycloak.events.Details; +import org.keycloak.events.Errors; +import org.keycloak.models.AuthenticationExecutionModel; +import org.keycloak.representations.AccessToken; +import org.keycloak.representations.RefreshToken; +import org.keycloak.representations.idm.AuthenticationExecutionInfoRepresentation; +import org.keycloak.representations.idm.AuthenticationExecutionRepresentation; +import org.keycloak.representations.idm.AuthenticationFlowRepresentation; +import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.representations.idm.UserRepresentation; +import org.keycloak.testsuite.AssertEvents; +import org.keycloak.testsuite.TestRealmKeycloakTest; +import org.keycloak.testsuite.pages.AppPage; +import org.keycloak.testsuite.pages.AppPage.RequestType; +import org.keycloak.testsuite.pages.ErrorPage; +import org.keycloak.testsuite.pages.LoginPage; +import org.keycloak.testsuite.pages.LoginPasswordUpdatePage; +import org.keycloak.testsuite.pages.RegisterPage; +import org.keycloak.testsuite.util.ClientBuilder; +import org.keycloak.testsuite.util.ExecutionBuilder; +import org.keycloak.testsuite.util.FlowBuilder; +import org.keycloak.testsuite.util.OAuthClient; +import org.keycloak.testsuite.util.UserBuilder; + +import static org.junit.Assert.assertEquals; + +/** + * @author Stian Thorgersen + * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. + */ +public class CustomFlowTest extends AbstractFlowTest { + + @Override + public void configureTestRealm(RealmRepresentation testRealm) { + UserRepresentation user = UserBuilder.create() + .username("login-test") + .email("login@test.com") + .enabled(true) + .build(); + testRealm.getUsers().add(user); + + // Set passthrough clientAuthenticator for our clients + ClientRepresentation dummyClient = ClientBuilder.create() + .clientId("dummy-client") + .name("dummy-client") + .authenticatorType(PassThroughClientAuthenticator.PROVIDER_ID) + .directAccessGrants() + .build(); + testRealm.getClients().add(dummyClient); + + ClientRepresentation testApp = findClientInRealmRep(testRealm, "test-app"); + testApp.setClientAuthenticatorType(PassThroughClientAuthenticator.PROVIDER_ID); + testApp.setDirectAccessGrantsEnabled(true); + } + + @Before + public void configureFlows() { + userId = findUser("login-test").getId(); + + AuthenticationFlowRepresentation flow = FlowBuilder.create() + .alias("dummy") + .description("dummy pass through flow") + .providerId("basic-flow") + .topLevel(true) + .builtIn(false) + .build(); + testRealm().flows().createFlow(flow); + + RealmRepresentation realm = testRealm().toRepresentation(); + realm.setBrowserFlow(flow.getAlias()); + realm.setDirectGrantFlow(flow.getAlias()); + testRealm().update(realm); + + // refresh flow to find its id + flow = findFlowByAlias(flow.getAlias()); + + AuthenticationExecutionRepresentation execution = ExecutionBuilder.create() + .parentFlow(flow.getId()) + .requirement(AuthenticationExecutionModel.Requirement.REQUIRED.toString()) + .authenticator(PassThroughAuthenticator.PROVIDER_ID) + .priority(10) + .authenticatorFlow(false) + .build(); + testRealm().flows().addExecution(execution); + + flow = FlowBuilder.create() + .alias("dummy registration") + .description("dummy pass through registration") + .providerId("basic-flow") + .topLevel(true) + .builtIn(false) + .build(); + testRealm().flows().createFlow(flow); + + setRegistrationFlow(flow); + + // refresh flow to find its id + flow = findFlowByAlias(flow.getAlias()); + + execution = ExecutionBuilder.create() + .parentFlow(flow.getId()) + .requirement(AuthenticationExecutionModel.Requirement.REQUIRED.toString()) + .authenticator(PassThroughRegistration.PROVIDER_ID) + .priority(10) + .authenticatorFlow(false) + .build(); + testRealm().flows().addExecution(execution); + + AuthenticationFlowRepresentation clientFlow = FlowBuilder.create() + .alias("client-dummy") + .description("dummy pass through flow") + .providerId(AuthenticationFlow.CLIENT_FLOW) + .topLevel(true) + .builtIn(false) + .build(); + testRealm().flows().createFlow(clientFlow); + + realm = testRealm().toRepresentation(); + realm.setClientAuthenticationFlow(clientFlow.getAlias()); + testRealm().update(realm); + + // refresh flow to find its id + clientFlow = findFlowByAlias(clientFlow.getAlias()); + + execution = ExecutionBuilder.create() + .parentFlow(clientFlow.getId()) + .requirement(AuthenticationExecutionModel.Requirement.REQUIRED.toString()) + .authenticator(PassThroughClientAuthenticator.PROVIDER_ID) + .priority(10) + .authenticatorFlow(false) + .build(); + testRealm().flows().addExecution(execution); + } + + + @Rule + public AssertEvents events = new AssertEvents(this); + + @Page + protected AppPage appPage; + + @Page + protected LoginPage loginPage; + + @Page + protected ErrorPage errorPage; + + @Page + protected LoginPasswordUpdatePage updatePasswordPage; + + @Page + protected RegisterPage registerPage; + + private static String userId; + + @Test + public void loginSuccess() { + + PassThroughAuthenticator.username = "login-test"; + + oauth.openLoginForm(); + + Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType()); + Assert.assertNotNull(oauth.getCurrentQuery().get(OAuth2Constants.CODE)); + + events.expectLogin().user(userId).detail(Details.USERNAME, "login-test").assertEvent(); + } + + @Test + public void grantTest() throws Exception { + PassThroughAuthenticator.username = "login-test"; + grantAccessToken("test-app", "login-test"); + } + + @Test + public void clientAuthTest() throws Exception { + PassThroughClientAuthenticator.clientId = "dummy-client"; + PassThroughAuthenticator.username = "login-test"; + grantAccessToken("dummy-client", "login-test"); + + PassThroughClientAuthenticator.clientId = "test-app"; + grantAccessToken("test-app", "login-test"); + + PassThroughClientAuthenticator.clientId = "unknown"; + OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("password", "test-user", "password"); + assertEquals(400, response.getStatusCode()); + assertEquals("unauthorized_client", response.getError()); + + events.expectLogin() + .client((String) null) + .user((String) null) + .session((String) null) + .removeDetail(Details.CODE_ID) + .removeDetail(Details.REDIRECT_URI) + .removeDetail(Details.CONSENT) + .error(Errors.INVALID_CLIENT_CREDENTIALS) + .assertEvent(); + } + + + private void grantAccessToken(String clientId, String login) throws Exception { + + OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("password", login, "password"); + + assertEquals(200, response.getStatusCode()); + + AccessToken accessToken = oauth.verifyToken(response.getAccessToken()); + RefreshToken refreshToken = oauth.verifyRefreshToken(response.getRefreshToken()); + + events.expectLogin() + .client(clientId) + .user(userId) + .session(accessToken.getSessionState()) + .detail(Details.GRANT_TYPE, OAuth2Constants.PASSWORD) + .detail(Details.TOKEN_ID, accessToken.getId()) + .detail(Details.REFRESH_TOKEN_ID, refreshToken.getId()) + .detail(Details.USERNAME, login) + .detail(Details.CLIENT_AUTH_METHOD, PassThroughClientAuthenticator.PROVIDER_ID) + .removeDetail(Details.CODE_ID) + .removeDetail(Details.REDIRECT_URI) + .removeDetail(Details.CONSENT) + .assertEvent(); + + assertEquals(accessToken.getSessionState(), refreshToken.getSessionState()); + + OAuthClient.AccessTokenResponse refreshedResponse = oauth.doRefreshTokenRequest(response.getRefreshToken(), "password"); + + AccessToken refreshedAccessToken = oauth.verifyToken(refreshedResponse.getAccessToken()); + RefreshToken refreshedRefreshToken = oauth.verifyRefreshToken(refreshedResponse.getRefreshToken()); + + assertEquals(accessToken.getSessionState(), refreshedAccessToken.getSessionState()); + assertEquals(accessToken.getSessionState(), refreshedRefreshToken.getSessionState()); + + events.expectRefresh(refreshToken.getId(), refreshToken.getSessionState()) + .user(userId) + .client(clientId) + .detail(Details.CLIENT_AUTH_METHOD, PassThroughClientAuthenticator.PROVIDER_ID) + .assertEvent(); + } + + +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/CustomRegistrationFlowTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/CustomRegistrationFlowTest.java new file mode 100755 index 0000000000..79b2738307 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/CustomRegistrationFlowTest.java @@ -0,0 +1,107 @@ +/* + * 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.forms; + +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.models.AuthenticationExecutionModel; +import org.keycloak.representations.idm.AuthenticationExecutionRepresentation; +import org.keycloak.representations.idm.AuthenticationFlowRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.testsuite.AssertEvents; +import org.keycloak.testsuite.pages.AppPage; +import org.keycloak.testsuite.pages.AppPage.RequestType; +import org.keycloak.testsuite.pages.ErrorPage; +import org.keycloak.testsuite.pages.LoginPage; +import org.keycloak.testsuite.pages.LoginPasswordUpdatePage; +import org.keycloak.testsuite.pages.RegisterPage; +import org.keycloak.testsuite.util.ExecutionBuilder; +import org.keycloak.testsuite.util.FlowBuilder; + +/** + * @author Stian Thorgersen + * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. + */ +public class CustomRegistrationFlowTest extends AbstractFlowTest { + + @Override + public void configureTestRealm(RealmRepresentation testRealm) { + } + + @Before + public void configureFlow() { + AuthenticationFlowRepresentation flow = FlowBuilder.create() + .alias("dummy registration") + .description("dummy pass through registration") + .providerId("basic-flow") + .topLevel(true) + .builtIn(false) + .build(); + testRealm().flows().createFlow(flow); + + setRegistrationFlow(flow); + + // refresh flow to find its id + flow = findFlowByAlias(flow.getAlias()); + + AuthenticationExecutionRepresentation execution = ExecutionBuilder.create() + .parentFlow(flow.getId()) + .requirement(AuthenticationExecutionModel.Requirement.REQUIRED.toString()) + .authenticator(PassThroughRegistration.PROVIDER_ID) + .priority(10) + .authenticatorFlow(false) + .build(); + + testRealm().flows().addExecution(execution); + } + + @Rule + public AssertEvents events = new AssertEvents(this); + + @Page + protected AppPage appPage; + + @Page + protected LoginPage loginPage; + + @Page + protected ErrorPage errorPage; + + @Page + protected LoginPasswordUpdatePage updatePasswordPage; + + @Page + protected RegisterPage registerPage; + + @Test + public void registerUserSuccess() { + loginPage.open(); + loginPage.clickRegister(); + + Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType()); + + String userId = events.expectRegister(PassThroughRegistration.username, PassThroughRegistration.email).assertEvent().getUserId(); + events.expectLogin().detail("username", PassThroughRegistration.username).user(userId).assertEvent(); + } + + + + +} diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginHotpTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LoginHotpTest.java old mode 100755 new mode 100644 similarity index 66% rename from testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginHotpTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LoginHotpTest.java index caf1cd7904..8964040e8e --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginHotpTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LoginHotpTest.java @@ -18,82 +18,58 @@ package org.keycloak.testsuite.forms; import org.junit.Assert; import org.junit.Before; -import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.keycloak.events.Details; import org.keycloak.models.OTPPolicy; -import org.keycloak.models.RealmModel; -import org.keycloak.models.UserCredentialModel; -import org.keycloak.models.UserModel; import org.keycloak.models.utils.HmacOTP; -import org.keycloak.representations.idm.CredentialRepresentation; -import org.keycloak.services.managers.RealmManager; import org.keycloak.testsuite.AssertEvents; import org.keycloak.testsuite.pages.AppPage; import org.keycloak.testsuite.pages.AppPage.RequestType; import org.keycloak.testsuite.pages.LoginPage; import org.keycloak.testsuite.pages.LoginTotpPage; -import org.keycloak.testsuite.rule.GreenMailRule; -import org.keycloak.testsuite.rule.KeycloakRule; -import org.keycloak.testsuite.rule.KeycloakRule.KeycloakSetup; -import org.keycloak.testsuite.rule.WebResource; -import org.keycloak.testsuite.rule.WebRule; -import org.openqa.selenium.WebDriver; import java.net.MalformedURLException; -import java.util.Collections; +import org.jboss.arquillian.graphene.page.Page; +import org.keycloak.models.UserCredentialModel; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.representations.idm.UserRepresentation; +import org.keycloak.testsuite.TestRealmKeycloakTest; +import org.keycloak.testsuite.util.GreenMailRule; +import org.keycloak.testsuite.util.UserBuilder; /** * @author Stian Thorgersen + * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. */ -public class LoginHotpTest { +public class LoginHotpTest extends TestRealmKeycloakTest { public static OTPPolicy policy; - @ClassRule - public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakSetup() { - @Override - public void config(RealmManager manager, RealmModel defaultRealm, RealmModel appRealm) { - UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm); - policy = appRealm.getOTPPolicy(); - policy.setType(UserCredentialModel.HOTP); - policy.setLookAheadWindow(2); - appRealm.setOTPPolicy(policy); - - UserCredentialModel credentials = new UserCredentialModel(); - credentials.setType(CredentialRepresentation.HOTP); - credentials.setValue("hotpSecret"); - user.updateCredential(credentials); - - user.setOtpEnabled(true); - appRealm.setEventsListeners(Collections.singleton("dummy")); - } - - }); + @Override + public void configureTestRealm(RealmRepresentation testRealm) { + UserRepresentation user = findUserInRealmRep(testRealm, "test-user@localhost"); + UserBuilder.edit(user) + .hotpSecret("hotpSecret") + .otpEnabled(); + } @Rule - public AssertEvents events = new AssertEvents(keycloakRule); - - @Rule - public WebRule webRule = new WebRule(this); + public AssertEvents events = new AssertEvents(this); @Rule public GreenMailRule greenMail = new GreenMailRule(); - @WebResource - protected WebDriver driver; - - @WebResource + @Page protected AppPage appPage; - @WebResource + @Page protected LoginPage loginPage; - @WebResource + @Page protected LoginTotpPage loginTotpPage; - private HmacOTP otp = new HmacOTP(policy.getDigits(), policy.getAlgorithm(), policy.getLookAheadWindow()); + private HmacOTP otp; // = new HmacOTP(policy.getDigits(), policy.getAlgorithm(), policy.getLookAheadWindow()); private int lifespan; @@ -101,6 +77,19 @@ public class LoginHotpTest { @Before public void before() throws MalformedURLException { + RealmRepresentation testRealm = testRealm().toRepresentation(); + testRealm.setOtpPolicyType(UserCredentialModel.HOTP); + testRealm.setOtpPolicyLookAheadWindow(2); + testRealm().update(testRealm); + + policy = new OTPPolicy(); + policy.setAlgorithm(testRealm.getOtpPolicyAlgorithm()); + policy.setDigits(testRealm.getOtpPolicyDigits()); + policy.setInitialCounter(testRealm.getOtpPolicyInitialCounter()); + policy.setLookAheadWindow(testRealm.getOtpPolicyLookAheadWindow()); + policy.setPeriod(testRealm.getOtpPolicyLookAheadWindow()); + policy.setType(testRealm.getOtpPolicyType()); + otp = new HmacOTP(policy.getDigits(), policy.getAlgorithm(), policy.getLookAheadWindow()); } @@ -109,7 +98,7 @@ public class LoginHotpTest { loginPage.open(); loginPage.login("test-user@localhost", "password"); - loginTotpPage.assertCurrent(); + Assert.assertTrue(loginTotpPage.isCurrent()); loginTotpPage.login("123456"); loginTotpPage.assertCurrent(); @@ -128,7 +117,7 @@ public class LoginHotpTest { loginPage.open(); loginPage.login("test-user@localhost", "password"); - loginTotpPage.assertCurrent(); + Assert.assertTrue(loginTotpPage.isCurrent()); loginTotpPage.login(null); loginTotpPage.assertCurrent(); @@ -147,7 +136,7 @@ public class LoginHotpTest { loginPage.open(); loginPage.login("test-user@localhost", "password"); - loginTotpPage.assertCurrent(); + Assert.assertTrue(loginTotpPage.isCurrent()); loginTotpPage.login(otp.generateHOTP("hotpSecret", counter++)); @@ -161,7 +150,7 @@ public class LoginHotpTest { loginPage.open(); loginPage.login("test-user@localhost", "invalid"); - loginPage.assertCurrent(); + Assert.assertTrue(loginPage.isCurrent()); Assert.assertEquals("Invalid username or password.", loginPage.getError()); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java old mode 100755 new mode 100644 similarity index 69% rename from testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java index 98576e1561..1c048474de --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java @@ -18,73 +18,51 @@ package org.keycloak.testsuite.forms; import org.junit.Assert; import org.junit.Before; -import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.keycloak.events.Details; -import org.keycloak.models.RealmModel; -import org.keycloak.models.UserCredentialModel; -import org.keycloak.models.UserModel; import org.keycloak.models.utils.TimeBasedOTP; -import org.keycloak.representations.idm.CredentialRepresentation; -import org.keycloak.services.managers.RealmManager; import org.keycloak.testsuite.AssertEvents; import org.keycloak.testsuite.pages.AppPage; import org.keycloak.testsuite.pages.AppPage.RequestType; import org.keycloak.testsuite.pages.LoginPage; import org.keycloak.testsuite.pages.LoginTotpPage; -import org.keycloak.testsuite.rule.GreenMailRule; -import org.keycloak.testsuite.rule.KeycloakRule; -import org.keycloak.testsuite.rule.KeycloakRule.KeycloakSetup; -import org.keycloak.testsuite.rule.WebResource; -import org.keycloak.testsuite.rule.WebRule; -import org.openqa.selenium.WebDriver; import java.net.MalformedURLException; -import java.util.Collections; +import org.jboss.arquillian.graphene.page.Page; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.representations.idm.UserRepresentation; +import org.keycloak.testsuite.TestRealmKeycloakTest; +import org.keycloak.testsuite.util.GreenMailRule; +import org.keycloak.testsuite.util.UserBuilder; /** * @author Stian Thorgersen + * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. */ -public class LoginTotpTest { +public class LoginTotpTest extends TestRealmKeycloakTest { - @ClassRule - public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakSetup() { - - @Override - public void config(RealmManager manager, RealmModel defaultRealm, RealmModel appRealm) { - UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm); - - UserCredentialModel credentials = new UserCredentialModel(); - credentials.setType(CredentialRepresentation.TOTP); - credentials.setValue("totpSecret"); - user.updateCredential(credentials); - - user.setOtpEnabled(true); - appRealm.setEventsListeners(Collections.singleton("dummy")); - } - - }); + @Override + public void configureTestRealm(RealmRepresentation testRealm) { + UserRepresentation user = findUserInRealmRep(testRealm, "test-user@localhost"); + UserBuilder.edit(user) + .totpSecret("totpSecret") + .otpEnabled(); + } @Rule - public AssertEvents events = new AssertEvents(keycloakRule); - - @Rule - public WebRule webRule = new WebRule(this); + public AssertEvents events = new AssertEvents(this); @Rule public GreenMailRule greenMail = new GreenMailRule(); - @WebResource - protected WebDriver driver; - - @WebResource + @Page protected AppPage appPage; - @WebResource + @Page protected LoginPage loginPage; - @WebResource + @Page protected LoginTotpPage loginTotpPage; private TimeBasedOTP totp = new TimeBasedOTP(); @@ -101,7 +79,7 @@ public class LoginTotpTest { loginPage.open(); loginPage.login("test-user@localhost", "password"); - loginTotpPage.assertCurrent(); + Assert.assertTrue(loginTotpPage.isCurrent()); loginTotpPage.login("123456"); loginTotpPage.assertCurrent(); @@ -120,7 +98,7 @@ public class LoginTotpTest { loginPage.open(); loginPage.login("test-user@localhost", "password"); - loginTotpPage.assertCurrent(); + Assert.assertTrue(loginTotpPage.isCurrent()); loginTotpPage.login(null); loginTotpPage.assertCurrent(); @@ -139,7 +117,7 @@ public class LoginTotpTest { loginPage.open(); loginPage.login("test-user@localhost", "password"); - loginTotpPage.assertCurrent(); + Assert.assertTrue(loginTotpPage.isCurrent()); loginTotpPage.login(totp.generateTOTP("totpSecret")); @@ -153,7 +131,7 @@ public class LoginTotpTest { loginPage.open(); loginPage.login("test-user@localhost", "password"); - loginTotpPage.assertCurrent(); + Assert.assertTrue(loginTotpPage.isCurrent()); loginTotpPage.cancel(); loginPage.assertCurrent(); } @@ -163,7 +141,7 @@ public class LoginTotpTest { loginPage.open(); loginPage.login("test-user@localhost", "invalid"); - loginPage.assertCurrent(); + Assert.assertTrue(loginPage.isCurrent()); Assert.assertEquals("Invalid username or password.", loginPage.getError()); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LogoutTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LogoutTest.java old mode 100755 new mode 100644 similarity index 86% rename from testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LogoutTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LogoutTest.java index 0cade0e187..087d35ed26 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LogoutTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LogoutTest.java @@ -16,49 +16,39 @@ */ package org.keycloak.testsuite.forms; -import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.keycloak.events.Details; import org.keycloak.testsuite.AssertEvents; -import org.keycloak.testsuite.OAuthClient; import org.keycloak.testsuite.pages.AppPage; import org.keycloak.testsuite.pages.LoginPage; -import org.keycloak.testsuite.rule.KeycloakRule; -import org.keycloak.testsuite.rule.WebResource; -import org.keycloak.testsuite.rule.WebRule; -import org.openqa.selenium.WebDriver; import java.io.IOException; +import org.jboss.arquillian.graphene.page.Page; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.testsuite.TestRealmKeycloakTest; import static org.junit.Assert.*; /** * @author Stian Thorgersen + * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. */ -public class LogoutTest { - - @ClassRule - public static KeycloakRule keycloakRule = new KeycloakRule(); +public class LogoutTest extends TestRealmKeycloakTest { @Rule - public AssertEvents events = new AssertEvents(keycloakRule); + public AssertEvents events = new AssertEvents(this); - @Rule - public WebRule webRule = new WebRule(this); - - @WebResource - protected OAuthClient oauth; - - @WebResource - protected WebDriver driver; - - @WebResource + @Page protected AppPage appPage; - @WebResource + @Page protected LoginPage loginPage; + @Override + public void configureTestRealm(RealmRepresentation testRealm) { + } + @Test public void logoutRedirect() { loginPage.open(); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/PassThroughAuthenticator.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PassThroughAuthenticator.java old mode 100755 new mode 100644 similarity index 100% rename from testsuite/integration/src/test/java/org/keycloak/testsuite/forms/PassThroughAuthenticator.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PassThroughAuthenticator.java diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/PassThroughClientAuthenticator.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PassThroughClientAuthenticator.java similarity index 100% rename from testsuite/integration/src/test/java/org/keycloak/testsuite/forms/PassThroughClientAuthenticator.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PassThroughClientAuthenticator.java diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/PassThroughRegistration.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PassThroughRegistration.java similarity index 100% rename from testsuite/integration/src/test/java/org/keycloak/testsuite/forms/PassThroughRegistration.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/PassThroughRegistration.java diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/RegisterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/RegisterTest.java old mode 100755 new mode 100644 similarity index 90% rename from testsuite/integration/src/test/java/org/keycloak/testsuite/forms/RegisterTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/RegisterTest.java index 63297cc335..dda7540d7c --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/RegisterTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/RegisterTest.java @@ -16,54 +16,41 @@ */ package org.keycloak.testsuite.forms; +import org.jboss.arquillian.graphene.page.Page; import org.junit.*; import org.keycloak.events.Details; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.PasswordPolicy; -import org.keycloak.models.RealmModel; -import org.keycloak.models.UserModel; -import org.keycloak.services.managers.RealmManager; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.testsuite.AssertEvents; -import org.keycloak.testsuite.OAuthClient; +import org.keycloak.testsuite.TestRealmKeycloakTest; import org.keycloak.testsuite.pages.AppPage; import org.keycloak.testsuite.pages.AppPage.RequestType; import org.keycloak.testsuite.pages.LoginPage; import org.keycloak.testsuite.pages.RegisterPage; -import org.keycloak.testsuite.rule.KeycloakRule; -import org.keycloak.testsuite.rule.WebResource; -import org.keycloak.testsuite.rule.WebRule; -import org.openqa.selenium.WebDriver; import static org.junit.Assert.assertEquals; /** * @author Stian Thorgersen + * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. */ -public class RegisterTest { - - @ClassRule - public static KeycloakRule keycloakRule = new KeycloakRule(); +public class RegisterTest extends TestRealmKeycloakTest { @Rule - public AssertEvents events = new AssertEvents(keycloakRule); + public AssertEvents events = new AssertEvents(this); - @Rule - public WebRule webRule = new WebRule(this); - - @WebResource - protected WebDriver driver; - - @WebResource + @Page protected AppPage appPage; - @WebResource + @Page protected LoginPage loginPage; - @WebResource + @Page protected RegisterPage registerPage; - @WebResource - protected OAuthClient oauth; + @Override + public void configureTestRealm(RealmRepresentation testRealm) { + } @Test public void registerExistingUser() { @@ -133,12 +120,15 @@ public class RegisterTest { @Test public void registerPasswordPolicy() { - keycloakRule.configure(new KeycloakRule.KeycloakSetup() { + /*keycloakRule.configure(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { appRealm.setPasswordPolicy(new PasswordPolicy("length")); } - }); + });*/ + RealmRepresentation realm = testRealm().toRepresentation(); + realm.setPasswordPolicy("length"); + testRealm().update(realm); try { loginPage.open(); @@ -162,12 +152,12 @@ public class RegisterTest { events.expectLogin().user(userId).detail(Details.USERNAME, "registerpasswordpolicy").assertEvent(); } finally { - keycloakRule.configure(new KeycloakRule.KeycloakSetup() { + /*keycloakRule.configure(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { appRealm.setPasswordPolicy(new PasswordPolicy(null)); } - }); + });*/ } } @@ -251,7 +241,7 @@ public class RegisterTest { String userId = events.expectRegister("registerUserSuccess", "registerUserSuccess@email").assertEvent().getUserId(); events.expectLogin().detail("username", "registerusersuccess").user(userId).assertEvent(); - UserModel user = getUser(userId); + UserRepresentation user = getUser(userId); Assert.assertNotNull(user); Assert.assertNotNull(user.getCreatedTimestamp()); // test that timestamp is current with 10s tollerance @@ -263,7 +253,7 @@ public class RegisterTest { assertEquals("lastName", user.getLastName()); } - protected UserModel getUser(String userId) { + /*protected UserModel getUser(String userId) { KeycloakSession samlServerSession = keycloakRule.startSession(); try { RealmModel brokerRealm = samlServerSession.realms().getRealm("test"); @@ -271,6 +261,10 @@ public class RegisterTest { } finally { keycloakRule.stopSession(samlServerSession, false); } + }*/ + + protected UserRepresentation getUser(String userId) { + return testRealm().users().get(userId).toRepresentation(); } @Test @@ -319,7 +313,7 @@ public class RegisterTest { @Test public void registerUserSuccess_emailAsUsername() { configureRelamRegistrationEmailAsUsername(true); - + try { loginPage.open(); loginPage.clickRegister(); @@ -332,7 +326,7 @@ public class RegisterTest { String userId = events.expectRegister("registerUserSuccessE@email", "registerUserSuccessE@email").assertEvent().getUserId(); events.expectLogin().detail("username", "registerusersuccesse@email").user(userId).assertEvent(); - UserModel user = getUser(userId); + UserRepresentation user = getUser(userId); Assert.assertNotNull(user); Assert.assertNotNull(user.getCreatedTimestamp()); // test that timestamp is current with 10s tollerance @@ -344,12 +338,9 @@ public class RegisterTest { } protected void configureRelamRegistrationEmailAsUsername(final boolean value) { - keycloakRule.configure(new KeycloakRule.KeycloakSetup() { - @Override - public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - appRealm.setRegistrationEmailAsUsername(value); - } - }); + RealmRepresentation realm = testRealm().toRepresentation(); + realm.setRegistrationEmailAsUsername(value); + testRealm().update(realm); } } diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java old mode 100755 new mode 100644 similarity index 65% rename from testsuite/integration/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java index 921e682e24..98a3fe6135 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java @@ -19,122 +19,96 @@ package org.keycloak.testsuite.forms; import org.junit.*; import org.keycloak.events.Details; import org.keycloak.events.Errors; -import org.keycloak.events.Event; import org.keycloak.events.EventType; -import org.keycloak.models.PasswordPolicy; -import org.keycloak.models.RealmModel; -import org.keycloak.models.UserCredentialModel; -import org.keycloak.models.UserModel; -import org.keycloak.representations.idm.CredentialRepresentation; -import org.keycloak.services.managers.RealmManager; import org.keycloak.testsuite.AssertEvents; -import org.keycloak.testsuite.Constants; -import org.keycloak.testsuite.MailUtil; -import org.keycloak.testsuite.OAuthClient; +//import org.keycloak.testsuite.Constants; +import org.keycloak.testsuite.util.MailUtils; import org.keycloak.testsuite.pages.*; import org.keycloak.testsuite.pages.AppPage.RequestType; -import org.keycloak.testsuite.rule.GreenMailRule; -import org.keycloak.testsuite.rule.KeycloakRule; -import org.keycloak.testsuite.rule.WebResource; -import org.keycloak.testsuite.rule.WebRule; -import org.keycloak.common.util.Time; -import org.openqa.selenium.WebDriver; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.internet.MimeMessage; import java.io.IOException; -import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; +import org.jboss.arquillian.graphene.page.Page; +import org.keycloak.representations.idm.EventRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.representations.idm.UserRepresentation; +import org.keycloak.testsuite.TestRealmKeycloakTest; +import org.keycloak.testsuite.util.GreenMailRule; +import org.keycloak.testsuite.util.OAuthClient; +import org.keycloak.testsuite.util.UserBuilder; import static org.junit.Assert.*; /** * @author Stian Thorgersen + * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. */ -public class ResetPasswordTest { +public class ResetPasswordTest extends TestRealmKeycloakTest { static int lifespan = 0; - @ClassRule - public static KeycloakRule keycloakRule = new KeycloakRule((new KeycloakRule.KeycloakSetup() { - @Override - public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - UserModel user = manager.getSession().users().addUser(appRealm, "login-test"); - user.setEmail("login@test.com"); - user.setEnabled(true); - userId = user.getId(); + @Override + public void configureTestRealm(RealmRepresentation testRealm) { + UserRepresentation user = UserBuilder.create() + .username("login-test") + .email("login@test.com") + .enabled(true) + .password("password") + .build(); + testRealm.getUsers().add(user); + } - UserCredentialModel creds = new UserCredentialModel(); - creds.setType(CredentialRepresentation.PASSWORD); - creds.setValue("password"); + @Before + public void setAccessCodeLifespanUserAction() { + // Must do this with adminClient because default is not set until after testRealm.json is loaded. + lifespan = testRealm().toRepresentation().getAccessCodeLifespanUserAction(); + } + + @Before + public void setUserId() { + userId = findUser("login-test").getId(); + } - user.updateCredential(creds); - appRealm.setEventsListeners(Collections.singleton("dummy")); - lifespan = appRealm.getAccessCodeLifespanUserAction(); - } - })); private static String userId; - @Rule - public WebRule webRule = new WebRule(this); - @Rule public GreenMailRule greenMail = new GreenMailRule(); - @WebResource - protected WebDriver driver; - - @WebResource - protected OAuthClient oauth; - - @WebResource + @Page protected AppPage appPage; - @WebResource + @Page protected LoginPage loginPage; - @WebResource + @Page protected ErrorPage errorPage; - @WebResource + @Page protected InfoPage infoPage; - @WebResource + @Page protected VerifyEmailPage verifyEmailPage; - @WebResource + @Page protected LoginPasswordResetPage resetPasswordPage; - @WebResource + @Page protected LoginPasswordUpdatePage updatePasswordPage; @Rule - public AssertEvents events = new AssertEvents(keycloakRule); - - @Before - public void resetPasswordToOriginal() { - keycloakRule.configure(new KeycloakRule.KeycloakSetup() { - @Override - public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - UserModel user = session.users().getUserByUsername("login-test", appRealm); - UserCredentialModel creds = new UserCredentialModel(); - creds.setType(CredentialRepresentation.PASSWORD); - creds.setValue("password"); - - user.updateCredential(creds); - } - }); - } + public AssertEvents events = new AssertEvents(this); @Test public void resetPasswordLink() throws IOException, MessagingException { String username = "login-test"; - String resetUri = Constants.AUTH_SERVER_ROOT + "/realms/test/login-actions/reset-credentials"; + String resetUri = oauth.AUTH_SERVER_ROOT + "/realms/test/login-actions/reset-credentials"; driver.navigate().to(resetUri); resetPasswordPage.assertCurrent(); @@ -146,7 +120,7 @@ public class ResetPasswordTest { events.expectRequiredAction(EventType.SEND_RESET_PASSWORD) .user(userId) - .detail(Details.REDIRECT_URI, Constants.AUTH_SERVER_ROOT + "/realms/test/account/") + .detail(Details.REDIRECT_URI, oauth.AUTH_SERVER_ROOT + "/realms/test/account/") .client("account") .detail(Details.USERNAME, username) .detail(Details.EMAIL, "login@test.com") @@ -166,12 +140,12 @@ public class ResetPasswordTest { updatePasswordPage.changePassword("resetPassword", "resetPassword"); String sessionId = events.expectRequiredAction(EventType.UPDATE_PASSWORD) - .detail(Details.REDIRECT_URI, Constants.AUTH_SERVER_ROOT + "/realms/test/account/") + .detail(Details.REDIRECT_URI, oauth.AUTH_SERVER_ROOT + "/realms/test/account/") .client("account") .user(userId).detail(Details.USERNAME, username).assertEvent().getSessionId(); events.expectLogin().user(userId).detail(Details.USERNAME, username) - .detail(Details.REDIRECT_URI, Constants.AUTH_SERVER_ROOT + "/realms/test/account/") + .detail(Details.REDIRECT_URI, oauth.AUTH_SERVER_ROOT + "/realms/test/account/") .client("account") .session(sessionId).assertEvent(); @@ -213,7 +187,7 @@ public class ResetPasswordTest { loginPage.login("login@test.com", "password"); - Event loginEvent = events.expectLogin().user(userId).detail(Details.USERNAME, "login@test.com").assertEvent(); + EventRepresentation loginEvent = events.expectLogin().user(userId).detail(Details.USERNAME, "login@test.com").assertEvent(); String code = oauth.getCurrentQuery().get("code"); OAuthClient.AccessTokenResponse tokenResponse = oauth.doAccessTokenRequest(code, "password"); @@ -358,7 +332,7 @@ public class ResetPasswordTest { events.expectRequiredAction(EventType.RESET_PASSWORD).user((String) null).session((String) null).detail(Details.USERNAME, "invalid").removeDetail(Details.EMAIL).removeDetail(Details.CODE_ID).error("user_not_found").assertEvent(); } - + @Test public void resetPasswordMissingUsername() throws IOException, MessagingException, InterruptedException { loginPage.open(); @@ -373,9 +347,9 @@ public class ResetPasswordTest { assertEquals("Please specify username.", resetPasswordPage.getErrorMessage()); assertEquals(0, greenMail.getReceivedMessages().length); - + events.expectRequiredAction(EventType.RESET_PASSWORD).user((String) null).session((String) null).clearDetails().error("username_missing").assertEvent(); - + } @Test @@ -401,7 +375,7 @@ public class ResetPasswordTest { String changePasswordUrl = getPasswordResetEmailLink(message); - Time.setOffset(1800 + 23); + setTimeOffset(1800 + 23); driver.navigate().to(changePasswordUrl.trim()); @@ -411,20 +385,18 @@ public class ResetPasswordTest { events.expectRequiredAction(EventType.RESET_PASSWORD).error("expired_code").client("test-app").user((String) null).session((String) null).clearDetails().assertEvent(); } finally { - Time.setOffset(0); + setTimeOffset(0); } } @Test public void resetPasswordExpiredCodeShort() throws IOException, MessagingException, InterruptedException { final AtomicInteger originalValue = new AtomicInteger(); - keycloakRule.configure(new KeycloakRule.KeycloakSetup() { - @Override - public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - originalValue.set(appRealm.getAccessCodeLifespan()); - appRealm.setAccessCodeLifespanUserAction(60); - } - }); + + RealmRepresentation realmRep = testRealm().toRepresentation(); + originalValue.set(realmRep.getAccessCodeLifespan()); + realmRep.setAccessCodeLifespanUserAction(60); + testRealm().update(realmRep); try { loginPage.open(); @@ -447,7 +419,7 @@ public class ResetPasswordTest { String changePasswordUrl = getPasswordResetEmailLink(message); - Time.setOffset(70); + setTimeOffset(70); driver.navigate().to(changePasswordUrl.trim()); @@ -457,139 +429,94 @@ public class ResetPasswordTest { events.expectRequiredAction(EventType.RESET_PASSWORD).error("expired_code").client("test-app").user((String) null).session((String) null).clearDetails().assertEvent(); } finally { - Time.setOffset(0); - - keycloakRule.configure(new KeycloakRule.KeycloakSetup() { - @Override - public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - appRealm.setAccessCodeLifespanUserAction(originalValue.get()); - } - }); + setTimeOffset(0); } } @Test public void resetPasswordDisabledUser() throws IOException, MessagingException, InterruptedException { - keycloakRule.configure(new KeycloakRule.KeycloakSetup() { - @Override - public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - session.users().getUserByUsername("login-test", appRealm).setEnabled(false); - } - }); + UserRepresentation user = findUser("login-test"); + user.setEnabled(false); + updateUser(user); - try { - loginPage.open(); - loginPage.resetPassword(); + loginPage.open(); + loginPage.resetPassword(); - resetPasswordPage.assertCurrent(); + resetPasswordPage.assertCurrent(); - resetPasswordPage.changePassword("login-test"); + resetPasswordPage.changePassword("login-test"); - loginPage.assertCurrent(); - assertEquals("You should receive an email shortly with further instructions.", loginPage.getSuccessMessage()); + loginPage.assertCurrent(); + assertEquals("You should receive an email shortly with further instructions.", loginPage.getSuccessMessage()); - assertEquals(0, greenMail.getReceivedMessages().length); + assertEquals(0, greenMail.getReceivedMessages().length); - events.expectRequiredAction(EventType.RESET_PASSWORD).session((String) null).user(userId).detail(Details.USERNAME, "login-test").removeDetail(Details.CODE_ID).error("user_disabled").assertEvent(); - } finally { - keycloakRule.configure(new KeycloakRule.KeycloakSetup() { - @Override - public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - session.users().getUserByUsername("login-test", appRealm).setEnabled(true); - } - }); - } + events.expectRequiredAction(EventType.RESET_PASSWORD).session((String) null).user(userId).detail(Details.USERNAME, "login-test").removeDetail(Details.CODE_ID).error("user_disabled").assertEvent(); } @Test public void resetPasswordNoEmail() throws IOException, MessagingException, InterruptedException { final String[] email = new String[1]; - keycloakRule.configure(new KeycloakRule.KeycloakSetup() { - @Override - public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - UserModel user = session.users().getUserByUsername("login-test", appRealm); - email[0] = user.getEmail(); - user.setEmail(null); - } - }); + UserRepresentation user = findUser("login-test"); + email[0] = user.getEmail(); + user.setEmail(""); + updateUser(user); - try { - loginPage.open(); - loginPage.resetPassword(); + loginPage.open(); + loginPage.resetPassword(); - resetPasswordPage.assertCurrent(); + resetPasswordPage.assertCurrent(); - resetPasswordPage.changePassword("login-test"); + resetPasswordPage.changePassword("login-test"); - loginPage.assertCurrent(); - assertEquals("You should receive an email shortly with further instructions.", loginPage.getSuccessMessage()); + loginPage.assertCurrent(); + assertEquals("You should receive an email shortly with further instructions.", loginPage.getSuccessMessage()); - assertEquals(0, greenMail.getReceivedMessages().length); + assertEquals(0, greenMail.getReceivedMessages().length); - events.expectRequiredAction(EventType.RESET_PASSWORD_ERROR).session((String) null).user(userId).detail(Details.USERNAME, "login-test").removeDetail(Details.CODE_ID).error("invalid_email").assertEvent(); - } finally { - keycloakRule.configure(new KeycloakRule.KeycloakSetup() { - @Override - public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - session.users().getUserByUsername("login-test", appRealm).setEmail(email[0]); - } - }); - } + events.expectRequiredAction(EventType.RESET_PASSWORD_ERROR).session((String) null).user(userId).detail(Details.USERNAME, "login-test").removeDetail(Details.CODE_ID).error("invalid_email").assertEvent(); } @Test public void resetPasswordWrongSmtp() throws IOException, MessagingException, InterruptedException { final String[] host = new String[1]; - keycloakRule.configure(new KeycloakRule.KeycloakSetup() { - @Override - public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - Map smtpConfig = new HashMap<>(); - smtpConfig.putAll(appRealm.getSmtpConfig()); - host[0] = smtpConfig.get("host"); - smtpConfig.put("host", "invalid_host"); - appRealm.setSmtpConfig(smtpConfig); - } - }); - try { - loginPage.open(); - loginPage.resetPassword(); + Map smtpConfig = new HashMap<>(); + smtpConfig.putAll(testRealm().toRepresentation().getSmtpServer()); + host[0] = smtpConfig.get("host"); + smtpConfig.put("host", "invalid_host"); + RealmRepresentation realmRep = testRealm().toRepresentation(); + realmRep.setSmtpServer(smtpConfig); + testRealm().update(realmRep); - resetPasswordPage.assertCurrent(); + loginPage.open(); + loginPage.resetPassword(); - resetPasswordPage.changePassword("login-test"); + resetPasswordPage.assertCurrent(); - errorPage.assertCurrent(); + resetPasswordPage.changePassword("login-test"); - assertEquals("Failed to send email, please try again later.", errorPage.getError()); + errorPage.assertCurrent(); - assertEquals(0, greenMail.getReceivedMessages().length); + assertEquals("Failed to send email, please try again later.", errorPage.getError()); - events.expectRequiredAction(EventType.SEND_RESET_PASSWORD_ERROR).user(userId) - .session((String)null) - .detail(Details.USERNAME, "login-test").removeDetail(Details.CODE_ID).error(Errors.EMAIL_SEND_FAILED).assertEvent(); - } finally { - keycloakRule.configure(new KeycloakRule.KeycloakSetup() { - @Override - public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - Map smtpConfig = new HashMap<>(); - smtpConfig.putAll(appRealm.getSmtpConfig()); - smtpConfig.put("host",host[0]); - appRealm.setSmtpConfig(smtpConfig); - } - }); - } + assertEquals(0, greenMail.getReceivedMessages().length); + + events.expectRequiredAction(EventType.SEND_RESET_PASSWORD_ERROR).user(userId) + .session((String)null) + .detail(Details.USERNAME, "login-test").removeDetail(Details.CODE_ID).error(Errors.EMAIL_SEND_FAILED).assertEvent(); + } + + private void setPasswordPolicy(String policy) { + RealmRepresentation realmRep = testRealm().toRepresentation(); + realmRep.setPasswordPolicy(policy); + testRealm().update(realmRep); } @Test public void resetPasswordWithLengthPasswordPolicy() throws IOException, MessagingException { - keycloakRule.update(new KeycloakRule.KeycloakSetup() { - @Override - public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - appRealm.setPasswordPolicy(new PasswordPolicy("length")); - } - }); + setPasswordPolicy("length"); loginPage.open(); loginPage.resetPassword(); @@ -640,62 +567,51 @@ public class ResetPasswordTest { @Test public void resetPasswordWithPasswordHisoryPolicy() throws IOException, MessagingException { - keycloakRule.update(new KeycloakRule.KeycloakSetup() { - @Override - public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - //Block passwords that are equal to previous passwords. Default value is 3. - appRealm.setPasswordPolicy(new PasswordPolicy("passwordHistory")); - } - }); - + //Block passwords that are equal to previous passwords. Default value is 3. + setPasswordPolicy("passwordHistory"); + try { - Time.setOffset(2000000); + setTimeOffset(2000000); resetPassword("login-test", "password1"); - + resetPasswordInvalidPassword("login-test", "password1", "Invalid password: must not be equal to any of last 3 passwords."); - Time.setOffset(4000000); + setTimeOffset(4000000); resetPassword("login-test", "password2"); - + resetPasswordInvalidPassword("login-test", "password1", "Invalid password: must not be equal to any of last 3 passwords."); resetPasswordInvalidPassword("login-test", "password2", "Invalid password: must not be equal to any of last 3 passwords."); - - Time.setOffset(8000000); + + setTimeOffset(8000000); resetPassword("login-test", "password3"); - + resetPasswordInvalidPassword("login-test", "password1", "Invalid password: must not be equal to any of last 3 passwords."); resetPasswordInvalidPassword("login-test", "password2", "Invalid password: must not be equal to any of last 3 passwords."); resetPasswordInvalidPassword("login-test", "password3", "Invalid password: must not be equal to any of last 3 passwords."); resetPassword("login-test", "password"); } finally { - keycloakRule.update(new KeycloakRule.KeycloakSetup() { - @Override - public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - appRealm.setPasswordPolicy(new PasswordPolicy(null)); - } - }); - Time.setOffset(0); + setTimeOffset(0); } } public static String getPasswordResetEmailLink(MimeMessage message) throws IOException, MessagingException { Multipart multipart = (Multipart) message.getContent(); - + final String textContentType = multipart.getBodyPart(0).getContentType(); - + assertEquals("text/plain; charset=UTF-8", textContentType); - + final String textBody = (String) multipart.getBodyPart(0).getContent(); - final String textChangePwdUrl = MailUtil.getLink(textBody); - + final String textChangePwdUrl = MailUtils.getLink(textBody); + final String htmlContentType = multipart.getBodyPart(1).getContentType(); - + assertEquals("text/html; charset=UTF-8", htmlContentType); - + final String htmlBody = (String) multipart.getBodyPart(1).getContent(); - final String htmlChangePwdUrl = MailUtil.getLink(htmlBody); - + final String htmlChangePwdUrl = MailUtils.getLink(htmlBody); + assertEquals(htmlChangePwdUrl, textChangePwdUrl); return htmlChangePwdUrl; diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/SSOTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/SSOTest.java old mode 100755 new mode 100644 similarity index 77% rename from testsuite/integration/src/test/java/org/keycloak/testsuite/forms/SSOTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/SSOTest.java index 18ff041499..ba561cc5c8 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/SSOTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/SSOTest.java @@ -16,22 +16,23 @@ */ package org.keycloak.testsuite.forms; +import org.jboss.arquillian.drone.api.annotation.Drone; +import org.jboss.arquillian.graphene.page.Page; import org.junit.Assert; -import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.keycloak.OAuth2Constants; import org.keycloak.events.Details; -import org.keycloak.events.Event; +import org.keycloak.representations.idm.EventRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.testsuite.AssertEvents; -import org.keycloak.testsuite.OAuthClient; +import org.keycloak.testsuite.TestRealmKeycloakTest; +import org.keycloak.testsuite.drone.Different; import org.keycloak.testsuite.pages.AccountUpdateProfilePage; import org.keycloak.testsuite.pages.AppPage; import org.keycloak.testsuite.pages.AppPage.RequestType; import org.keycloak.testsuite.pages.LoginPage; -import org.keycloak.testsuite.rule.KeycloakRule; -import org.keycloak.testsuite.rule.WebResource; -import org.keycloak.testsuite.rule.WebRule; +import org.keycloak.testsuite.util.OAuthClient; import org.openqa.selenium.WebDriver; import static org.junit.Assert.assertEquals; @@ -40,38 +41,35 @@ import static org.junit.Assert.assertTrue; /** * @author Stian Thorgersen + * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. */ -public class SSOTest { +public class SSOTest extends TestRealmKeycloakTest { - @ClassRule - public static KeycloakRule keycloakRule = new KeycloakRule(); + @Drone + @Different + protected WebDriver driver2; - @Rule - public WebRule webRule = new WebRule(this); - - @WebResource - protected OAuthClient oauth; - - @WebResource - protected WebDriver driver; - - @WebResource + @Page protected AppPage appPage; - @WebResource + @Page protected LoginPage loginPage; - @WebResource + @Page protected AccountUpdateProfilePage profilePage; @Rule - public AssertEvents events = new AssertEvents(keycloakRule); + public AssertEvents events = new AssertEvents(this); + + @Override + public void configureTestRealm(RealmRepresentation testRealm) { + } @Test public void loginSuccess() { loginPage.open(); loginPage.login("test-user@localhost", "password"); - + assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType()); Assert.assertNotNull(oauth.getCurrentQuery().get(OAuth2Constants.CODE)); @@ -92,7 +90,7 @@ public class SSOTest { assertEquals(sessionId, sessionId2); // Expire session - keycloakRule.removeUserSession(sessionId); + testingClient.testing().removeUserSession("test", sessionId); oauth.doLogin("test-user@localhost", "password"); @@ -110,15 +108,18 @@ public class SSOTest { Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType()); Assert.assertNotNull(oauth.getCurrentQuery().get(OAuth2Constants.CODE)); - Event login1 = events.expectLogin().assertEvent(); + EventRepresentation login1 = events.expectLogin().assertEvent(); - WebDriver driver2 = WebRule.createWebDriver(); try { - OAuthClient oauth2 = new OAuthClient(driver2); + //OAuthClient oauth2 = new OAuthClient(driver2); + OAuthClient oauth2 = new OAuthClient(); + oauth2.setDriver(driver2); + oauth2.setAdminClient(adminClient); + oauth2.state("mystate"); oauth2.doLogin("test-user@localhost", "password"); - Event login2 = events.expectLogin().assertEvent(); + EventRepresentation login2 = events.expectLogin().assertEvent(); Assert.assertEquals(RequestType.AUTH_RESPONSE, RequestType.valueOf(driver2.getTitle())); Assert.assertNotNull(oauth2.getCurrentQuery().get(OAuth2Constants.CODE)); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientBuilder.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientBuilder.java index 7c5da16e12..7d932a20cc 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientBuilder.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientBuilder.java @@ -43,6 +43,11 @@ public class ClientBuilder { return this; } + public ClientBuilder name(String name) { + rep.setName(name); + return this; + } + public ClientBuilder clientId(String clientId) { rep.setClientId(clientId); return this; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ExecutionBuilder.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ExecutionBuilder.java new file mode 100644 index 0000000000..1722c44566 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ExecutionBuilder.java @@ -0,0 +1,71 @@ +/* + * 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.util; + + +import org.keycloak.representations.idm.AuthenticationExecutionRepresentation; + +/** + * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. + */ +public class ExecutionBuilder { + + private AuthenticationExecutionRepresentation rep = new AuthenticationExecutionRepresentation(); + + public static ExecutionBuilder create() { + return new ExecutionBuilder(); + } + + private ExecutionBuilder() { + } + + public ExecutionBuilder id(String id) { + rep.setId(id); + return this; + } + + public ExecutionBuilder parentFlow(String parentFlow) { + rep.setParentFlow(parentFlow); + return this; + } + + public ExecutionBuilder requirement(String requirement) { + rep.setRequirement(requirement); + return this; + } + + public ExecutionBuilder authenticator(String authenticator) { + rep.setAuthenticator(authenticator); + return this; + } + + public ExecutionBuilder priority(int priority) { + rep.setPriority(priority); + return this; + } + + public ExecutionBuilder authenticatorFlow(boolean authenticatorFlow) { + rep.setAutheticatorFlow(authenticatorFlow); + return this; + } + + public AuthenticationExecutionRepresentation build() { + return rep; + } + +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/FlowBuilder.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/FlowBuilder.java new file mode 100644 index 0000000000..1823886058 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/FlowBuilder.java @@ -0,0 +1,71 @@ +/* + * 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.util; + + +import org.keycloak.representations.idm.AuthenticationFlowRepresentation; + +/** + * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. + */ +public class FlowBuilder { + + private AuthenticationFlowRepresentation rep = new AuthenticationFlowRepresentation(); + + public static FlowBuilder create() { + return new FlowBuilder(); + } + + private FlowBuilder() { + } + + public FlowBuilder id(String id) { + rep.setId(id); + return this; + } + + public FlowBuilder alias(String alias) { + rep.setAlias(alias); + return this; + } + + public FlowBuilder description(String description) { + rep.setDescription(description); + return this; + } + + public FlowBuilder providerId(String providerId) { + rep.setProviderId(providerId); + return this; + } + + public FlowBuilder topLevel(boolean topLevel) { + rep.setTopLevel(topLevel); + return this; + } + + public FlowBuilder builtIn(boolean builtIn) { + rep.setBuiltIn(builtIn); + return this; + } + + public AuthenticationFlowRepresentation build() { + return rep; + } + +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/UserBuilder.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/UserBuilder.java index 26968337e8..90f2421a2e 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/UserBuilder.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/UserBuilder.java @@ -122,20 +122,33 @@ public class UserBuilder { return this; } - public UserBuilder totpSecret(String totpSecret) { + public UserBuilder secret(String type, String secret) { if (rep.getCredentials() == null) { rep.setCredentials(new LinkedList()); } CredentialRepresentation credential = new CredentialRepresentation(); - credential.setType(CredentialRepresentation.TOTP); - credential.setValue(totpSecret); + credential.setType(type); + credential.setValue(secret); rep.getCredentials().add(credential); rep.setTotp(true); return this; } + public UserBuilder totpSecret(String totpSecret) { + return secret(CredentialRepresentation.TOTP, totpSecret); + } + + public UserBuilder hotpSecret(String hotpSecret) { + return secret(CredentialRepresentation.HOTP, hotpSecret); + } + + public UserBuilder otpEnabled() { + rep.setTotp(Boolean.TRUE); + return this; + } + public UserRepresentation build() { return rep; } diff --git a/testsuite/integration/src/test/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory b/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory similarity index 100% rename from testsuite/integration/src/test/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory rename to testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory diff --git a/testsuite/integration/src/test/resources/META-INF/services/org.keycloak.authentication.ClientAuthenticatorFactory b/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/services/org.keycloak.authentication.ClientAuthenticatorFactory similarity index 100% rename from testsuite/integration/src/test/resources/META-INF/services/org.keycloak.authentication.ClientAuthenticatorFactory rename to testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/services/org.keycloak.authentication.ClientAuthenticatorFactory diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/CustomFlowTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/CustomFlowTest.java deleted file mode 100755 index 72582e1121..0000000000 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/CustomFlowTest.java +++ /dev/null @@ -1,248 +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.forms; - -import org.junit.Assert; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.keycloak.OAuth2Constants; -import org.keycloak.authentication.AuthenticationFlow; -import org.keycloak.events.Details; -import org.keycloak.events.Errors; -import org.keycloak.models.AuthenticationExecutionModel; -import org.keycloak.models.AuthenticationFlowModel; -import org.keycloak.models.ClientModel; -import org.keycloak.models.RealmModel; -import org.keycloak.models.UserModel; -import org.keycloak.models.utils.KeycloakModelUtils; -import org.keycloak.representations.AccessToken; -import org.keycloak.representations.RefreshToken; -import org.keycloak.services.managers.RealmManager; -import org.keycloak.testsuite.AssertEvents; -import org.keycloak.testsuite.OAuthClient; -import org.keycloak.testsuite.pages.AppPage; -import org.keycloak.testsuite.pages.AppPage.RequestType; -import org.keycloak.testsuite.pages.ErrorPage; -import org.keycloak.testsuite.pages.LoginPage; -import org.keycloak.testsuite.pages.LoginPasswordUpdatePage; -import org.keycloak.testsuite.pages.RegisterPage; -import org.keycloak.testsuite.rule.KeycloakRule; -import org.keycloak.testsuite.rule.WebResource; -import org.keycloak.testsuite.rule.WebRule; -import org.openqa.selenium.WebDriver; - -import static org.junit.Assert.assertEquals; - -/** - * @author Stian Thorgersen - */ -public class CustomFlowTest { - - @ClassRule - public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakRule.KeycloakSetup() { - @Override - public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - UserModel user = manager.getSession().users().addUser(appRealm, "login-test"); - user.setEmail("login@test.com"); - user.setEnabled(true); - - userId = user.getId(); - - AuthenticationFlowModel flow = new AuthenticationFlowModel(); - flow.setAlias("dummy"); - flow.setDescription("dummy pass through flow"); - flow.setProviderId("basic-flow"); - flow.setTopLevel(true); - flow.setBuiltIn(false); - flow = appRealm.addAuthenticationFlow(flow); - appRealm.setBrowserFlow(flow); - appRealm.setDirectGrantFlow(flow); - - AuthenticationExecutionModel execution; - - execution = new AuthenticationExecutionModel(); - execution.setParentFlow(flow.getId()); - execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED); - execution.setAuthenticator(PassThroughAuthenticator.PROVIDER_ID); - execution.setPriority(10); - execution.setAuthenticatorFlow(false); - appRealm.addAuthenticatorExecution(execution); - - - - flow = new AuthenticationFlowModel(); - flow.setAlias("dummy registration"); - flow.setDescription("dummy pass through registration"); - flow.setProviderId("basic-flow"); - flow.setTopLevel(true); - flow.setBuiltIn(false); - flow = appRealm.addAuthenticationFlow(flow); - appRealm.setRegistrationFlow(flow); - - execution = new AuthenticationExecutionModel(); - execution.setParentFlow(flow.getId()); - execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED); - execution.setAuthenticator(PassThroughRegistration.PROVIDER_ID); - execution.setPriority(10); - execution.setAuthenticatorFlow(false); - appRealm.addAuthenticatorExecution(execution); - - AuthenticationFlowModel clientFlow = new AuthenticationFlowModel(); - clientFlow.setAlias("client-dummy"); - clientFlow.setDescription("dummy pass through flow"); - clientFlow.setProviderId(AuthenticationFlow.CLIENT_FLOW); - clientFlow.setTopLevel(true); - clientFlow.setBuiltIn(false); - clientFlow = appRealm.addAuthenticationFlow(clientFlow); - appRealm.setClientAuthenticationFlow(clientFlow); - - execution = new AuthenticationExecutionModel(); - execution.setParentFlow(clientFlow.getId()); - execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED); - execution.setAuthenticator(PassThroughClientAuthenticator.PROVIDER_ID); - execution.setPriority(10); - execution.setAuthenticatorFlow(false); - appRealm.addAuthenticatorExecution(execution); - - // Set passthrough clientAuthenticator for our clients - ClientModel dummyClient = KeycloakModelUtils.createClient(appRealm, "dummy-client"); - dummyClient.setClientAuthenticatorType(PassThroughClientAuthenticator.PROVIDER_ID); - dummyClient.setDirectAccessGrantsEnabled(true); - - ClientModel testApp = appRealm.getClientByClientId("test-app"); - testApp.setClientAuthenticatorType(PassThroughClientAuthenticator.PROVIDER_ID); - testApp.setDirectAccessGrantsEnabled(true); - } - }); - - @Rule - public AssertEvents events = new AssertEvents(keycloakRule); - - @Rule - public WebRule webRule = new WebRule(this); - - @WebResource - protected OAuthClient oauth; - - @WebResource - protected WebDriver driver; - - @WebResource - protected AppPage appPage; - - @WebResource - protected LoginPage loginPage; - - @WebResource - protected ErrorPage errorPage; - - @WebResource - protected LoginPasswordUpdatePage updatePasswordPage; - - @WebResource - protected RegisterPage registerPage; - - private static String userId; - - @Test - public void loginSuccess() { - - PassThroughAuthenticator.username = "login-test"; - - oauth.openLoginForm(); - - Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType()); - Assert.assertNotNull(oauth.getCurrentQuery().get(OAuth2Constants.CODE)); - - events.expectLogin().user(userId).detail(Details.USERNAME, "login-test").assertEvent(); - } - - @Test - public void grantTest() throws Exception { - PassThroughAuthenticator.username = "login-test"; - grantAccessToken("test-app", "login-test"); - } - - @Test - public void clientAuthTest() throws Exception { - PassThroughClientAuthenticator.clientId = "dummy-client"; - PassThroughAuthenticator.username = "login-test"; - grantAccessToken("dummy-client", "login-test"); - - PassThroughClientAuthenticator.clientId = "test-app"; - grantAccessToken("test-app", "login-test"); - - PassThroughClientAuthenticator.clientId = "unknown"; - OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("password", "test-user", "password"); - assertEquals(400, response.getStatusCode()); - assertEquals("unauthorized_client", response.getError()); - - events.expectLogin() - .client((String) null) - .user((String) null) - .session((String) null) - .removeDetail(Details.CODE_ID) - .removeDetail(Details.REDIRECT_URI) - .removeDetail(Details.CONSENT) - .error(Errors.INVALID_CLIENT_CREDENTIALS) - .assertEvent(); - } - - - private void grantAccessToken(String clientId, String login) throws Exception { - - OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("password", login, "password"); - - assertEquals(200, response.getStatusCode()); - - AccessToken accessToken = oauth.verifyToken(response.getAccessToken()); - RefreshToken refreshToken = oauth.verifyRefreshToken(response.getRefreshToken()); - - events.expectLogin() - .client(clientId) - .user(userId) - .session(accessToken.getSessionState()) - .detail(Details.GRANT_TYPE, OAuth2Constants.PASSWORD) - .detail(Details.TOKEN_ID, accessToken.getId()) - .detail(Details.REFRESH_TOKEN_ID, refreshToken.getId()) - .detail(Details.USERNAME, login) - .detail(Details.CLIENT_AUTH_METHOD, PassThroughClientAuthenticator.PROVIDER_ID) - .removeDetail(Details.CODE_ID) - .removeDetail(Details.REDIRECT_URI) - .removeDetail(Details.CONSENT) - .assertEvent(); - - assertEquals(accessToken.getSessionState(), refreshToken.getSessionState()); - - OAuthClient.AccessTokenResponse refreshedResponse = oauth.doRefreshTokenRequest(response.getRefreshToken(), "password"); - - AccessToken refreshedAccessToken = oauth.verifyToken(refreshedResponse.getAccessToken()); - RefreshToken refreshedRefreshToken = oauth.verifyRefreshToken(refreshedResponse.getRefreshToken()); - - assertEquals(accessToken.getSessionState(), refreshedAccessToken.getSessionState()); - assertEquals(accessToken.getSessionState(), refreshedRefreshToken.getSessionState()); - - events.expectRefresh(refreshToken.getId(), refreshToken.getSessionState()) - .user(userId) - .client(clientId) - .detail(Details.CLIENT_AUTH_METHOD, PassThroughClientAuthenticator.PROVIDER_ID) - .assertEvent(); - } - - -} diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/CustomRegistrationFlowTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/CustomRegistrationFlowTest.java deleted file mode 100755 index 9f1f2f5684..0000000000 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/CustomRegistrationFlowTest.java +++ /dev/null @@ -1,115 +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.forms; - -import org.junit.Assert; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.keycloak.models.AuthenticationExecutionModel; -import org.keycloak.models.AuthenticationFlowModel; -import org.keycloak.models.RealmModel; -import org.keycloak.services.managers.RealmManager; -import org.keycloak.testsuite.AssertEvents; -import org.keycloak.testsuite.OAuthClient; -import org.keycloak.testsuite.pages.AppPage; -import org.keycloak.testsuite.pages.AppPage.RequestType; -import org.keycloak.testsuite.pages.ErrorPage; -import org.keycloak.testsuite.pages.LoginPage; -import org.keycloak.testsuite.pages.LoginPasswordUpdatePage; -import org.keycloak.testsuite.pages.RegisterPage; -import org.keycloak.testsuite.rule.KeycloakRule; -import org.keycloak.testsuite.rule.WebResource; -import org.keycloak.testsuite.rule.WebRule; -import org.openqa.selenium.WebDriver; - -import static org.junit.Assert.assertEquals; - -/** - * @author Stian Thorgersen - */ -public class CustomRegistrationFlowTest { - - @ClassRule - public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakRule.KeycloakSetup() { - @Override - public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - AuthenticationFlowModel flow = new AuthenticationFlowModel(); - flow.setAlias("dummy registration"); - flow.setDescription("dummy pass through registration"); - flow.setProviderId("basic-flow"); - flow.setTopLevel(true); - flow.setBuiltIn(false); - flow = appRealm.addAuthenticationFlow(flow); - appRealm.setRegistrationFlow(flow); - - AuthenticationExecutionModel execution = new AuthenticationExecutionModel(); - execution.setParentFlow(flow.getId()); - execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED); - execution.setAuthenticator(PassThroughRegistration.PROVIDER_ID); - execution.setPriority(10); - execution.setAuthenticatorFlow(false); - appRealm.addAuthenticatorExecution(execution); - - - } - }); - - @Rule - public AssertEvents events = new AssertEvents(keycloakRule); - - @Rule - public WebRule webRule = new WebRule(this); - - @WebResource - protected OAuthClient oauth; - - @WebResource - protected WebDriver driver; - - @WebResource - protected AppPage appPage; - - @WebResource - protected LoginPage loginPage; - - @WebResource - protected ErrorPage errorPage; - - @WebResource - protected LoginPasswordUpdatePage updatePasswordPage; - - @WebResource - protected RegisterPage registerPage; - - private static String userId; - - @Test - public void registerUserSuccess() { - loginPage.open(); - loginPage.clickRegister(); - - Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType()); - - String userId = events.expectRegister(PassThroughRegistration.username, PassThroughRegistration.email).assertEvent().getUserId(); - events.expectLogin().detail("username", PassThroughRegistration.username).user(userId).assertEvent(); - } - - - - -}