parent
3528e7ba54
commit
191ef1874e
7 changed files with 588 additions and 731 deletions
|
@ -20,6 +20,7 @@ package org.keycloak.testsuite.webauthn.utils;
|
|||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
@ -79,4 +80,84 @@ public class WebAuthnRealmData {
|
|||
public List<String> getAcceptableAaguids() {
|
||||
return isPasswordless ? realm.getWebAuthnPolicyPasswordlessAcceptableAaguids() : realm.getWebAuthnPolicyAcceptableAaguids();
|
||||
}
|
||||
|
||||
public RealmRepresentation getRealm() {
|
||||
return realm;
|
||||
}
|
||||
|
||||
public Builder builder() {
|
||||
return new Builder(realm, isPasswordless);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final RealmRepresentation realm;
|
||||
private final boolean isPasswordless;
|
||||
|
||||
public Builder(RealmRepresentation realm, boolean isPasswordless) {
|
||||
this.realm = realm;
|
||||
this.isPasswordless = isPasswordless;
|
||||
}
|
||||
|
||||
public Builder rpEntityName(String entityName) {
|
||||
setProperty(entityName, realm::setWebAuthnPolicyRpEntityName, realm::setWebAuthnPolicyPasswordlessRpEntityName);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder signatureAlgorithms(List<String> list) {
|
||||
setProperty(list, realm::setWebAuthnPolicySignatureAlgorithms, realm::setWebAuthnPolicyPasswordlessSignatureAlgorithms);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder rpId(String rpId) {
|
||||
setProperty(rpId, realm::setWebAuthnPolicyRpId, realm::setWebAuthnPolicyPasswordlessRpId);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder attestationConveyancePreference(String preference) {
|
||||
setProperty(preference, realm::setWebAuthnPolicyAttestationConveyancePreference, realm::setWebAuthnPolicyPasswordlessAttestationConveyancePreference);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder authenticatorAttachment(String attachment) {
|
||||
setProperty(attachment, realm::setWebAuthnPolicyAuthenticatorAttachment, realm::setWebAuthnPolicyPasswordlessAuthenticatorAttachment);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder requireResidentKey(String requirement) {
|
||||
setProperty(requirement, realm::setWebAuthnPolicyRequireResidentKey, realm::setWebAuthnPolicyPasswordlessRequireResidentKey);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder userVerificationRequirement(String requirement) {
|
||||
setProperty(requirement, realm::setWebAuthnPolicyUserVerificationRequirement, realm::setWebAuthnPolicyPasswordlessUserVerificationRequirement);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder timeout(Integer timeout) {
|
||||
setProperty(timeout, realm::setWebAuthnPolicyCreateTimeout, realm::setWebAuthnPolicyPasswordlessCreateTimeout);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder avoidSameAuthenticatorRegister(Boolean state) {
|
||||
setProperty(state, realm::setWebAuthnPolicyAvoidSameAuthenticatorRegister, realm::setWebAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder acceptableAaguids(List<String> aaguids) {
|
||||
setProperty(aaguids, realm::setWebAuthnPolicyAcceptableAaguids, realm::setWebAuthnPolicyPasswordlessAcceptableAaguids);
|
||||
return this;
|
||||
}
|
||||
|
||||
public RealmRepresentation build() {
|
||||
return realm;
|
||||
}
|
||||
|
||||
private <T> void setProperty(T value, Consumer<T> webauthnSetter, Consumer<T> passwordlessSetter) {
|
||||
if (isPasswordless) {
|
||||
passwordlessSetter.accept(value);
|
||||
} else {
|
||||
webauthnSetter.accept(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,422 +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.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
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.util.UIUtils;
|
||||
import org.keycloak.testsuite.webauthn.pages.WebAuthnPolicyPage;
|
||||
import org.keycloak.testsuite.webauthn.updaters.AbstractWebAuthnRealmUpdater;
|
||||
import org.keycloak.testsuite.webauthn.utils.PropertyRequirement;
|
||||
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.stream.Collectors;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
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.hasSize;
|
||||
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 <a href="mailto:mabartos@redhat.com">Martin Bartos</a>
|
||||
*/
|
||||
public abstract class AbstractWebAuthnPolicySettingsTest 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);
|
||||
|
||||
@Before
|
||||
public void navigateToPolicy() {
|
||||
driver.manage().window().maximize();
|
||||
getPolicyPage().navigateTo();
|
||||
waitForPageToLoad();
|
||||
getPolicyPage().assertCurrent();
|
||||
}
|
||||
|
||||
protected abstract WebAuthnPolicyPage getPolicyPage();
|
||||
|
||||
protected abstract AbstractWebAuthnRealmUpdater<?> getWebAuthnRealmUpdater();
|
||||
|
||||
protected AbstractWebAuthnRealmUpdater<?> updateWebAuthnPolicy(
|
||||
String rpName,
|
||||
List<String> algorithms,
|
||||
String attestationPreference,
|
||||
String authenticatorAttachment,
|
||||
String requireResidentKey,
|
||||
String rpId,
|
||||
String userVerification,
|
||||
List<String> 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 <T> void checkAndSet(T value, Consumer<T> consumer) {
|
||||
if (value != null) {
|
||||
consumer.accept(value);
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkRpEntityValues() {
|
||||
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"));
|
||||
}
|
||||
|
||||
protected void checkWrongSignatureAlgorithm() throws IOException {
|
||||
try (Closeable c = getWebAuthnRealmUpdater()
|
||||
.setWebAuthnPolicySignatureAlgorithms(Collections.singletonList("something-bad"))
|
||||
.update()) {
|
||||
|
||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
|
||||
final List<String> 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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkSignatureAlgorithms() {
|
||||
getPolicyPage().assertCurrent();
|
||||
|
||||
final Select algorithms = getPolicyPage().getSignatureAlgorithms();
|
||||
assertThat(algorithms, notNullValue());
|
||||
|
||||
algorithms.selectByValue("ES256");
|
||||
algorithms.selectByValue("ES384");
|
||||
algorithms.selectByValue("RS1");
|
||||
|
||||
final List<String> 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));
|
||||
}
|
||||
|
||||
public void checkAttestationConveyancePreference() {
|
||||
// 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) {
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkAuthenticatorAttachment() {
|
||||
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));
|
||||
}
|
||||
|
||||
protected void checkResidentKey() {
|
||||
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));
|
||||
}
|
||||
|
||||
protected void checkUserVerification() {
|
||||
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));
|
||||
}
|
||||
|
||||
protected void checkTimeout() {
|
||||
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));
|
||||
}
|
||||
|
||||
protected void checkAvoidSameAuthenticatorRegistration() {
|
||||
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));
|
||||
}
|
||||
|
||||
protected void checkAcceptableAaguid() {
|
||||
WebAuthnPolicyPage.MultivaluedAcceptableAaguid acceptableAaguid = getPolicyPage().getAcceptableAaguid();
|
||||
assertThat(acceptableAaguid, notNullValue());
|
||||
|
||||
List<String> 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);
|
||||
}
|
||||
|
||||
protected List<String> getAcceptableAaguid(WebAuthnPolicyPage.MultivaluedAcceptableAaguid acceptableAaguid) {
|
||||
return acceptableAaguid.getItems()
|
||||
.stream()
|
||||
.map(UIUtils::getTextInputValue)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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 <a href="mailto:mabartos@redhat.com">Martin Bartos</a>
|
||||
*/
|
||||
public class PwdLessPolicySettingsTest extends WebAuthnPolicySettingsTest {
|
||||
|
||||
@Override
|
||||
protected boolean isPasswordless() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,219 +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.Test;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.updaters.RealmAttributeUpdater;
|
||||
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 java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.webauthn4j.data.AttestationConveyancePreference.DIRECT;
|
||||
import static com.webauthn4j.data.AuthenticatorAttachment.PLATFORM;
|
||||
import static com.webauthn4j.data.UserVerificationRequirement.PREFERRED;
|
||||
import static org.hamcrest.CoreMatchers.hasItems;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mabartos@redhat.com">Martin Bartos</a>
|
||||
*/
|
||||
public class WebAuthnPolicyPasswordlessSettingsTest extends AbstractWebAuthnPolicySettingsTest {
|
||||
|
||||
@Page
|
||||
WebAuthnPolicyPasswordlessPage webAuthnPolicyPasswordlessPage;
|
||||
|
||||
@Override
|
||||
protected WebAuthnPolicyPage getPolicyPage() {
|
||||
return webAuthnPolicyPasswordlessPage;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractWebAuthnRealmUpdater<PasswordLessRealmAttributeUpdater> getWebAuthnRealmUpdater() {
|
||||
return new PasswordLessRealmAttributeUpdater(testRealmResource());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void policySettingsWithExternalProperties() throws IOException {
|
||||
try (RealmAttributeUpdater rau = updateWebAuthnPolicy(
|
||||
"rpNamePasswordless",
|
||||
Collections.singletonList("RS256"),
|
||||
DIRECT.getValue(),
|
||||
PLATFORM.getValue(),
|
||||
"Yes",
|
||||
"1234",
|
||||
PREFERRED.getValue(),
|
||||
Collections.singletonList(ALL_ZERO_AAGUID))
|
||||
) {
|
||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
|
||||
assertThat(realm.getWebAuthnPolicyPasswordlessSignatureAlgorithms(), hasItems("RS256"));
|
||||
assertThat(realm.getWebAuthnPolicyPasswordlessAttestationConveyancePreference(), is(DIRECT.getValue()));
|
||||
assertThat(realm.getWebAuthnPolicyPasswordlessAuthenticatorAttachment(), is(PLATFORM.getValue()));
|
||||
assertThat(realm.getWebAuthnPolicyPasswordlessRequireResidentKey(), is("Yes"));
|
||||
assertThat(realm.getWebAuthnPolicyPasswordlessRpId(), is("1234"));
|
||||
assertThat(realm.getWebAuthnPolicyPasswordlessUserVerificationRequirement(), is(PREFERRED.getValue()));
|
||||
assertThat(realm.getWebAuthnPolicyPasswordlessAcceptableAaguids(), hasItems(ALL_ZERO_AAGUID));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void wrongSignatureAlgorithm() throws IOException {
|
||||
checkWrongSignatureAlgorithm();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void algorithmsValuesSetUpInAdminConsole() {
|
||||
checkSignatureAlgorithms();
|
||||
|
||||
final RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
|
||||
final List<String> realmSignatureAlgs = realm.getWebAuthnPolicyPasswordlessSignatureAlgorithms();
|
||||
assertThat(realmSignatureAlgs, notNullValue());
|
||||
assertThat(realmSignatureAlgs, hasSize(3));
|
||||
assertThat(realmSignatureAlgs, contains("ES256", "ES384", "RS1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rpValuesSetUpInAdminConsole() {
|
||||
checkRpEntityValues();
|
||||
|
||||
final RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
|
||||
assertThat(realm.getWebAuthnPolicyPasswordlessRpEntityName(), is(Constants.DEFAULT_WEBAUTHN_POLICY_RP_ENTITY_NAME));
|
||||
assertThat(realm.getWebAuthnPolicyPasswordlessRpId(), is("rpId123"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void attestationConveyancePreferenceSettings() {
|
||||
checkAttestationConveyancePreference();
|
||||
|
||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
|
||||
assertThat(realm.getWebAuthnPolicyPasswordlessAttestationConveyancePreference(), is(AttestationConveyancePreference.NONE.getValue()));
|
||||
|
||||
realm.setWebAuthnPolicyPasswordlessAttestationConveyancePreference(null);
|
||||
testRealmResource().update(realm);
|
||||
|
||||
realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
|
||||
assertThat(realm.getWebAuthnPolicyPasswordlessAttestationConveyancePreference(), is(DEFAULT_WEBAUTHN_POLICY_NOT_SPECIFIED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticatorAttachmentSettings() {
|
||||
checkAuthenticatorAttachment();
|
||||
|
||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
|
||||
assertThat(realm.getWebAuthnPolicyPasswordlessAuthenticatorAttachment(), is(AuthenticatorAttachment.PLATFORM.getValue()));
|
||||
|
||||
realm.setWebAuthnPolicyPasswordlessAuthenticatorAttachment(null);
|
||||
testRealmResource().update(realm);
|
||||
|
||||
realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
|
||||
assertThat(realm.getWebAuthnPolicyPasswordlessAuthenticatorAttachment(), is(DEFAULT_WEBAUTHN_POLICY_NOT_SPECIFIED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requireResidentKeySettings() {
|
||||
checkResidentKey();
|
||||
|
||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
|
||||
assertThat(realm.getWebAuthnPolicyPasswordlessRequireResidentKey(), is("No"));
|
||||
|
||||
realm.setWebAuthnPolicyPasswordlessRequireResidentKey(null);
|
||||
testRealmResource().update(realm);
|
||||
|
||||
realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
|
||||
assertThat(realm.getWebAuthnPolicyPasswordlessRequireResidentKey(), is(DEFAULT_WEBAUTHN_POLICY_NOT_SPECIFIED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void userVerificationRequirementSettings() {
|
||||
checkUserVerification();
|
||||
|
||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
|
||||
assertThat(realm.getWebAuthnPolicyPasswordlessUserVerificationRequirement(), is(UserVerificationRequirement.DISCOURAGED.getValue()));
|
||||
|
||||
realm.setWebAuthnPolicyPasswordlessUserVerificationRequirement(null);
|
||||
testRealmResource().update(realm);
|
||||
|
||||
realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
|
||||
assertThat(realm.getWebAuthnPolicyPasswordlessUserVerificationRequirement(), is(DEFAULT_WEBAUTHN_POLICY_NOT_SPECIFIED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void timeoutSettings() {
|
||||
checkTimeout();
|
||||
|
||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
|
||||
assertThat(realm.getWebAuthnPolicyPasswordlessCreateTimeout(), is(500));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void avoidSameAuthenticatorRegistrationSettings() {
|
||||
checkAvoidSameAuthenticatorRegistration();
|
||||
|
||||
final RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
assertThat(realm.isWebAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister(), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void acceptableAaguidSettings() {
|
||||
checkAcceptableAaguid();
|
||||
|
||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
assertThat(realm.getWebAuthnPolicyPasswordlessAcceptableAaguids(), is(getAcceptableAaguid(getPolicyPage().getAcceptableAaguid())));
|
||||
}
|
||||
}
|
|
@ -21,45 +21,117 @@ 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 <a href="mailto:mabartos@redhat.com">Martin Bartos</a>
|
||||
*/
|
||||
public class WebAuthnPolicySettingsTest extends AbstractWebAuthnPolicySettingsTest {
|
||||
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;
|
||||
|
||||
@Override
|
||||
protected WebAuthnPolicyPage getPolicyPage() {
|
||||
return webAuthnPolicyPage;
|
||||
@Page
|
||||
WebAuthnPolicyPasswordlessPage webAuthnPolicyPasswordlessPage;
|
||||
|
||||
@Before
|
||||
public void navigateToPolicy() {
|
||||
driver.manage().window().maximize();
|
||||
getPolicyPage().navigateTo();
|
||||
waitForPageToLoad();
|
||||
getPolicyPage().assertCurrent();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractWebAuthnRealmUpdater<WebAuthnRealmAttributeUpdater> getWebAuthnRealmUpdater() {
|
||||
return new WebAuthnRealmAttributeUpdater(testRealmResource());
|
||||
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<String> algorithms,
|
||||
String attestationPreference,
|
||||
String authenticatorAttachment,
|
||||
String requireResidentKey,
|
||||
String rpId,
|
||||
String userVerification,
|
||||
List<String> 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 <T> void checkAndSet(T value, Consumer<T> consumer) {
|
||||
if (value != null) {
|
||||
consumer.accept(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -74,150 +146,424 @@ public class WebAuthnPolicySettingsTest extends AbstractWebAuthnPolicySettingsTe
|
|||
PREFERRED.getValue(),
|
||||
Collections.singletonList(ALL_ZERO_AAGUID))
|
||||
) {
|
||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
|
||||
WebAuthnRealmData realm = new WebAuthnRealmData(testRealmResource().toRepresentation(), isPasswordless());
|
||||
assertThat(realm, notNullValue());
|
||||
|
||||
assertThat(realm.getWebAuthnPolicySignatureAlgorithms(), hasItems("ES256"));
|
||||
assertThat(realm.getWebAuthnPolicyAttestationConveyancePreference(), is(INDIRECT.getValue()));
|
||||
assertThat(realm.getWebAuthnPolicyAuthenticatorAttachment(), is(CROSS_PLATFORM.getValue()));
|
||||
assertThat(realm.getWebAuthnPolicyRequireResidentKey(), is("No"));
|
||||
assertThat(realm.getWebAuthnPolicyRpId(), is(""));
|
||||
assertThat(realm.getWebAuthnPolicyUserVerificationRequirement(), is(PREFERRED.getValue()));
|
||||
assertThat(realm.getWebAuthnPolicyAcceptableAaguids(), hasItems(ALL_ZERO_AAGUID));
|
||||
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 wrongSignatureAlgorithm() throws IOException {
|
||||
checkWrongSignatureAlgorithm();
|
||||
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 algorithmsValuesSetUpInAdminConsole() {
|
||||
checkSignatureAlgorithms();
|
||||
public void wrongSignatureAlgorithm() throws IOException {
|
||||
try (Closeable c = getWebAuthnRealmUpdater()
|
||||
.setWebAuthnPolicySignatureAlgorithms(Collections.singletonList("something-bad"))
|
||||
.update()) {
|
||||
|
||||
final RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
|
||||
final List<String> 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<String> 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<String> realmSignatureAlgs = realm.getWebAuthnPolicySignatureAlgorithms();
|
||||
final List<String> realmSignatureAlgs = realm.getSignatureAlgorithms();
|
||||
assertThat(realmSignatureAlgs, notNullValue());
|
||||
assertThat(realmSignatureAlgs, hasSize(3));
|
||||
assertThat(realmSignatureAlgs, contains("ES256", "ES384", "RS1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rpValuesSetUpInAdminConsole() {
|
||||
checkRpEntityValues();
|
||||
public void attestationConveyancePreference() {
|
||||
// default not specified
|
||||
AttestationConveyancePreference attestation = getPolicyPage().getAttestationConveyancePreference();
|
||||
assertThat(attestation, nullValue());
|
||||
|
||||
final RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
// Direct
|
||||
getPolicyPage().setAttestationConveyancePreference(AttestationConveyancePreference.DIRECT);
|
||||
getPolicyPage().clickSaveButton();
|
||||
|
||||
assertThat(realm.getWebAuthnPolicyRpEntityName(), is(Constants.DEFAULT_WEBAUTHN_POLICY_RP_ENTITY_NAME));
|
||||
assertThat(realm.getWebAuthnPolicyRpId(), is("rpId123"));
|
||||
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 attestationConveyancePreferenceSettings() {
|
||||
checkAttestationConveyancePreference();
|
||||
public void authenticatorAttachment() {
|
||||
AuthenticatorAttachment attachment = getPolicyPage().getAuthenticatorAttachment();
|
||||
assertThat(attachment, nullValue());
|
||||
|
||||
// Realm
|
||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
// Cross-platform
|
||||
getPolicyPage().setAuthenticatorAttachment(AuthenticatorAttachment.CROSS_PLATFORM);
|
||||
getPolicyPage().clickSaveButton();
|
||||
|
||||
assertThat(realm.getWebAuthnPolicyAttestationConveyancePreference(), is(AttestationConveyancePreference.NONE.getValue()));
|
||||
attachment = getPolicyPage().getAuthenticatorAttachment();
|
||||
assertThat(attachment, notNullValue());
|
||||
assertThat(attachment, is(AuthenticatorAttachment.CROSS_PLATFORM));
|
||||
|
||||
realm.setWebAuthnPolicyAttestationConveyancePreference(null);
|
||||
testRealmResource().update(realm);
|
||||
// Platform
|
||||
getPolicyPage().setAuthenticatorAttachment(AuthenticatorAttachment.PLATFORM);
|
||||
getPolicyPage().clickSaveButton();
|
||||
|
||||
realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
attachment = getPolicyPage().getAuthenticatorAttachment();
|
||||
assertThat(attachment, notNullValue());
|
||||
assertThat(attachment, is(AuthenticatorAttachment.PLATFORM));
|
||||
|
||||
assertThat(realm.getWebAuthnPolicyAttestationConveyancePreference(), is(DEFAULT_WEBAUTHN_POLICY_NOT_SPECIFIED));
|
||||
assertDataAfterModification(AuthenticatorAttachment.PLATFORM.getValue(),
|
||||
DEFAULT_WEBAUTHN_POLICY_NOT_SPECIFIED,
|
||||
WebAuthnRealmData::getAuthenticatorAttachment,
|
||||
(builder) -> builder.authenticatorAttachment(null)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticatorAttachmentSettings() {
|
||||
checkAuthenticatorAttachment();
|
||||
public void residentKey() {
|
||||
PropertyRequirement requireResidentKey = getPolicyPage().requireResidentKey();
|
||||
assertThat(requireResidentKey, notNullValue());
|
||||
assertThat(requireResidentKey, is(PropertyRequirement.NOT_SPECIFIED));
|
||||
|
||||
// Realm
|
||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
getPolicyPage().requireResidentKey(YES);
|
||||
getPolicyPage().clickSaveButton();
|
||||
|
||||
assertThat(realm.getWebAuthnPolicyAuthenticatorAttachment(), is(AuthenticatorAttachment.PLATFORM.getValue()));
|
||||
// Yes
|
||||
requireResidentKey = getPolicyPage().requireResidentKey();
|
||||
assertThat(requireResidentKey, notNullValue());
|
||||
assertThat(requireResidentKey, is(YES));
|
||||
|
||||
realm.setWebAuthnPolicyAuthenticatorAttachment(null);
|
||||
testRealmResource().update(realm);
|
||||
getPolicyPage().requireResidentKey(NO);
|
||||
getPolicyPage().clickSaveButton();
|
||||
|
||||
realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
// Null
|
||||
getPolicyPage().requireResidentKey(null);
|
||||
assertThat(getPolicyPage().isSaveButtonEnabled(), is(false));
|
||||
|
||||
assertThat(realm.getWebAuthnPolicyAuthenticatorAttachment(), is(DEFAULT_WEBAUTHN_POLICY_NOT_SPECIFIED));
|
||||
// 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 requireResidentKeySettings() {
|
||||
checkResidentKey();
|
||||
public void userVerification() {
|
||||
UserVerificationRequirement userVerification = getPolicyPage().getUserVerification();
|
||||
assertThat(userVerification, nullValue());
|
||||
|
||||
// Realm
|
||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
// Preferred
|
||||
getPolicyPage().setUserVerification(UserVerificationRequirement.PREFERRED);
|
||||
getPolicyPage().clickSaveButton();
|
||||
|
||||
assertThat(realm.getWebAuthnPolicyRequireResidentKey(), is("No"));
|
||||
userVerification = getPolicyPage().getUserVerification();
|
||||
assertThat(userVerification, notNullValue());
|
||||
assertThat(userVerification, is(UserVerificationRequirement.PREFERRED));
|
||||
|
||||
realm.setWebAuthnPolicyRequireResidentKey(null);
|
||||
testRealmResource().update(realm);
|
||||
// Required
|
||||
getPolicyPage().setUserVerification(UserVerificationRequirement.REQUIRED);
|
||||
getPolicyPage().clickSaveButton();
|
||||
|
||||
realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
userVerification = getPolicyPage().getUserVerification();
|
||||
assertThat(userVerification, notNullValue());
|
||||
assertThat(userVerification, is(UserVerificationRequirement.REQUIRED));
|
||||
|
||||
assertThat(realm.getWebAuthnPolicyRequireResidentKey(), is(DEFAULT_WEBAUTHN_POLICY_NOT_SPECIFIED));
|
||||
// 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 userVerificationRequirementSettings() {
|
||||
checkUserVerification();
|
||||
public void timeout() {
|
||||
int timeout = getPolicyPage().getTimeout();
|
||||
assertThat(timeout, is(0));
|
||||
|
||||
// Realm
|
||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
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.getWebAuthnPolicyUserVerificationRequirement(), is(UserVerificationRequirement.DISCOURAGED.getValue()));
|
||||
|
||||
realm.setWebAuthnPolicyUserVerificationRequirement(null);
|
||||
testRealmResource().update(realm);
|
||||
|
||||
realm = testRealmResource().toRepresentation();
|
||||
assertThat(realm, notNullValue());
|
||||
|
||||
assertThat(realm.getWebAuthnPolicyUserVerificationRequirement(), is(DEFAULT_WEBAUTHN_POLICY_NOT_SPECIFIED));
|
||||
assertThat(realm.getCreateTimeout(), is(500));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void timeoutSettings() {
|
||||
checkTimeout();
|
||||
public void avoidSameAuthenticatorRegistration() {
|
||||
boolean avoidSameAuthenticatorRegistration = getPolicyPage().avoidSameAuthenticatorRegistration();
|
||||
assertThat(avoidSameAuthenticatorRegistration, is(false));
|
||||
|
||||
// Realm
|
||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
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.getWebAuthnPolicyCreateTimeout(), is(500));
|
||||
assertThat(realm.isAvoidSameAuthenticatorRegister(), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void avoidSameAuthenticatorRegistrationSettings() {
|
||||
checkAvoidSameAuthenticatorRegistration();
|
||||
public void acceptableAaguid() {
|
||||
WebAuthnPolicyPage.MultivaluedAcceptableAaguid acceptableAaguid = getPolicyPage().getAcceptableAaguid();
|
||||
assertThat(acceptableAaguid, notNullValue());
|
||||
|
||||
final RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
List<String> 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.isWebAuthnPolicyAvoidSameAuthenticatorRegister(), is(false));
|
||||
assertThat(realm.getAcceptableAaguids(), is(getAcceptableAaguid(getPolicyPage().getAcceptableAaguid())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void acceptableAaguidSettings() {
|
||||
checkAcceptableAaguid();
|
||||
protected List<String> getAcceptableAaguid(WebAuthnPolicyPage.MultivaluedAcceptableAaguid acceptableAaguid) {
|
||||
return acceptableAaguid.getItems()
|
||||
.stream()
|
||||
.map(UIUtils::getTextInputValue)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
/**
|
||||
* 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 <T> void assertDataAfterModification(T actualValue, T expectedValue,
|
||||
Function<WebAuthnRealmData, T> getCurrentValue,
|
||||
Consumer<WebAuthnRealmData.Builder> setData) {
|
||||
|
||||
WebAuthnRealmData realm = new WebAuthnRealmData(testRealmResource().toRepresentation(), isPasswordless());
|
||||
assertThat(realm, notNullValue());
|
||||
assertThat(realm.getWebAuthnPolicyAcceptableAaguids(), is(getAcceptableAaguid(getPolicyPage().getAcceptableAaguid())));
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,13 +15,16 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.webauthn;
|
||||
package org.keycloak.testsuite.webauthn.passwordless;
|
||||
|
||||
import org.keycloak.testsuite.webauthn.AppInitiatedActionWebAuthnTest;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mabartos@redhat.com">Martin Bartos</a>
|
||||
*/
|
||||
public class AppInitiatedActionPwdLessTest extends AppInitiatedActionWebAuthnTest {
|
||||
|
||||
@Override
|
||||
protected boolean isPasswordless() {
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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.passwordless;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.testsuite.webauthn.WebAuthnPropertyTest;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mabartos@redhat.com">Martin Bartos</a>
|
||||
*/
|
||||
public class WebAuthnPwdLessPropertyTest extends WebAuthnPropertyTest {
|
||||
|
||||
@Override
|
||||
public boolean isPasswordless() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Ignore("Not usable for Passwordless")
|
||||
@Test
|
||||
public void requiredActionRegistration() {
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue