diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f88b6ab4eb..a8f602ba06 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -502,6 +502,43 @@ jobs:
with:
job-name: Account Console IT
+ webauthn-integration-tests:
+ name: WebAuthn IT
+ runs-on: ubuntu-latest
+ needs: build
+ timeout-minutes: 30
+ strategy:
+ matrix:
+ browser: [firefox] # Chrome not working for now
+ fail-fast: false
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Setup firefox
+ uses: browser-actions/setup-firefox@latest
+ with:
+ firefox-version: latest
+ - run: firefox --version
+
+ - id: integration-test-setup
+ name: Integration test setup
+ uses: ./.github/actions/integration-test-setup
+
+ - name: Run WebAuthn IT
+ run: ./mvnw test -Dsurefire.rerunFailingTestsCount=${{ env.SUREFIRE_RERUN_FAILING_COUNT }} -nsu -B -Pauth-server-quarkus -Dtest=org.keycloak.testsuite.webauthn.**.*Test -Dbrowser=${{ matrix.browser }} -Pwebauthn -f testsuite/integration-arquillian/tests/other/pom.xml | misc/log/trimmer.sh
+
+ - name: Upload JVM Heapdumps
+ if: always()
+ uses: ./.github/actions/upload-heapdumps
+
+ - uses: ./.github/actions/upload-flaky-tests
+ name: Upload flaky tests
+ env:
+ GH_TOKEN: ${{ github.token }}
+ with:
+ job-name: WebAuthn IT
+
+
check-set-status:
name: Set check conclusion
needs:
@@ -516,6 +553,7 @@ jobs:
- fips-unit-tests
- fips-integration-tests
- account-console-integration-tests
+ - webauthn-integration-tests
runs-on: ubuntu-latest
outputs:
conclusion: ${{ steps.check.outputs.conclusion }}
diff --git a/testsuite/integration-arquillian/tests/other/webauthn/src/main/java/org/keycloak/testsuite/webauthn/pages/WebAuthnPolicyPage.java b/testsuite/integration-arquillian/tests/other/webauthn/src/main/java/org/keycloak/testsuite/webauthn/pages/WebAuthnPolicyPage.java
index a43ac49d76..a4832be2fe 100644
--- a/testsuite/integration-arquillian/tests/other/webauthn/src/main/java/org/keycloak/testsuite/webauthn/pages/WebAuthnPolicyPage.java
+++ b/testsuite/integration-arquillian/tests/other/webauthn/src/main/java/org/keycloak/testsuite/webauthn/pages/WebAuthnPolicyPage.java
@@ -21,9 +21,7 @@ import com.webauthn4j.data.AttestationConveyancePreference;
import com.webauthn4j.data.AuthenticatorAttachment;
import com.webauthn4j.data.UserVerificationRequirement;
import org.jboss.arquillian.graphene.page.Page;
-import org.keycloak.testsuite.console.page.authentication.Authentication;
import org.keycloak.testsuite.console.page.fragment.OnOffSwitch;
-import org.keycloak.testsuite.console.page.idp.mappers.MultivaluedStringProperty;
import org.keycloak.testsuite.webauthn.utils.PropertyRequirement;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebElement;
@@ -44,7 +42,7 @@ import static org.keycloak.utils.StringUtil.isNotBlank;
*
* @author Martin Bartos
*/
-public class WebAuthnPolicyPage extends Authentication {
+public class WebAuthnPolicyPage {
@FindBy(id = "name")
private WebElement rpEntityName;
@@ -73,24 +71,12 @@ public class WebAuthnPolicyPage extends Authentication {
@FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='avoidsame']]")
private OnOffSwitch avoidSameAuthenticatorRegister;
- @Page
- private MultivaluedAcceptableAaguid acceptableAaguid;
-
@FindBy(xpath = "//button[text()='Save']")
private WebElement saveButton;
@FindBy(xpath = "//button[text()='Cancel']")
private WebElement cancelButton;
- @Override
- public String getUriFragment() {
- return getAuthenticationUriFragment() + "/webauthn-policy";
- }
-
- public String getAuthenticationUriFragment() {
- return super.getUriFragment();
- }
-
/* Relaying Party Entity Name */
public String getRpEntityName() {
@@ -212,10 +198,6 @@ public class WebAuthnPolicyPage extends Authentication {
}
}
- public MultivaluedAcceptableAaguid getAcceptableAaguid() {
- return acceptableAaguid;
- }
-
/* Buttons */
public void clickSaveButton() {
waitUntilElement(checkElement(() -> saveButton)).is().clickable();
@@ -256,40 +238,4 @@ public class WebAuthnPolicyPage extends Authentication {
return null;
}
}
-
- public class MultivaluedAcceptableAaguid extends MultivaluedStringProperty {
-
- @FindBy(className = "webauthn-acceptable-aaguid")
- private List aaguids;
-
- @FindBy(id = "newAcceptableAaguid")
- private WebElement newAaguid;
-
- @FindBy(xpath = "//button[@data-ng-click='deleteAcceptableAaguid($index)']")
- private List minusButtons;
-
- @FindBy(xpath = "//button[@data-ng-click='newAcceptableAaguid.length > 0 && addAcceptableAaguid()']")
- private WebElement plusButton;
-
- @Override
- public List getItems() {
- return checkElement(() -> aaguids);
- }
-
- @Override
- public void addItem(String item) {
- setTextInputValue(checkElement(() -> newAaguid), item);
- clickAddItem();
- }
-
- @Override
- protected List getMinusButtons() {
- return minusButtons;
- }
-
- @Override
- protected WebElement getPlusButton() {
- return plusButton;
- }
- }
}
diff --git a/testsuite/integration-arquillian/tests/other/webauthn/src/main/java/org/keycloak/testsuite/webauthn/pages/WebAuthnPolicyPasswordlessPage.java b/testsuite/integration-arquillian/tests/other/webauthn/src/main/java/org/keycloak/testsuite/webauthn/pages/WebAuthnPolicyPasswordlessPage.java
deleted file mode 100644
index 2cc54f487f..0000000000
--- a/testsuite/integration-arquillian/tests/other/webauthn/src/main/java/org/keycloak/testsuite/webauthn/pages/WebAuthnPolicyPasswordlessPage.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.pages;
-
-/**
- * Helper class for WebAuthnPolicy Passwordless Page
- *
- * @author Martin Bartos
- */
-public class WebAuthnPolicyPasswordlessPage extends WebAuthnPolicyPage {
-
- @Override
- public String getUriFragment() {
- return super.getAuthenticationUriFragment() + "/webauthn-policy-passwordless";
- }
-}
diff --git a/testsuite/integration-arquillian/tests/other/webauthn/src/test/java/org/keycloak/testsuite/webauthn/admin/PwdLessPolicySettingsTest.java b/testsuite/integration-arquillian/tests/other/webauthn/src/test/java/org/keycloak/testsuite/webauthn/admin/PwdLessPolicySettingsTest.java
deleted file mode 100644
index b3dc2a5340..0000000000
--- a/testsuite/integration-arquillian/tests/other/webauthn/src/test/java/org/keycloak/testsuite/webauthn/admin/PwdLessPolicySettingsTest.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2022 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.admin;
-
-/**
- * @author Martin Bartos
- */
-public class PwdLessPolicySettingsTest extends WebAuthnPolicySettingsTest {
-
- @Override
- protected boolean isPasswordless() {
- return true;
- }
-}
diff --git a/testsuite/integration-arquillian/tests/other/webauthn/src/test/java/org/keycloak/testsuite/webauthn/admin/WebAuthnPolicySettingsTest.java b/testsuite/integration-arquillian/tests/other/webauthn/src/test/java/org/keycloak/testsuite/webauthn/admin/WebAuthnPolicySettingsTest.java
deleted file mode 100644
index 70616f13cb..0000000000
--- a/testsuite/integration-arquillian/tests/other/webauthn/src/test/java/org/keycloak/testsuite/webauthn/admin/WebAuthnPolicySettingsTest.java
+++ /dev/null
@@ -1,569 +0,0 @@
-/*
- * 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.admin;
-
-import com.webauthn4j.data.AttestationConveyancePreference;
-import com.webauthn4j.data.AuthenticatorAttachment;
-import com.webauthn4j.data.UserVerificationRequirement;
-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.Constants;
-import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.testsuite.AssertEvents;
-import org.keycloak.testsuite.console.AbstractConsoleTest;
-import org.keycloak.testsuite.page.AbstractPatternFlyAlert;
-import org.keycloak.testsuite.updaters.RealmAttributeUpdater;
-import org.keycloak.testsuite.util.UIUtils;
-import org.keycloak.testsuite.webauthn.pages.WebAuthnPolicyPage;
-import org.keycloak.testsuite.webauthn.pages.WebAuthnPolicyPasswordlessPage;
-import org.keycloak.testsuite.webauthn.updaters.AbstractWebAuthnRealmUpdater;
-import org.keycloak.testsuite.webauthn.updaters.PasswordLessRealmAttributeUpdater;
-import org.keycloak.testsuite.webauthn.updaters.WebAuthnRealmAttributeUpdater;
-import org.keycloak.testsuite.webauthn.utils.PropertyRequirement;
-import org.keycloak.testsuite.webauthn.utils.WebAuthnRealmData;
-import org.openqa.selenium.NoSuchElementException;
-import org.openqa.selenium.WebElement;
-import org.openqa.selenium.support.ui.Select;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-import static com.webauthn4j.data.AttestationConveyancePreference.INDIRECT;
-import static com.webauthn4j.data.AuthenticatorAttachment.CROSS_PLATFORM;
-import static com.webauthn4j.data.UserVerificationRequirement.PREFERRED;
-import static org.hamcrest.CoreMatchers.containsString;
-import static org.hamcrest.CoreMatchers.hasItems;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.contains;
-import static org.hamcrest.Matchers.hasSize;
-import static org.keycloak.models.Constants.DEFAULT_WEBAUTHN_POLICY_NOT_SPECIFIED;
-import static org.keycloak.testsuite.util.WaitUtils.pause;
-import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad;
-import static org.keycloak.testsuite.webauthn.utils.PropertyRequirement.NO;
-import static org.keycloak.testsuite.webauthn.utils.PropertyRequirement.YES;
-
-/**
- * @author Martin Bartos
- */
-public class WebAuthnPolicySettingsTest extends AbstractConsoleTest {
-
- protected static final String ALL_ZERO_AAGUID = "00000000-0000-0000-0000-000000000000";
- protected static final String ALL_ONE_AAGUID = "11111111-1111-1111-1111-111111111111";
-
- @Rule
- public AssertEvents events = new AssertEvents(this);
-
- @Page
- WebAuthnPolicyPage webAuthnPolicyPage;
-
- @Page
- WebAuthnPolicyPasswordlessPage webAuthnPolicyPasswordlessPage;
-
- @Before
- public void navigateToPolicy() {
- driver.manage().window().maximize();
- getPolicyPage().navigateTo();
- waitForPageToLoad();
- getPolicyPage().assertCurrent();
- }
-
- protected boolean isPasswordless() {
- return false;
- }
-
- protected WebAuthnPolicyPage getPolicyPage() {
- return isPasswordless() ? webAuthnPolicyPasswordlessPage : webAuthnPolicyPage;
- }
-
- protected AbstractWebAuthnRealmUpdater> getWebAuthnRealmUpdater() {
- return isPasswordless() ? new PasswordLessRealmAttributeUpdater(testRealmResource()) : new WebAuthnRealmAttributeUpdater(testRealmResource());
- }
-
- protected AbstractWebAuthnRealmUpdater> updateWebAuthnPolicy(
- String rpName,
- List algorithms,
- String attestationPreference,
- String authenticatorAttachment,
- String requireResidentKey,
- String rpId,
- String userVerification,
- List acceptableAaguids) {
-
- AbstractWebAuthnRealmUpdater> updater = getWebAuthnRealmUpdater().setWebAuthnPolicyRpEntityName(rpName);
-
- checkAndSet(algorithms, updater::setWebAuthnPolicySignatureAlgorithms);
- checkAndSet(attestationPreference, updater::setWebAuthnPolicyAttestationConveyancePreference);
- checkAndSet(authenticatorAttachment, updater::setWebAuthnPolicyAuthenticatorAttachment);
- checkAndSet(requireResidentKey, updater::setWebAuthnPolicyRequireResidentKey);
- checkAndSet(rpId, updater::setWebAuthnPolicyRpId);
- checkAndSet(userVerification, updater::setWebAuthnPolicyUserVerificationRequirement);
- checkAndSet(acceptableAaguids, updater::setWebAuthnPolicyAcceptableAaguids);
-
- return updater.update();
- }
-
- private void checkAndSet(T value, Consumer consumer) {
- if (value != null) {
- consumer.accept(value);
- }
- }
-
- @Test
- public void policySettingsWithExternalProperties() throws IOException {
- try (RealmAttributeUpdater rau = updateWebAuthnPolicy(
- "rpName",
- Collections.singletonList("ES256"),
- INDIRECT.getValue(),
- CROSS_PLATFORM.getValue(),
- "No",
- null,
- PREFERRED.getValue(),
- Collections.singletonList(ALL_ZERO_AAGUID))
- ) {
-
- WebAuthnRealmData realm = new WebAuthnRealmData(testRealmResource().toRepresentation(), isPasswordless());
- assertThat(realm, notNullValue());
-
- assertThat(realm.getSignatureAlgorithms(), hasItems("ES256"));
- assertThat(realm.getAttestationConveyancePreference(), is(INDIRECT.getValue()));
- assertThat(realm.getAuthenticatorAttachment(), is(CROSS_PLATFORM.getValue()));
- assertThat(realm.getRequireResidentKey(), is("No"));
- assertThat(realm.getRpId(), is(""));
- assertThat(realm.getUserVerificationRequirement(), is(PREFERRED.getValue()));
- assertThat(realm.getAcceptableAaguids(), hasItems(ALL_ZERO_AAGUID));
- }
- }
-
- @Test
- public void rpEntityValues() {
- String rpEntityName = getPolicyPage().getRpEntityName();
- assertThat(rpEntityName, notNullValue());
- assertThat(rpEntityName, is(Constants.DEFAULT_WEBAUTHN_POLICY_RP_ENTITY_NAME));
-
- getPolicyPage().setRpEntityName("newEntityName");
- getPolicyPage().clickSaveButton();
- AbstractPatternFlyAlert.waitUntilHidden();
-
- rpEntityName = getPolicyPage().getRpEntityName();
- assertThat(rpEntityName, notNullValue());
- assertThat(rpEntityName, is("newEntityName"));
-
- getPolicyPage().setRpEntityName("");
- getPolicyPage().clickSaveButton();
- AbstractPatternFlyAlert.waitUntilHidden();
-
- rpEntityName = getPolicyPage().getRpEntityName();
- assertThat(rpEntityName, notNullValue());
- assertThat(rpEntityName, is(Constants.DEFAULT_WEBAUTHN_POLICY_RP_ENTITY_NAME));
-
- String rpEntityId = getPolicyPage().getRpEntityId();
- assertThat(rpEntityId, notNullValue());
- assertThat(rpEntityId, is(""));
-
- getPolicyPage().setRpEntityId("rpId123");
- getPolicyPage().clickSaveButton();
- AbstractPatternFlyAlert.waitUntilHidden();
-
- rpEntityId = getPolicyPage().getRpEntityId();
- assertThat(rpEntityId, notNullValue());
- assertThat(rpEntityId, is("rpId123"));
-
- final WebAuthnRealmData realm = new WebAuthnRealmData(testRealmResource().toRepresentation(), isPasswordless());
- assertThat(realm, notNullValue());
-
- assertThat(realm.getRpEntityName(), is(Constants.DEFAULT_WEBAUTHN_POLICY_RP_ENTITY_NAME));
- assertThat(realm.getRpId(), is("rpId123"));
- }
-
- @Test
- public void wrongSignatureAlgorithm() throws IOException {
- try (Closeable c = getWebAuthnRealmUpdater()
- .setWebAuthnPolicySignatureAlgorithms(Collections.singletonList("something-bad"))
- .update()) {
-
- RealmRepresentation realm = testRealmResource().toRepresentation();
- assertThat(realm, notNullValue());
-
- final List signatureAlgorithms = realm.getWebAuthnPolicySignatureAlgorithms();
- assertThat(signatureAlgorithms, notNullValue());
- assertThat(signatureAlgorithms.size(), is(1));
-
- getPolicyPage().navigateTo();
- waitForPageToLoad();
-
- Select selectedAlg = getPolicyPage().getSignatureAlgorithms();
- assertThat(selectedAlg, notNullValue());
-
- try {
- // should throw an exception
- selectedAlg.getFirstSelectedOption();
- } catch (NoSuchElementException e) {
- assertThat(e.getMessage(), containsString("No options are selected"));
- }
- }
- }
-
- @Test
- public void signatureAlgorithms() {
- getPolicyPage().assertCurrent();
-
- final Select algorithms = getPolicyPage().getSignatureAlgorithms();
- assertThat(algorithms, notNullValue());
-
- algorithms.selectByValue("ES256");
- algorithms.selectByValue("ES384");
- algorithms.selectByValue("RS1");
-
- final List selectedAlgs = algorithms.getAllSelectedOptions()
- .stream()
- .map(WebElement::getText)
- .collect(Collectors.toList());
-
- assertThat(selectedAlgs, notNullValue());
- assertThat(selectedAlgs, hasSize(3));
-
- try {
- algorithms.selectByValue("something-bad");
- } catch (NoSuchElementException e) {
- assertThat(e.getMessage(), containsString("Cannot locate option with value: something-bad"));
- }
-
- assertThat(getPolicyPage().isSaveButtonEnabled(), is(true));
- assertThat(getPolicyPage().isCancelButtonEnabled(), is(true));
-
- getPolicyPage().clickSaveButton();
-
- assertThat(getPolicyPage().isSaveButtonEnabled(), is(false));
- assertThat(getPolicyPage().isCancelButtonEnabled(), is(false));
-
- final WebAuthnRealmData realm = new WebAuthnRealmData(testRealmResource().toRepresentation(), isPasswordless());
- assertThat(realm, notNullValue());
-
- final List realmSignatureAlgs = realm.getSignatureAlgorithms();
- assertThat(realmSignatureAlgs, notNullValue());
- assertThat(realmSignatureAlgs, hasSize(3));
- assertThat(realmSignatureAlgs, contains("ES256", "ES384", "RS1"));
- }
-
- @Test
- public void attestationConveyancePreference() {
- // default not specified
- AttestationConveyancePreference attestation = getPolicyPage().getAttestationConveyancePreference();
- assertThat(attestation, nullValue());
-
- // Direct
- getPolicyPage().setAttestationConveyancePreference(AttestationConveyancePreference.DIRECT);
- getPolicyPage().clickSaveButton();
-
- attestation = getPolicyPage().getAttestationConveyancePreference();
- assertThat(attestation, notNullValue());
- assertThat(attestation, is(AttestationConveyancePreference.DIRECT));
-
- // Indirect
- getPolicyPage().setAttestationConveyancePreference(AttestationConveyancePreference.INDIRECT);
- getPolicyPage().clickSaveButton();
-
- attestation = getPolicyPage().getAttestationConveyancePreference();
- assertThat(attestation, notNullValue());
- assertThat(attestation, is(AttestationConveyancePreference.INDIRECT));
-
- // None
- getPolicyPage().setAttestationConveyancePreference(AttestationConveyancePreference.NONE);
- getPolicyPage().clickSaveButton();
-
- attestation = getPolicyPage().getAttestationConveyancePreference();
- assertThat(attestation, notNullValue());
- assertThat(attestation, is(AttestationConveyancePreference.NONE));
-
- try {
- getPolicyPage().setAttestationConveyancePreference(AttestationConveyancePreference.ENTERPRISE);
- Assert.fail("We don't support 'Enterprise' mode at this moment");
- } catch (NoSuchElementException e) {
- // Expected - NOP
- }
-
- assertDataAfterModification(AttestationConveyancePreference.NONE.getValue(),
- DEFAULT_WEBAUTHN_POLICY_NOT_SPECIFIED,
- WebAuthnRealmData::getAttestationConveyancePreference,
- (builder) -> builder.attestationConveyancePreference(null)
- );
- }
-
- @Test
- public void authenticatorAttachment() {
- AuthenticatorAttachment attachment = getPolicyPage().getAuthenticatorAttachment();
- assertThat(attachment, nullValue());
-
- // Cross-platform
- getPolicyPage().setAuthenticatorAttachment(AuthenticatorAttachment.CROSS_PLATFORM);
- getPolicyPage().clickSaveButton();
-
- attachment = getPolicyPage().getAuthenticatorAttachment();
- assertThat(attachment, notNullValue());
- assertThat(attachment, is(AuthenticatorAttachment.CROSS_PLATFORM));
-
- // Platform
- getPolicyPage().setAuthenticatorAttachment(AuthenticatorAttachment.PLATFORM);
- getPolicyPage().clickSaveButton();
-
- attachment = getPolicyPage().getAuthenticatorAttachment();
- assertThat(attachment, notNullValue());
- assertThat(attachment, is(AuthenticatorAttachment.PLATFORM));
-
- assertDataAfterModification(AuthenticatorAttachment.PLATFORM.getValue(),
- DEFAULT_WEBAUTHN_POLICY_NOT_SPECIFIED,
- WebAuthnRealmData::getAuthenticatorAttachment,
- (builder) -> builder.authenticatorAttachment(null)
- );
- }
-
- @Test
- public void residentKey() {
- PropertyRequirement requireResidentKey = getPolicyPage().requireResidentKey();
- assertThat(requireResidentKey, notNullValue());
- assertThat(requireResidentKey, is(PropertyRequirement.NOT_SPECIFIED));
-
- getPolicyPage().requireResidentKey(YES);
- getPolicyPage().clickSaveButton();
-
- // Yes
- requireResidentKey = getPolicyPage().requireResidentKey();
- assertThat(requireResidentKey, notNullValue());
- assertThat(requireResidentKey, is(YES));
-
- getPolicyPage().requireResidentKey(NO);
- getPolicyPage().clickSaveButton();
-
- // Null
- getPolicyPage().requireResidentKey(null);
- assertThat(getPolicyPage().isSaveButtonEnabled(), is(false));
-
- // Not specified
- getPolicyPage().requireResidentKey(PropertyRequirement.NOT_SPECIFIED);
- assertThat(getPolicyPage().isSaveButtonEnabled(), is(true));
- getPolicyPage().clickSaveButton();
-
- // No
- getPolicyPage().requireResidentKey(NO);
- getPolicyPage().clickSaveButton();
-
- requireResidentKey = getPolicyPage().requireResidentKey();
- assertThat(requireResidentKey, notNullValue());
- assertThat(requireResidentKey, is(NO));
-
- assertDataAfterModification(NO.getValue(),
- DEFAULT_WEBAUTHN_POLICY_NOT_SPECIFIED,
- WebAuthnRealmData::getRequireResidentKey,
- (builder) -> builder.requireResidentKey(null)
- );
- }
-
- @Test
- public void userVerification() {
- UserVerificationRequirement userVerification = getPolicyPage().getUserVerification();
- assertThat(userVerification, nullValue());
-
- // Preferred
- getPolicyPage().setUserVerification(UserVerificationRequirement.PREFERRED);
- getPolicyPage().clickSaveButton();
-
- userVerification = getPolicyPage().getUserVerification();
- assertThat(userVerification, notNullValue());
- assertThat(userVerification, is(UserVerificationRequirement.PREFERRED));
-
- // Required
- getPolicyPage().setUserVerification(UserVerificationRequirement.REQUIRED);
- getPolicyPage().clickSaveButton();
-
- userVerification = getPolicyPage().getUserVerification();
- assertThat(userVerification, notNullValue());
- assertThat(userVerification, is(UserVerificationRequirement.REQUIRED));
-
- // Discouraged
- getPolicyPage().setUserVerification(UserVerificationRequirement.DISCOURAGED);
- getPolicyPage().clickSaveButton();
-
- userVerification = getPolicyPage().getUserVerification();
- assertThat(userVerification, notNullValue());
- assertThat(userVerification, is(UserVerificationRequirement.DISCOURAGED));
-
- assertDataAfterModification(UserVerificationRequirement.DISCOURAGED.getValue(),
- DEFAULT_WEBAUTHN_POLICY_NOT_SPECIFIED,
- WebAuthnRealmData::getUserVerificationRequirement,
- (builder) -> builder.userVerificationRequirement(null)
- );
- }
-
- @Test
- public void timeout() {
- int timeout = getPolicyPage().getTimeout();
- assertThat(timeout, is(0));
-
- getPolicyPage().setTimeout(10);
- getPolicyPage().clickSaveButton();
-
- timeout = getPolicyPage().getTimeout();
- assertThat(timeout, is(10));
-
- getPolicyPage().setTimeout(-10);
- getPolicyPage().clickSaveButton();
- assertAlertDanger();
-
- timeout = getPolicyPage().getTimeout();
- assertThat(timeout, is(-10));
-
- getPolicyPage().navigateTo();
- waitForPageToLoad();
-
- timeout = getPolicyPage().getTimeout();
- assertThat(timeout, is(10));
-
- getPolicyPage().setTimeout(1000000);
- getPolicyPage().clickSaveButton();
- assertAlertDanger();
-
- getPolicyPage().setTimeout(500);
- getPolicyPage().clickSaveButton();
-
- timeout = getPolicyPage().getTimeout();
- assertThat(timeout, is(500));
-
- final WebAuthnRealmData realm = new WebAuthnRealmData(testRealmResource().toRepresentation(), isPasswordless());
- assertThat(realm, notNullValue());
- assertThat(realm.getCreateTimeout(), is(500));
- }
-
- @Test
- public void avoidSameAuthenticatorRegistration() {
- boolean avoidSameAuthenticatorRegistration = getPolicyPage().avoidSameAuthenticatorRegistration();
- assertThat(avoidSameAuthenticatorRegistration, is(false));
-
- getPolicyPage().avoidSameAuthenticatorRegister(true);
- assertThat(getPolicyPage().isSaveButtonEnabled(), is(true));
- getPolicyPage().clickSaveButton();
-
- avoidSameAuthenticatorRegistration = getPolicyPage().avoidSameAuthenticatorRegistration();
- assertThat(avoidSameAuthenticatorRegistration, is(true));
-
- getPolicyPage().avoidSameAuthenticatorRegister(false);
- getPolicyPage().clickSaveButton();
-
- avoidSameAuthenticatorRegistration = getPolicyPage().avoidSameAuthenticatorRegistration();
- assertThat(avoidSameAuthenticatorRegistration, is(false));
-
- final WebAuthnRealmData realm = new WebAuthnRealmData(testRealmResource().toRepresentation(), isPasswordless());
- assertThat(realm, notNullValue());
- assertThat(realm.isAvoidSameAuthenticatorRegister(), is(false));
- }
-
- @Test
- public void acceptableAaguid() {
- WebAuthnPolicyPage.MultivaluedAcceptableAaguid acceptableAaguid = getPolicyPage().getAcceptableAaguid();
- assertThat(acceptableAaguid, notNullValue());
-
- List items = getAcceptableAaguid(getPolicyPage().getAcceptableAaguid());
- assertThat(items, notNullValue());
-
- acceptableAaguid.addItem(ALL_ONE_AAGUID);
- getPolicyPage().clickSaveButton();
-
- items = getAcceptableAaguid(getPolicyPage().getAcceptableAaguid());
-
- assertThat(items, notNullValue());
- assertThat(items.isEmpty(), is(false));
- assertThat(items.contains(ALL_ONE_AAGUID), is(true));
-
- final String YUBIKEY_5_AAGUID = "cb69481e-8ff7-4039-93ec-0a2729a154a8";
- final String YUBICO_AAGUID = "f8a011f3-8c0a-4d15-8006-17111f9edc7d";
-
- acceptableAaguid.addItem(YUBIKEY_5_AAGUID);
- acceptableAaguid.addItem(YUBICO_AAGUID);
- items = getAcceptableAaguid(getPolicyPage().getAcceptableAaguid());
-
- assertThat(items, notNullValue());
- assertThat(items, hasSize(3));
-
- getPolicyPage().clickSaveButton();
- acceptableAaguid.removeItem(0);
- items = getAcceptableAaguid(getPolicyPage().getAcceptableAaguid());
-
- assertThat(items, notNullValue());
- assertThat(items, hasSize(2));
- assertThat(items.contains(YUBICO_AAGUID), is(true));
- assertThat(items.contains(YUBIKEY_5_AAGUID), is(true));
- assertThat(items.contains(ALL_ONE_AAGUID), is(false));
-
- assertThat(getPolicyPage().isSaveButtonEnabled(), is(true));
- getPolicyPage().clickSaveButton();
- pause(100);
-
- WebAuthnRealmData realm = new WebAuthnRealmData(testRealmResource().toRepresentation(), isPasswordless());
- assertThat(realm, notNullValue());
- assertThat(realm.getAcceptableAaguids(), is(getAcceptableAaguid(getPolicyPage().getAcceptableAaguid())));
- }
-
- protected List getAcceptableAaguid(WebAuthnPolicyPage.MultivaluedAcceptableAaguid acceptableAaguid) {
- return acceptableAaguid.getItems()
- .stream()
- .map(UIUtils::getTextInputValue)
- .collect(Collectors.toList());
- }
-
- /**
- * Assert WebAuthn Realm data before and after modification
- *
- * @param actualValue actual value before modification
- * @param expectedValue expected value after modification
- * @param getCurrentValue get updated value
- * @param setData exact approach, how to change the realm data
- */
- private void assertDataAfterModification(T actualValue, T expectedValue,
- Function getCurrentValue,
- Consumer setData) {
-
- WebAuthnRealmData realm = new WebAuthnRealmData(testRealmResource().toRepresentation(), isPasswordless());
- assertThat(realm, notNullValue());
-
- assertThat(getCurrentValue.apply(realm), is(actualValue));
-
- WebAuthnRealmData.Builder builder = realm.builder();
- assertThat(builder, notNullValue());
- setData.accept(builder);
-
- final RealmRepresentation newRealm = builder.build();
- assertThat(newRealm, notNullValue());
-
- testRealmResource().update(newRealm);
-
- realm = new WebAuthnRealmData(testRealmResource().toRepresentation(), isPasswordless());
- assertThat(realm, notNullValue());
-
- assertThat(getCurrentValue.apply(realm), is(expectedValue));
- }
-}