parent
24d6f75d11
commit
2919342f3a
6 changed files with 102 additions and 44 deletions
|
@ -50,7 +50,10 @@ import static org.keycloak.testsuite.util.ServerURLs.getAuthServerContextRoot;
|
|||
* @author Stan Silvert
|
||||
*/
|
||||
public abstract class AbstractAppInitiatedActionTest extends AbstractTestRealmKeycloakTest {
|
||||
|
||||
|
||||
protected static final String SUCCESS = "success";
|
||||
protected static final String CANCELLED = "cancelled";
|
||||
|
||||
@Page
|
||||
protected LoginPage loginPage;
|
||||
|
||||
|
@ -59,16 +62,12 @@ public abstract class AbstractAppInitiatedActionTest extends AbstractTestRealmKe
|
|||
|
||||
@Rule
|
||||
public AssertEvents events = new AssertEvents(this);
|
||||
|
||||
protected final String aiaAction;
|
||||
|
||||
public AbstractAppInitiatedActionTest(String aiaAction) {
|
||||
this.aiaAction = aiaAction;
|
||||
}
|
||||
|
||||
protected abstract String getAiaAction();
|
||||
|
||||
protected void doAIA() {
|
||||
UriBuilder builder = OIDCLoginProtocolService.authUrl(authServerPage.createUriBuilder());
|
||||
String uri = builder.queryParam(KC_ACTION, this.aiaAction)
|
||||
String uri = builder.queryParam(KC_ACTION, getAiaAction())
|
||||
.queryParam(RESPONSE_TYPE, "code")
|
||||
.queryParam(CLIENT_ID, "test-app")
|
||||
.queryParam(SCOPE, "openid")
|
||||
|
|
|
@ -46,10 +46,11 @@ import static org.junit.Assert.assertTrue;
|
|||
*/
|
||||
public class AppInitiatedActionResetPasswordTest extends AbstractAppInitiatedActionTest {
|
||||
|
||||
public AppInitiatedActionResetPasswordTest() {
|
||||
super(UserModel.RequiredAction.UPDATE_PASSWORD.name());
|
||||
@Override
|
||||
protected String getAiaAction() {
|
||||
return UserModel.RequiredAction.UPDATE_PASSWORD.name();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void configureTestRealm(RealmRepresentation testRealm) {
|
||||
testRealm.setResetPasswordAllowed(Boolean.TRUE);
|
||||
|
@ -86,7 +87,7 @@ public class AppInitiatedActionResetPasswordTest extends AbstractAppInitiatedAct
|
|||
|
||||
events.expectRequiredAction(EventType.UPDATE_PASSWORD).assertEvent();
|
||||
|
||||
assertKcActionStatus("success");
|
||||
assertKcActionStatus(SUCCESS);
|
||||
|
||||
EventRepresentation loginEvent = events.expectLogin().assertEvent();
|
||||
|
||||
|
@ -121,7 +122,7 @@ public class AppInitiatedActionResetPasswordTest extends AbstractAppInitiatedAct
|
|||
changePasswordPage.changePassword("new-password", "new-password");
|
||||
|
||||
events.expectRequiredAction(EventType.UPDATE_PASSWORD).assertEvent();
|
||||
assertKcActionStatus("success");
|
||||
assertKcActionStatus(SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -133,7 +134,7 @@ public class AppInitiatedActionResetPasswordTest extends AbstractAppInitiatedAct
|
|||
changePasswordPage.assertCurrent();
|
||||
changePasswordPage.cancel();
|
||||
|
||||
assertKcActionStatus("cancelled");
|
||||
assertKcActionStatus(CANCELLED);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -157,7 +158,7 @@ public class AppInitiatedActionResetPasswordTest extends AbstractAppInitiatedAct
|
|||
|
||||
events.expectRequiredAction(EventType.UPDATE_PASSWORD).assertEvent();
|
||||
|
||||
assertKcActionStatus("success");
|
||||
assertKcActionStatus(SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -184,7 +185,7 @@ public class AppInitiatedActionResetPasswordTest extends AbstractAppInitiatedAct
|
|||
assertTrue("Logout sessions is checked by default", changePasswordPage.isLogoutSessionsChecked());
|
||||
changePasswordPage.changePassword("All Right Then, Keep Your Secrets", "All Right Then, Keep Your Secrets");
|
||||
events.expectRequiredAction(EventType.UPDATE_PASSWORD).assertEvent();
|
||||
assertKcActionStatus("success");
|
||||
assertKcActionStatus(SUCCESS);
|
||||
|
||||
sessions = testUser.getUserSessions();
|
||||
assertEquals(1, sessions.size());
|
||||
|
@ -212,7 +213,7 @@ public class AppInitiatedActionResetPasswordTest extends AbstractAppInitiatedAct
|
|||
changePasswordPage.uncheckLogoutSessions();
|
||||
changePasswordPage.changePassword("All Right Then, Keep Your Secrets", "All Right Then, Keep Your Secrets");
|
||||
events.expectRequiredAction(EventType.UPDATE_PASSWORD).assertEvent();
|
||||
assertKcActionStatus("success");
|
||||
assertKcActionStatus(SUCCESS);
|
||||
|
||||
assertEquals(2, testUser.getUserSessions().size());
|
||||
}
|
||||
|
|
|
@ -55,10 +55,11 @@ import static org.junit.Assert.assertTrue;
|
|||
*/
|
||||
public class AppInitiatedActionTotpSetupTest extends AbstractAppInitiatedActionTest {
|
||||
|
||||
public AppInitiatedActionTotpSetupTest() {
|
||||
super(UserModel.RequiredAction.CONFIGURE_TOTP.name());
|
||||
@Override
|
||||
public String getAiaAction() {
|
||||
return UserModel.RequiredAction.CONFIGURE_TOTP.name();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void configureTestRealm(RealmRepresentation testRealm) {
|
||||
testRealm.setResetPasswordAllowed(Boolean.TRUE);
|
||||
|
@ -117,7 +118,7 @@ public class AppInitiatedActionTotpSetupTest extends AbstractAppInitiatedActionT
|
|||
String authSessionId = events.expectRequiredAction(EventType.UPDATE_TOTP).user(userId).detail(Details.USERNAME, "setuptotp").assertEvent()
|
||||
.getDetails().get(Details.CODE_ID);
|
||||
|
||||
assertKcActionStatus("success");
|
||||
assertKcActionStatus(SUCCESS);
|
||||
|
||||
events.expectLogin().user(userId).session(authSessionId).detail(Details.USERNAME, "setuptotp").assertEvent();
|
||||
}
|
||||
|
@ -352,7 +353,7 @@ public class AppInitiatedActionTotpSetupTest extends AbstractAppInitiatedActionT
|
|||
String authSessionId = events.expectRequiredAction(EventType.UPDATE_TOTP).assertEvent()
|
||||
.getDetails().get(Details.CODE_ID);
|
||||
|
||||
assertKcActionStatus("success");
|
||||
assertKcActionStatus(SUCCESS);
|
||||
|
||||
EventRepresentation loginEvent = events.expectLogin().session(authSessionId).assertEvent();
|
||||
|
||||
|
@ -387,7 +388,7 @@ public class AppInitiatedActionTotpSetupTest extends AbstractAppInitiatedActionT
|
|||
totpPage.configure(totp.generateTOTP(totpCode));
|
||||
|
||||
// After totp config, user should be on the app page
|
||||
assertKcActionStatus("success");
|
||||
assertKcActionStatus(SUCCESS);
|
||||
|
||||
events.poll();
|
||||
events.expectRequiredAction(EventType.UPDATE_TOTP).user(userId).detail(Details.USERNAME, "setuptotp2").assertEvent();
|
||||
|
@ -459,7 +460,7 @@ public class AppInitiatedActionTotpSetupTest extends AbstractAppInitiatedActionT
|
|||
String sessionId = events.expectRequiredAction(EventType.UPDATE_TOTP).assertEvent()
|
||||
.getDetails().get(Details.CODE_ID);
|
||||
|
||||
assertKcActionStatus("success");
|
||||
assertKcActionStatus(SUCCESS);
|
||||
|
||||
EventRepresentation loginEvent = events.expectLogin().session(sessionId).assertEvent();
|
||||
|
||||
|
@ -512,7 +513,7 @@ public class AppInitiatedActionTotpSetupTest extends AbstractAppInitiatedActionT
|
|||
.getDetails().get(Details.CODE_ID);
|
||||
|
||||
//RequestType reqType = appPage.getRequestType();
|
||||
assertKcActionStatus("success");
|
||||
assertKcActionStatus(SUCCESS);
|
||||
EventRepresentation loginEvent = events.expectLogin().session(sessionId).assertEvent();
|
||||
|
||||
oauth.openLogout();
|
||||
|
|
|
@ -37,8 +37,9 @@ import org.keycloak.testsuite.util.UserBuilder;
|
|||
*/
|
||||
public class AppInitiatedActionUpdateProfileTest extends AbstractAppInitiatedActionTest {
|
||||
|
||||
public AppInitiatedActionUpdateProfileTest() {
|
||||
super(UserModel.RequiredAction.UPDATE_PROFILE.name());
|
||||
@Override
|
||||
public String getAiaAction() {
|
||||
return UserModel.RequiredAction.UPDATE_PROFILE.name();
|
||||
}
|
||||
|
||||
@Page
|
||||
|
@ -46,7 +47,7 @@ public class AppInitiatedActionUpdateProfileTest extends AbstractAppInitiatedAct
|
|||
|
||||
@Page
|
||||
protected ErrorPage errorPage;
|
||||
|
||||
|
||||
protected boolean isDynamicForm() {
|
||||
return false;
|
||||
}
|
||||
|
@ -92,7 +93,7 @@ public class AppInitiatedActionUpdateProfileTest extends AbstractAppInitiatedAct
|
|||
.assertEvent();
|
||||
events.expectLogin().assertEvent();
|
||||
|
||||
assertKcActionStatus("success");
|
||||
assertKcActionStatus(SUCCESS);
|
||||
|
||||
// assert user is really updated in persistent store
|
||||
UserRepresentation user = ActionUtil.findUserWithAdminClient(adminClient, "test-user@localhost");
|
||||
|
@ -123,7 +124,7 @@ public class AppInitiatedActionUpdateProfileTest extends AbstractAppInitiatedAct
|
|||
.assertEvent();
|
||||
events.expectLogin().assertEvent();
|
||||
|
||||
assertKcActionStatus("success");
|
||||
assertKcActionStatus(SUCCESS);
|
||||
|
||||
// assert user is really updated in persistent store
|
||||
UserRepresentation user = ActionUtil.findUserWithAdminClient(adminClient, "test-user@localhost");
|
||||
|
@ -142,7 +143,7 @@ public class AppInitiatedActionUpdateProfileTest extends AbstractAppInitiatedAct
|
|||
updateProfilePage.assertCurrent();
|
||||
updateProfilePage.cancel();
|
||||
|
||||
assertKcActionStatus("cancelled");
|
||||
assertKcActionStatus(CANCELLED);
|
||||
|
||||
|
||||
// assert nothing was updated in persistent store
|
||||
|
@ -177,7 +178,7 @@ public class AppInitiatedActionUpdateProfileTest extends AbstractAppInitiatedAct
|
|||
.removeDetail(Details.CONSENT)
|
||||
.assertEvent();
|
||||
|
||||
assertKcActionStatus("success");
|
||||
assertKcActionStatus(SUCCESS);
|
||||
|
||||
events.expectLogin().detail(Details.USERNAME, "john-doh@localhost").user(userId).assertEvent();
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright 2021 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.webauthn;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mabartos@redhat.com">Martin Bartos</a>
|
||||
*/
|
||||
public class AppInitiatedActionPwdLessTest extends AppInitiatedActionWebAuthnTest {
|
||||
|
||||
protected boolean isPasswordless() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -20,14 +20,18 @@ import org.jboss.arquillian.graphene.page.Page;
|
|||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.UserResource;
|
||||
import org.keycloak.authentication.authenticators.browser.PasswordFormFactory;
|
||||
import org.keycloak.authentication.authenticators.browser.UsernameFormFactory;
|
||||
import org.keycloak.authentication.authenticators.browser.WebAuthnAuthenticatorFactory;
|
||||
import org.keycloak.authentication.authenticators.browser.WebAuthnPasswordlessAuthenticatorFactory;
|
||||
import org.keycloak.authentication.requiredactions.WebAuthnPasswordlessRegisterFactory;
|
||||
import org.keycloak.authentication.requiredactions.WebAuthnRegisterFactory;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.RequiredActionProviderRepresentation;
|
||||
import org.keycloak.testsuite.actions.AbstractAppInitiatedActionTest;
|
||||
import org.keycloak.testsuite.admin.ApiUtil;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude;
|
||||
import org.keycloak.testsuite.arquillian.annotation.EnableFeature;
|
||||
import org.keycloak.testsuite.pages.LoginUsernameOnlyPage;
|
||||
|
@ -40,7 +44,11 @@ import org.keycloak.testsuite.webauthn.pages.WebAuthnRegisterPage;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.keycloak.common.Profile.Feature.WEB_AUTHN;
|
||||
import static org.keycloak.models.AuthenticationExecutionModel.Requirement.ALTERNATIVE;
|
||||
import static org.keycloak.models.AuthenticationExecutionModel.Requirement.REQUIRED;
|
||||
|
@ -56,6 +64,10 @@ public class AppInitiatedActionWebAuthnTest extends AbstractAppInitiatedActionTe
|
|||
|
||||
private VirtualAuthenticatorManager virtualManager;
|
||||
|
||||
protected final String WEB_AUTHN_REGISTER_PROVIDER = isPasswordless() ? WebAuthnPasswordlessRegisterFactory.PROVIDER_ID : WebAuthnRegisterFactory.PROVIDER_ID;
|
||||
protected final String DEFAULT_USERNAME = "test-user@localhost";
|
||||
protected final String DEFAULT_PASSWORD = "password";
|
||||
|
||||
@Page
|
||||
LoginUsernameOnlyPage usernamePage;
|
||||
|
||||
|
@ -77,8 +89,9 @@ public class AppInitiatedActionWebAuthnTest extends AbstractAppInitiatedActionTe
|
|||
virtualManager.removeAuthenticator();
|
||||
}
|
||||
|
||||
public AppInitiatedActionWebAuthnTest() {
|
||||
super(WebAuthnRegisterFactory.PROVIDER_ID);
|
||||
@Override
|
||||
public String getAiaAction() {
|
||||
return WEB_AUTHN_REGISTER_PROVIDER;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -86,11 +99,15 @@ public class AppInitiatedActionWebAuthnTest extends AbstractAppInitiatedActionTe
|
|||
return true;
|
||||
}
|
||||
|
||||
protected boolean isPasswordless() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureTestRealm(RealmRepresentation testRealm) {
|
||||
RequiredActionProviderRepresentation action = new RequiredActionProviderRepresentation();
|
||||
action.setAlias(WebAuthnRegisterFactory.PROVIDER_ID);
|
||||
action.setProviderId(WebAuthnRegisterFactory.PROVIDER_ID);
|
||||
action.setAlias(WEB_AUTHN_REGISTER_PROVIDER);
|
||||
action.setProviderId(WEB_AUTHN_REGISTER_PROVIDER);
|
||||
action.setEnabled(true);
|
||||
action.setDefaultAction(true);
|
||||
action.setPriority(10);
|
||||
|
@ -103,8 +120,10 @@ public class AppInitiatedActionWebAuthnTest extends AbstractAppInitiatedActionTe
|
|||
@Before
|
||||
public void setUpWebAuthnFlow() {
|
||||
final String newFlowAlias = "browserWebAuthnAIA";
|
||||
testingClient.server("test").run(session -> FlowUtil.inCurrentRealm(session).copyBrowserFlow(newFlowAlias));
|
||||
testingClient.server("test").run(session -> {
|
||||
final String webAuthnAuthProvider = isPasswordless() ? WebAuthnPasswordlessAuthenticatorFactory.PROVIDER_ID : WebAuthnAuthenticatorFactory.PROVIDER_ID;
|
||||
|
||||
testingClient.server(TEST_REALM_NAME).run(session -> FlowUtil.inCurrentRealm(session).copyBrowserFlow(newFlowAlias));
|
||||
testingClient.server(TEST_REALM_NAME).run(session -> {
|
||||
FlowUtil.inCurrentRealm(session)
|
||||
.selectFlow(newFlowAlias)
|
||||
.inForms(forms -> forms
|
||||
|
@ -112,7 +131,7 @@ public class AppInitiatedActionWebAuthnTest extends AbstractAppInitiatedActionTe
|
|||
.addAuthenticatorExecution(REQUIRED, UsernameFormFactory.PROVIDER_ID)
|
||||
.addSubFlowExecution(REQUIRED, subFlow -> subFlow
|
||||
.addAuthenticatorExecution(ALTERNATIVE, PasswordFormFactory.PROVIDER_ID)
|
||||
.addAuthenticatorExecution(ALTERNATIVE, WebAuthnAuthenticatorFactory.PROVIDER_ID)))
|
||||
.addAuthenticatorExecution(ALTERNATIVE, webAuthnAuthProvider)))
|
||||
.defineAsBrowserFlow();
|
||||
});
|
||||
}
|
||||
|
@ -128,7 +147,7 @@ public class AppInitiatedActionWebAuthnTest extends AbstractAppInitiatedActionTe
|
|||
|
||||
waitForPageToLoad();
|
||||
|
||||
assertKcActionStatus("cancelled");
|
||||
assertKcActionStatus(CANCELLED);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -137,25 +156,34 @@ public class AppInitiatedActionWebAuthnTest extends AbstractAppInitiatedActionTe
|
|||
|
||||
doAIA();
|
||||
|
||||
final Supplier<Integer> getCredentialCount = () -> Optional.ofNullable(ApiUtil.findUserByUsernameId(testRealm(), DEFAULT_USERNAME))
|
||||
.map(UserResource::credentials)
|
||||
.map(List::size)
|
||||
.orElse(0);
|
||||
|
||||
final int credentialsCount = getCredentialCount.get();
|
||||
|
||||
webAuthnRegisterPage.assertCurrent();
|
||||
webAuthnRegisterPage.clickRegister();
|
||||
webAuthnRegisterPage.registerWebAuthnCredential("authenticator1");
|
||||
|
||||
waitForPageToLoad();
|
||||
|
||||
assertKcActionStatus("success");
|
||||
assertKcActionStatus(SUCCESS);
|
||||
|
||||
assertThat(getCredentialCount.get(), is(credentialsCount + 1));
|
||||
}
|
||||
|
||||
private void loginUser() {
|
||||
usernamePage.open();
|
||||
usernamePage.assertCurrent();
|
||||
usernamePage.login("test-user@localhost");
|
||||
usernamePage.login(DEFAULT_USERNAME);
|
||||
|
||||
passwordPage.assertCurrent();
|
||||
passwordPage.login("password");
|
||||
passwordPage.login(DEFAULT_PASSWORD);
|
||||
|
||||
events.expectLogin()
|
||||
.detail(Details.USERNAME, "test-user@localhost")
|
||||
.detail(Details.USERNAME, DEFAULT_USERNAME)
|
||||
.assertEvent();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue