KEYCLOAK-2906 Migrate forms package to new testsuite

This commit is contained in:
Stan Silvert 2016-05-04 17:24:37 -04:00
parent 5abe06a2b7
commit c392f6659e
25 changed files with 949 additions and 806 deletions

View file

@ -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 {
}

View file

@ -30,7 +30,7 @@ import javax.ws.rs.core.UriBuilder;
public class AppPage extends AbstractPage { public class AppPage extends AbstractPage {
public static final String AUTH_SERVER_URL = "http://localhost:8180/auth"; 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") @FindBy(id = "account")
private WebElement accountLink; private WebElement accountLink;

View file

@ -21,6 +21,8 @@ import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RealmRepresentation;
import java.util.List; 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; 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 { 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<UserRepresentation> 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) { protected ClientRepresentation findTestApp(RealmRepresentation testRealm) {
for (ClientRepresentation client : testRealm.getClients()) { for (ClientRepresentation client : testRealm.getClients()) {
if (client.getClientId().equals("test-app")) return client; if (client.getClientId().equals("test-app")) return client;

View file

@ -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"); "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 " + 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"); "'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); 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."); "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. " + 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."); "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; return result;
} }

View file

@ -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);
}
}

View file

@ -18,94 +18,78 @@ package org.keycloak.testsuite.forms;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.keycloak.events.Details; import org.keycloak.events.Details;
import org.keycloak.events.Errors; import org.keycloak.events.Errors;
import org.keycloak.models.Constants; 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.models.utils.TimeBasedOTP;
import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.testsuite.AssertEvents; import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.OAuthClient;
import org.keycloak.testsuite.pages.AppPage; import org.keycloak.testsuite.pages.AppPage;
import org.keycloak.testsuite.pages.AppPage.RequestType; import org.keycloak.testsuite.pages.AppPage.RequestType;
import org.keycloak.testsuite.pages.LoginPage; import org.keycloak.testsuite.pages.LoginPage;
import org.keycloak.testsuite.pages.LoginTotpPage; import org.keycloak.testsuite.pages.LoginTotpPage;
import org.keycloak.testsuite.pages.RegisterPage; 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.Client;
import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.net.MalformedURLException; 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 <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
* @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
*/ */
public class BruteForceTest { public class BruteForceTest extends TestRealmKeycloakTest {
@ClassRule @Override
public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakSetup() { 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 testRealm.setBruteForceProtected(true);
public void config(RealmManager manager, RealmModel defaultRealm, RealmModel appRealm) { testRealm.setFailureFactor(2);
UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm);
UserCredentialModel credentials = new UserCredentialModel(); findClientInRealmRep(testRealm, "test-app").setDirectAccessGrantsEnabled(true);
credentials.setType(CredentialRepresentation.TOTP); }
credentials.setValue("totpSecret");
user.updateCredential(credentials);
user.setOtpEnabled(true); @Before
appRealm.setEventsListeners(Collections.singleton("dummy")); public void config() {
appRealm.setBruteForceProtected(true); }
appRealm.setFailureFactor(2);
appRealm.getClientByClientId("test-app").setDirectAccessGrantsEnabled(true);
}
});
@Rule @Rule
public AssertEvents events = new AssertEvents(keycloakRule); public AssertEvents events = new AssertEvents(this);
@Rule
public WebRule webRule = new WebRule(this);
@Rule @Rule
public GreenMailRule greenMail = new GreenMailRule(); public GreenMailRule greenMail = new GreenMailRule();
@WebResource @Page
protected WebDriver driver;
@WebResource
protected AppPage appPage; protected AppPage appPage;
@WebResource @Page
protected LoginPage loginPage; protected LoginPage loginPage;
@WebResource @Page
private RegisterPage registerPage; private RegisterPage registerPage;
@WebResource @Page
protected LoginTotpPage loginTotpPage; protected LoginTotpPage loginTotpPage;
@WebResource
protected OAuthClient oauth;
private TimeBasedOTP totp = new TimeBasedOTP(); private TimeBasedOTP totp = new TimeBasedOTP();
private int lifespan; private int lifespan;

View file

@ -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 <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
* @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();
}
}

View file

@ -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 <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
* @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();
}
}

View file

@ -18,82 +18,58 @@ package org.keycloak.testsuite.forms;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.keycloak.events.Details; import org.keycloak.events.Details;
import org.keycloak.models.OTPPolicy; 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.models.utils.HmacOTP;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.testsuite.AssertEvents; import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.pages.AppPage; import org.keycloak.testsuite.pages.AppPage;
import org.keycloak.testsuite.pages.AppPage.RequestType; import org.keycloak.testsuite.pages.AppPage.RequestType;
import org.keycloak.testsuite.pages.LoginPage; import org.keycloak.testsuite.pages.LoginPage;
import org.keycloak.testsuite.pages.LoginTotpPage; 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.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 <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
* @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
*/ */
public class LoginHotpTest { public class LoginHotpTest extends TestRealmKeycloakTest {
public static OTPPolicy policy; public static OTPPolicy policy;
@ClassRule
public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakSetup() {
@Override @Override
public void config(RealmManager manager, RealmModel defaultRealm, RealmModel appRealm) { public void configureTestRealm(RealmRepresentation testRealm) {
UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm); UserRepresentation user = findUserInRealmRep(testRealm, "test-user@localhost");
policy = appRealm.getOTPPolicy(); UserBuilder.edit(user)
policy.setType(UserCredentialModel.HOTP); .hotpSecret("hotpSecret")
policy.setLookAheadWindow(2); .otpEnabled();
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"));
}
});
@Rule @Rule
public AssertEvents events = new AssertEvents(keycloakRule); public AssertEvents events = new AssertEvents(this);
@Rule
public WebRule webRule = new WebRule(this);
@Rule @Rule
public GreenMailRule greenMail = new GreenMailRule(); public GreenMailRule greenMail = new GreenMailRule();
@WebResource @Page
protected WebDriver driver;
@WebResource
protected AppPage appPage; protected AppPage appPage;
@WebResource @Page
protected LoginPage loginPage; protected LoginPage loginPage;
@WebResource @Page
protected LoginTotpPage loginTotpPage; 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; private int lifespan;
@ -101,6 +77,19 @@ public class LoginHotpTest {
@Before @Before
public void before() throws MalformedURLException { 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()); otp = new HmacOTP(policy.getDigits(), policy.getAlgorithm(), policy.getLookAheadWindow());
} }
@ -109,7 +98,7 @@ public class LoginHotpTest {
loginPage.open(); loginPage.open();
loginPage.login("test-user@localhost", "password"); loginPage.login("test-user@localhost", "password");
loginTotpPage.assertCurrent(); Assert.assertTrue(loginTotpPage.isCurrent());
loginTotpPage.login("123456"); loginTotpPage.login("123456");
loginTotpPage.assertCurrent(); loginTotpPage.assertCurrent();
@ -128,7 +117,7 @@ public class LoginHotpTest {
loginPage.open(); loginPage.open();
loginPage.login("test-user@localhost", "password"); loginPage.login("test-user@localhost", "password");
loginTotpPage.assertCurrent(); Assert.assertTrue(loginTotpPage.isCurrent());
loginTotpPage.login(null); loginTotpPage.login(null);
loginTotpPage.assertCurrent(); loginTotpPage.assertCurrent();
@ -147,7 +136,7 @@ public class LoginHotpTest {
loginPage.open(); loginPage.open();
loginPage.login("test-user@localhost", "password"); loginPage.login("test-user@localhost", "password");
loginTotpPage.assertCurrent(); Assert.assertTrue(loginTotpPage.isCurrent());
loginTotpPage.login(otp.generateHOTP("hotpSecret", counter++)); loginTotpPage.login(otp.generateHOTP("hotpSecret", counter++));
@ -161,7 +150,7 @@ public class LoginHotpTest {
loginPage.open(); loginPage.open();
loginPage.login("test-user@localhost", "invalid"); loginPage.login("test-user@localhost", "invalid");
loginPage.assertCurrent(); Assert.assertTrue(loginPage.isCurrent());
Assert.assertEquals("Invalid username or password.", loginPage.getError()); Assert.assertEquals("Invalid username or password.", loginPage.getError());

View file

@ -18,73 +18,51 @@ package org.keycloak.testsuite.forms;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.keycloak.events.Details; 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.models.utils.TimeBasedOTP;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.testsuite.AssertEvents; import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.pages.AppPage; import org.keycloak.testsuite.pages.AppPage;
import org.keycloak.testsuite.pages.AppPage.RequestType; import org.keycloak.testsuite.pages.AppPage.RequestType;
import org.keycloak.testsuite.pages.LoginPage; import org.keycloak.testsuite.pages.LoginPage;
import org.keycloak.testsuite.pages.LoginTotpPage; 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.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 <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
* @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
*/ */
public class LoginTotpTest { public class LoginTotpTest extends TestRealmKeycloakTest {
@ClassRule @Override
public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakSetup() { public void configureTestRealm(RealmRepresentation testRealm) {
UserRepresentation user = findUserInRealmRep(testRealm, "test-user@localhost");
@Override UserBuilder.edit(user)
public void config(RealmManager manager, RealmModel defaultRealm, RealmModel appRealm) { .totpSecret("totpSecret")
UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm); .otpEnabled();
}
UserCredentialModel credentials = new UserCredentialModel();
credentials.setType(CredentialRepresentation.TOTP);
credentials.setValue("totpSecret");
user.updateCredential(credentials);
user.setOtpEnabled(true);
appRealm.setEventsListeners(Collections.singleton("dummy"));
}
});
@Rule @Rule
public AssertEvents events = new AssertEvents(keycloakRule); public AssertEvents events = new AssertEvents(this);
@Rule
public WebRule webRule = new WebRule(this);
@Rule @Rule
public GreenMailRule greenMail = new GreenMailRule(); public GreenMailRule greenMail = new GreenMailRule();
@WebResource @Page
protected WebDriver driver;
@WebResource
protected AppPage appPage; protected AppPage appPage;
@WebResource @Page
protected LoginPage loginPage; protected LoginPage loginPage;
@WebResource @Page
protected LoginTotpPage loginTotpPage; protected LoginTotpPage loginTotpPage;
private TimeBasedOTP totp = new TimeBasedOTP(); private TimeBasedOTP totp = new TimeBasedOTP();
@ -101,7 +79,7 @@ public class LoginTotpTest {
loginPage.open(); loginPage.open();
loginPage.login("test-user@localhost", "password"); loginPage.login("test-user@localhost", "password");
loginTotpPage.assertCurrent(); Assert.assertTrue(loginTotpPage.isCurrent());
loginTotpPage.login("123456"); loginTotpPage.login("123456");
loginTotpPage.assertCurrent(); loginTotpPage.assertCurrent();
@ -120,7 +98,7 @@ public class LoginTotpTest {
loginPage.open(); loginPage.open();
loginPage.login("test-user@localhost", "password"); loginPage.login("test-user@localhost", "password");
loginTotpPage.assertCurrent(); Assert.assertTrue(loginTotpPage.isCurrent());
loginTotpPage.login(null); loginTotpPage.login(null);
loginTotpPage.assertCurrent(); loginTotpPage.assertCurrent();
@ -139,7 +117,7 @@ public class LoginTotpTest {
loginPage.open(); loginPage.open();
loginPage.login("test-user@localhost", "password"); loginPage.login("test-user@localhost", "password");
loginTotpPage.assertCurrent(); Assert.assertTrue(loginTotpPage.isCurrent());
loginTotpPage.login(totp.generateTOTP("totpSecret")); loginTotpPage.login(totp.generateTOTP("totpSecret"));
@ -153,7 +131,7 @@ public class LoginTotpTest {
loginPage.open(); loginPage.open();
loginPage.login("test-user@localhost", "password"); loginPage.login("test-user@localhost", "password");
loginTotpPage.assertCurrent(); Assert.assertTrue(loginTotpPage.isCurrent());
loginTotpPage.cancel(); loginTotpPage.cancel();
loginPage.assertCurrent(); loginPage.assertCurrent();
} }
@ -163,7 +141,7 @@ public class LoginTotpTest {
loginPage.open(); loginPage.open();
loginPage.login("test-user@localhost", "invalid"); loginPage.login("test-user@localhost", "invalid");
loginPage.assertCurrent(); Assert.assertTrue(loginPage.isCurrent());
Assert.assertEquals("Invalid username or password.", loginPage.getError()); Assert.assertEquals("Invalid username or password.", loginPage.getError());

View file

@ -16,49 +16,39 @@
*/ */
package org.keycloak.testsuite.forms; package org.keycloak.testsuite.forms;
import org.junit.ClassRule;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.keycloak.events.Details; import org.keycloak.events.Details;
import org.keycloak.testsuite.AssertEvents; import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.OAuthClient;
import org.keycloak.testsuite.pages.AppPage; import org.keycloak.testsuite.pages.AppPage;
import org.keycloak.testsuite.pages.LoginPage; 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 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.*; import static org.junit.Assert.*;
/** /**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
* @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
*/ */
public class LogoutTest { public class LogoutTest extends TestRealmKeycloakTest {
@ClassRule
public static KeycloakRule keycloakRule = new KeycloakRule();
@Rule @Rule
public AssertEvents events = new AssertEvents(keycloakRule); public AssertEvents events = new AssertEvents(this);
@Rule @Page
public WebRule webRule = new WebRule(this);
@WebResource
protected OAuthClient oauth;
@WebResource
protected WebDriver driver;
@WebResource
protected AppPage appPage; protected AppPage appPage;
@WebResource @Page
protected LoginPage loginPage; protected LoginPage loginPage;
@Override
public void configureTestRealm(RealmRepresentation testRealm) {
}
@Test @Test
public void logoutRedirect() { public void logoutRedirect() {
loginPage.open(); loginPage.open();

View file

@ -16,54 +16,41 @@
*/ */
package org.keycloak.testsuite.forms; package org.keycloak.testsuite.forms;
import org.jboss.arquillian.graphene.page.Page;
import org.junit.*; import org.junit.*;
import org.keycloak.events.Details; import org.keycloak.events.Details;
import org.keycloak.models.KeycloakSession; import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.models.PasswordPolicy; import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.testsuite.AssertEvents; 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;
import org.keycloak.testsuite.pages.AppPage.RequestType; import org.keycloak.testsuite.pages.AppPage.RequestType;
import org.keycloak.testsuite.pages.LoginPage; import org.keycloak.testsuite.pages.LoginPage;
import org.keycloak.testsuite.pages.RegisterPage; 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; import static org.junit.Assert.assertEquals;
/** /**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
* @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
*/ */
public class RegisterTest { public class RegisterTest extends TestRealmKeycloakTest {
@ClassRule
public static KeycloakRule keycloakRule = new KeycloakRule();
@Rule @Rule
public AssertEvents events = new AssertEvents(keycloakRule); public AssertEvents events = new AssertEvents(this);
@Rule @Page
public WebRule webRule = new WebRule(this);
@WebResource
protected WebDriver driver;
@WebResource
protected AppPage appPage; protected AppPage appPage;
@WebResource @Page
protected LoginPage loginPage; protected LoginPage loginPage;
@WebResource @Page
protected RegisterPage registerPage; protected RegisterPage registerPage;
@WebResource @Override
protected OAuthClient oauth; public void configureTestRealm(RealmRepresentation testRealm) {
}
@Test @Test
public void registerExistingUser() { public void registerExistingUser() {
@ -133,12 +120,15 @@ public class RegisterTest {
@Test @Test
public void registerPasswordPolicy() { public void registerPasswordPolicy() {
keycloakRule.configure(new KeycloakRule.KeycloakSetup() { /*keycloakRule.configure(new KeycloakRule.KeycloakSetup() {
@Override @Override
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
appRealm.setPasswordPolicy(new PasswordPolicy("length")); appRealm.setPasswordPolicy(new PasswordPolicy("length"));
} }
}); });*/
RealmRepresentation realm = testRealm().toRepresentation();
realm.setPasswordPolicy("length");
testRealm().update(realm);
try { try {
loginPage.open(); loginPage.open();
@ -162,12 +152,12 @@ public class RegisterTest {
events.expectLogin().user(userId).detail(Details.USERNAME, "registerpasswordpolicy").assertEvent(); events.expectLogin().user(userId).detail(Details.USERNAME, "registerpasswordpolicy").assertEvent();
} finally { } finally {
keycloakRule.configure(new KeycloakRule.KeycloakSetup() { /*keycloakRule.configure(new KeycloakRule.KeycloakSetup() {
@Override @Override
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
appRealm.setPasswordPolicy(new PasswordPolicy(null)); appRealm.setPasswordPolicy(new PasswordPolicy(null));
} }
}); });*/
} }
} }
@ -251,7 +241,7 @@ public class RegisterTest {
String userId = events.expectRegister("registerUserSuccess", "registerUserSuccess@email").assertEvent().getUserId(); String userId = events.expectRegister("registerUserSuccess", "registerUserSuccess@email").assertEvent().getUserId();
events.expectLogin().detail("username", "registerusersuccess").user(userId).assertEvent(); events.expectLogin().detail("username", "registerusersuccess").user(userId).assertEvent();
UserModel user = getUser(userId); UserRepresentation user = getUser(userId);
Assert.assertNotNull(user); Assert.assertNotNull(user);
Assert.assertNotNull(user.getCreatedTimestamp()); Assert.assertNotNull(user.getCreatedTimestamp());
// test that timestamp is current with 10s tollerance // test that timestamp is current with 10s tollerance
@ -263,7 +253,7 @@ public class RegisterTest {
assertEquals("lastName", user.getLastName()); assertEquals("lastName", user.getLastName());
} }
protected UserModel getUser(String userId) { /*protected UserModel getUser(String userId) {
KeycloakSession samlServerSession = keycloakRule.startSession(); KeycloakSession samlServerSession = keycloakRule.startSession();
try { try {
RealmModel brokerRealm = samlServerSession.realms().getRealm("test"); RealmModel brokerRealm = samlServerSession.realms().getRealm("test");
@ -271,6 +261,10 @@ public class RegisterTest {
} finally { } finally {
keycloakRule.stopSession(samlServerSession, false); keycloakRule.stopSession(samlServerSession, false);
} }
}*/
protected UserRepresentation getUser(String userId) {
return testRealm().users().get(userId).toRepresentation();
} }
@Test @Test
@ -319,7 +313,7 @@ public class RegisterTest {
@Test @Test
public void registerUserSuccess_emailAsUsername() { public void registerUserSuccess_emailAsUsername() {
configureRelamRegistrationEmailAsUsername(true); configureRelamRegistrationEmailAsUsername(true);
try { try {
loginPage.open(); loginPage.open();
loginPage.clickRegister(); loginPage.clickRegister();
@ -332,7 +326,7 @@ public class RegisterTest {
String userId = events.expectRegister("registerUserSuccessE@email", "registerUserSuccessE@email").assertEvent().getUserId(); String userId = events.expectRegister("registerUserSuccessE@email", "registerUserSuccessE@email").assertEvent().getUserId();
events.expectLogin().detail("username", "registerusersuccesse@email").user(userId).assertEvent(); events.expectLogin().detail("username", "registerusersuccesse@email").user(userId).assertEvent();
UserModel user = getUser(userId); UserRepresentation user = getUser(userId);
Assert.assertNotNull(user); Assert.assertNotNull(user);
Assert.assertNotNull(user.getCreatedTimestamp()); Assert.assertNotNull(user.getCreatedTimestamp());
// test that timestamp is current with 10s tollerance // test that timestamp is current with 10s tollerance
@ -344,12 +338,9 @@ public class RegisterTest {
} }
protected void configureRelamRegistrationEmailAsUsername(final boolean value) { protected void configureRelamRegistrationEmailAsUsername(final boolean value) {
keycloakRule.configure(new KeycloakRule.KeycloakSetup() { RealmRepresentation realm = testRealm().toRepresentation();
@Override realm.setRegistrationEmailAsUsername(value);
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { testRealm().update(realm);
appRealm.setRegistrationEmailAsUsername(value);
}
});
} }
} }

View file

@ -19,122 +19,96 @@ package org.keycloak.testsuite.forms;
import org.junit.*; import org.junit.*;
import org.keycloak.events.Details; import org.keycloak.events.Details;
import org.keycloak.events.Errors; import org.keycloak.events.Errors;
import org.keycloak.events.Event;
import org.keycloak.events.EventType; 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.AssertEvents;
import org.keycloak.testsuite.Constants; //import org.keycloak.testsuite.Constants;
import org.keycloak.testsuite.MailUtil; import org.keycloak.testsuite.util.MailUtils;
import org.keycloak.testsuite.OAuthClient;
import org.keycloak.testsuite.pages.*; import org.keycloak.testsuite.pages.*;
import org.keycloak.testsuite.pages.AppPage.RequestType; 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.MessagingException;
import javax.mail.Multipart; import javax.mail.Multipart;
import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMessage;
import java.io.IOException; import java.io.IOException;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger; 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.*; import static org.junit.Assert.*;
/** /**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
* @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
*/ */
public class ResetPasswordTest { public class ResetPasswordTest extends TestRealmKeycloakTest {
static int lifespan = 0; 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(); @Before
creds.setType(CredentialRepresentation.PASSWORD); public void setAccessCodeLifespanUserAction() {
creds.setValue("password"); // 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; private static String userId;
@Rule
public WebRule webRule = new WebRule(this);
@Rule @Rule
public GreenMailRule greenMail = new GreenMailRule(); public GreenMailRule greenMail = new GreenMailRule();
@WebResource @Page
protected WebDriver driver;
@WebResource
protected OAuthClient oauth;
@WebResource
protected AppPage appPage; protected AppPage appPage;
@WebResource @Page
protected LoginPage loginPage; protected LoginPage loginPage;
@WebResource @Page
protected ErrorPage errorPage; protected ErrorPage errorPage;
@WebResource @Page
protected InfoPage infoPage; protected InfoPage infoPage;
@WebResource @Page
protected VerifyEmailPage verifyEmailPage; protected VerifyEmailPage verifyEmailPage;
@WebResource @Page
protected LoginPasswordResetPage resetPasswordPage; protected LoginPasswordResetPage resetPasswordPage;
@WebResource @Page
protected LoginPasswordUpdatePage updatePasswordPage; protected LoginPasswordUpdatePage updatePasswordPage;
@Rule @Rule
public AssertEvents events = new AssertEvents(keycloakRule); public AssertEvents events = new AssertEvents(this);
@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);
}
});
}
@Test @Test
public void resetPasswordLink() throws IOException, MessagingException { public void resetPasswordLink() throws IOException, MessagingException {
String username = "login-test"; 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); driver.navigate().to(resetUri);
resetPasswordPage.assertCurrent(); resetPasswordPage.assertCurrent();
@ -146,7 +120,7 @@ public class ResetPasswordTest {
events.expectRequiredAction(EventType.SEND_RESET_PASSWORD) events.expectRequiredAction(EventType.SEND_RESET_PASSWORD)
.user(userId) .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") .client("account")
.detail(Details.USERNAME, username) .detail(Details.USERNAME, username)
.detail(Details.EMAIL, "login@test.com") .detail(Details.EMAIL, "login@test.com")
@ -166,12 +140,12 @@ public class ResetPasswordTest {
updatePasswordPage.changePassword("resetPassword", "resetPassword"); updatePasswordPage.changePassword("resetPassword", "resetPassword");
String sessionId = events.expectRequiredAction(EventType.UPDATE_PASSWORD) 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") .client("account")
.user(userId).detail(Details.USERNAME, username).assertEvent().getSessionId(); .user(userId).detail(Details.USERNAME, username).assertEvent().getSessionId();
events.expectLogin().user(userId).detail(Details.USERNAME, username) 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") .client("account")
.session(sessionId).assertEvent(); .session(sessionId).assertEvent();
@ -213,7 +187,7 @@ public class ResetPasswordTest {
loginPage.login("login@test.com", "password"); 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"); String code = oauth.getCurrentQuery().get("code");
OAuthClient.AccessTokenResponse tokenResponse = oauth.doAccessTokenRequest(code, "password"); 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(); 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 @Test
public void resetPasswordMissingUsername() throws IOException, MessagingException, InterruptedException { public void resetPasswordMissingUsername() throws IOException, MessagingException, InterruptedException {
loginPage.open(); loginPage.open();
@ -373,9 +347,9 @@ public class ResetPasswordTest {
assertEquals("Please specify username.", resetPasswordPage.getErrorMessage()); assertEquals("Please specify username.", resetPasswordPage.getErrorMessage());
assertEquals(0, greenMail.getReceivedMessages().length); assertEquals(0, greenMail.getReceivedMessages().length);
events.expectRequiredAction(EventType.RESET_PASSWORD).user((String) null).session((String) null).clearDetails().error("username_missing").assertEvent(); events.expectRequiredAction(EventType.RESET_PASSWORD).user((String) null).session((String) null).clearDetails().error("username_missing").assertEvent();
} }
@Test @Test
@ -401,7 +375,7 @@ public class ResetPasswordTest {
String changePasswordUrl = getPasswordResetEmailLink(message); String changePasswordUrl = getPasswordResetEmailLink(message);
Time.setOffset(1800 + 23); setTimeOffset(1800 + 23);
driver.navigate().to(changePasswordUrl.trim()); 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(); events.expectRequiredAction(EventType.RESET_PASSWORD).error("expired_code").client("test-app").user((String) null).session((String) null).clearDetails().assertEvent();
} finally { } finally {
Time.setOffset(0); setTimeOffset(0);
} }
} }
@Test @Test
public void resetPasswordExpiredCodeShort() throws IOException, MessagingException, InterruptedException { public void resetPasswordExpiredCodeShort() throws IOException, MessagingException, InterruptedException {
final AtomicInteger originalValue = new AtomicInteger(); final AtomicInteger originalValue = new AtomicInteger();
keycloakRule.configure(new KeycloakRule.KeycloakSetup() {
@Override RealmRepresentation realmRep = testRealm().toRepresentation();
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { originalValue.set(realmRep.getAccessCodeLifespan());
originalValue.set(appRealm.getAccessCodeLifespan()); realmRep.setAccessCodeLifespanUserAction(60);
appRealm.setAccessCodeLifespanUserAction(60); testRealm().update(realmRep);
}
});
try { try {
loginPage.open(); loginPage.open();
@ -447,7 +419,7 @@ public class ResetPasswordTest {
String changePasswordUrl = getPasswordResetEmailLink(message); String changePasswordUrl = getPasswordResetEmailLink(message);
Time.setOffset(70); setTimeOffset(70);
driver.navigate().to(changePasswordUrl.trim()); 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(); events.expectRequiredAction(EventType.RESET_PASSWORD).error("expired_code").client("test-app").user((String) null).session((String) null).clearDetails().assertEvent();
} finally { } finally {
Time.setOffset(0); setTimeOffset(0);
keycloakRule.configure(new KeycloakRule.KeycloakSetup() {
@Override
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
appRealm.setAccessCodeLifespanUserAction(originalValue.get());
}
});
} }
} }
@Test @Test
public void resetPasswordDisabledUser() throws IOException, MessagingException, InterruptedException { public void resetPasswordDisabledUser() throws IOException, MessagingException, InterruptedException {
keycloakRule.configure(new KeycloakRule.KeycloakSetup() { UserRepresentation user = findUser("login-test");
@Override user.setEnabled(false);
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { updateUser(user);
session.users().getUserByUsername("login-test", appRealm).setEnabled(false);
}
});
try { loginPage.open();
loginPage.open(); loginPage.resetPassword();
loginPage.resetPassword();
resetPasswordPage.assertCurrent(); resetPasswordPage.assertCurrent();
resetPasswordPage.changePassword("login-test"); resetPasswordPage.changePassword("login-test");
loginPage.assertCurrent(); loginPage.assertCurrent();
assertEquals("You should receive an email shortly with further instructions.", loginPage.getSuccessMessage()); 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(); 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);
}
});
}
} }
@Test @Test
public void resetPasswordNoEmail() throws IOException, MessagingException, InterruptedException { public void resetPasswordNoEmail() throws IOException, MessagingException, InterruptedException {
final String[] email = new String[1]; 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.open(); loginPage.resetPassword();
loginPage.resetPassword();
resetPasswordPage.assertCurrent(); resetPasswordPage.assertCurrent();
resetPasswordPage.changePassword("login-test"); resetPasswordPage.changePassword("login-test");
loginPage.assertCurrent(); loginPage.assertCurrent();
assertEquals("You should receive an email shortly with further instructions.", loginPage.getSuccessMessage()); 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(); 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]);
}
});
}
} }
@Test @Test
public void resetPasswordWrongSmtp() throws IOException, MessagingException, InterruptedException { public void resetPasswordWrongSmtp() throws IOException, MessagingException, InterruptedException {
final String[] host = new String[1]; final String[] host = new String[1];
keycloakRule.configure(new KeycloakRule.KeycloakSetup() {
@Override
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
Map<String, String> smtpConfig = new HashMap<>();
smtpConfig.putAll(appRealm.getSmtpConfig());
host[0] = smtpConfig.get("host");
smtpConfig.put("host", "invalid_host");
appRealm.setSmtpConfig(smtpConfig);
}
});
try { Map<String, String> smtpConfig = new HashMap<>();
loginPage.open(); smtpConfig.putAll(testRealm().toRepresentation().getSmtpServer());
loginPage.resetPassword(); 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) assertEquals(0, greenMail.getReceivedMessages().length);
.session((String)null)
.detail(Details.USERNAME, "login-test").removeDetail(Details.CODE_ID).error(Errors.EMAIL_SEND_FAILED).assertEvent(); events.expectRequiredAction(EventType.SEND_RESET_PASSWORD_ERROR).user(userId)
} finally { .session((String)null)
keycloakRule.configure(new KeycloakRule.KeycloakSetup() { .detail(Details.USERNAME, "login-test").removeDetail(Details.CODE_ID).error(Errors.EMAIL_SEND_FAILED).assertEvent();
@Override }
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
Map<String, String> smtpConfig = new HashMap<>(); private void setPasswordPolicy(String policy) {
smtpConfig.putAll(appRealm.getSmtpConfig()); RealmRepresentation realmRep = testRealm().toRepresentation();
smtpConfig.put("host",host[0]); realmRep.setPasswordPolicy(policy);
appRealm.setSmtpConfig(smtpConfig); testRealm().update(realmRep);
}
});
}
} }
@Test @Test
public void resetPasswordWithLengthPasswordPolicy() throws IOException, MessagingException { public void resetPasswordWithLengthPasswordPolicy() throws IOException, MessagingException {
keycloakRule.update(new KeycloakRule.KeycloakSetup() { setPasswordPolicy("length");
@Override
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
appRealm.setPasswordPolicy(new PasswordPolicy("length"));
}
});
loginPage.open(); loginPage.open();
loginPage.resetPassword(); loginPage.resetPassword();
@ -640,62 +567,51 @@ public class ResetPasswordTest {
@Test @Test
public void resetPasswordWithPasswordHisoryPolicy() throws IOException, MessagingException { public void resetPasswordWithPasswordHisoryPolicy() throws IOException, MessagingException {
keycloakRule.update(new KeycloakRule.KeycloakSetup() { //Block passwords that are equal to previous passwords. Default value is 3.
@Override setPasswordPolicy("passwordHistory");
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"));
}
});
try { try {
Time.setOffset(2000000); setTimeOffset(2000000);
resetPassword("login-test", "password1"); resetPassword("login-test", "password1");
resetPasswordInvalidPassword("login-test", "password1", "Invalid password: must not be equal to any of last 3 passwords."); 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"); resetPassword("login-test", "password2");
resetPasswordInvalidPassword("login-test", "password1", "Invalid password: must not be equal to any of last 3 passwords."); 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", "password2", "Invalid password: must not be equal to any of last 3 passwords.");
Time.setOffset(8000000); setTimeOffset(8000000);
resetPassword("login-test", "password3"); resetPassword("login-test", "password3");
resetPasswordInvalidPassword("login-test", "password1", "Invalid password: must not be equal to any of last 3 passwords."); 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", "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."); resetPasswordInvalidPassword("login-test", "password3", "Invalid password: must not be equal to any of last 3 passwords.");
resetPassword("login-test", "password"); resetPassword("login-test", "password");
} finally { } finally {
keycloakRule.update(new KeycloakRule.KeycloakSetup() { setTimeOffset(0);
@Override
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
appRealm.setPasswordPolicy(new PasswordPolicy(null));
}
});
Time.setOffset(0);
} }
} }
public static String getPasswordResetEmailLink(MimeMessage message) throws IOException, MessagingException { public static String getPasswordResetEmailLink(MimeMessage message) throws IOException, MessagingException {
Multipart multipart = (Multipart) message.getContent(); Multipart multipart = (Multipart) message.getContent();
final String textContentType = multipart.getBodyPart(0).getContentType(); final String textContentType = multipart.getBodyPart(0).getContentType();
assertEquals("text/plain; charset=UTF-8", textContentType); assertEquals("text/plain; charset=UTF-8", textContentType);
final String textBody = (String) multipart.getBodyPart(0).getContent(); 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(); final String htmlContentType = multipart.getBodyPart(1).getContentType();
assertEquals("text/html; charset=UTF-8", htmlContentType); assertEquals("text/html; charset=UTF-8", htmlContentType);
final String htmlBody = (String) multipart.getBodyPart(1).getContent(); final String htmlBody = (String) multipart.getBodyPart(1).getContent();
final String htmlChangePwdUrl = MailUtil.getLink(htmlBody); final String htmlChangePwdUrl = MailUtils.getLink(htmlBody);
assertEquals(htmlChangePwdUrl, textChangePwdUrl); assertEquals(htmlChangePwdUrl, textChangePwdUrl);
return htmlChangePwdUrl; return htmlChangePwdUrl;

View file

@ -16,22 +16,23 @@
*/ */
package org.keycloak.testsuite.forms; 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.Assert;
import org.junit.ClassRule;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.keycloak.OAuth2Constants; import org.keycloak.OAuth2Constants;
import org.keycloak.events.Details; 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.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.AccountUpdateProfilePage;
import org.keycloak.testsuite.pages.AppPage; import org.keycloak.testsuite.pages.AppPage;
import org.keycloak.testsuite.pages.AppPage.RequestType; import org.keycloak.testsuite.pages.AppPage.RequestType;
import org.keycloak.testsuite.pages.LoginPage; import org.keycloak.testsuite.pages.LoginPage;
import org.keycloak.testsuite.rule.KeycloakRule; import org.keycloak.testsuite.util.OAuthClient;
import org.keycloak.testsuite.rule.WebResource;
import org.keycloak.testsuite.rule.WebRule;
import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriver;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@ -40,38 +41,35 @@ import static org.junit.Assert.assertTrue;
/** /**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
* @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
*/ */
public class SSOTest { public class SSOTest extends TestRealmKeycloakTest {
@ClassRule @Drone
public static KeycloakRule keycloakRule = new KeycloakRule(); @Different
protected WebDriver driver2;
@Rule @Page
public WebRule webRule = new WebRule(this);
@WebResource
protected OAuthClient oauth;
@WebResource
protected WebDriver driver;
@WebResource
protected AppPage appPage; protected AppPage appPage;
@WebResource @Page
protected LoginPage loginPage; protected LoginPage loginPage;
@WebResource @Page
protected AccountUpdateProfilePage profilePage; protected AccountUpdateProfilePage profilePage;
@Rule @Rule
public AssertEvents events = new AssertEvents(keycloakRule); public AssertEvents events = new AssertEvents(this);
@Override
public void configureTestRealm(RealmRepresentation testRealm) {
}
@Test @Test
public void loginSuccess() { public void loginSuccess() {
loginPage.open(); loginPage.open();
loginPage.login("test-user@localhost", "password"); loginPage.login("test-user@localhost", "password");
assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType()); assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
Assert.assertNotNull(oauth.getCurrentQuery().get(OAuth2Constants.CODE)); Assert.assertNotNull(oauth.getCurrentQuery().get(OAuth2Constants.CODE));
@ -92,7 +90,7 @@ public class SSOTest {
assertEquals(sessionId, sessionId2); assertEquals(sessionId, sessionId2);
// Expire session // Expire session
keycloakRule.removeUserSession(sessionId); testingClient.testing().removeUserSession("test", sessionId);
oauth.doLogin("test-user@localhost", "password"); oauth.doLogin("test-user@localhost", "password");
@ -110,15 +108,18 @@ public class SSOTest {
Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType()); Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
Assert.assertNotNull(oauth.getCurrentQuery().get(OAuth2Constants.CODE)); Assert.assertNotNull(oauth.getCurrentQuery().get(OAuth2Constants.CODE));
Event login1 = events.expectLogin().assertEvent(); EventRepresentation login1 = events.expectLogin().assertEvent();
WebDriver driver2 = WebRule.createWebDriver();
try { 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.state("mystate");
oauth2.doLogin("test-user@localhost", "password"); 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.assertEquals(RequestType.AUTH_RESPONSE, RequestType.valueOf(driver2.getTitle()));
Assert.assertNotNull(oauth2.getCurrentQuery().get(OAuth2Constants.CODE)); Assert.assertNotNull(oauth2.getCurrentQuery().get(OAuth2Constants.CODE));

View file

@ -43,6 +43,11 @@ public class ClientBuilder {
return this; return this;
} }
public ClientBuilder name(String name) {
rep.setName(name);
return this;
}
public ClientBuilder clientId(String clientId) { public ClientBuilder clientId(String clientId) {
rep.setClientId(clientId); rep.setClientId(clientId);
return this; return this;

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -122,20 +122,33 @@ public class UserBuilder {
return this; return this;
} }
public UserBuilder totpSecret(String totpSecret) { public UserBuilder secret(String type, String secret) {
if (rep.getCredentials() == null) { if (rep.getCredentials() == null) {
rep.setCredentials(new LinkedList<CredentialRepresentation>()); rep.setCredentials(new LinkedList<CredentialRepresentation>());
} }
CredentialRepresentation credential = new CredentialRepresentation(); CredentialRepresentation credential = new CredentialRepresentation();
credential.setType(CredentialRepresentation.TOTP); credential.setType(type);
credential.setValue(totpSecret); credential.setValue(secret);
rep.getCredentials().add(credential); rep.getCredentials().add(credential);
rep.setTotp(true); rep.setTotp(true);
return this; 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() { public UserRepresentation build() {
return rep; return rep;
} }

View file

@ -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 <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
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();
}
}

View file

@ -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 <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
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();
}
}