Pass and use rememberMe option in passkeys authenticators

Closes #45104
This commit is contained in:
Ricardo Martin
2026-04-15 15:28:56 +02:00
committed by GitHub
parent 072d0d9279
commit 95cdee91aa
15 changed files with 1148 additions and 918 deletions
@@ -163,4 +163,12 @@ public class EventAssertion {
return this;
}
/**
* Return the event associated to the assertion.
*
* @return the asserted {@link EventRepresentation}
*/
public EventRepresentation getEvent() {
return event;
}
}
@@ -454,6 +454,11 @@ public class RealmConfigBuilder {
return this;
}
public RealmConfigBuilder webAuthnPolicyPasswordlessPasskeysEnabled(Boolean enabled) {
rep.setWebAuthnPolicyPasswordlessPasskeysEnabled(enabled);
return this;
}
public RealmConfigBuilder webAuthnPolicyAcceptableAaguids(List<String> aaguids) {
rep.setWebAuthnPolicyAcceptableAaguids(aaguids);
return this;
@@ -17,6 +17,8 @@
package org.keycloak.testframework.ui.page;
import java.util.Optional;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.openqa.selenium.By;
@@ -41,6 +43,12 @@ public abstract class AbstractLoginPage extends AbstractPage {
@FindBy(id = "kc-attempted-username") // Username during re-authentication
private WebElement attemptedUsernameLabel;
@FindBy(className = "pf-m-info")
private WebElement loginInfoMessage;
@FindBy(className = "pf-m-danger")
private WebElement loginErrorMessage;
public AbstractLoginPage(ManagedWebDriver driver) {
super(driver);
}
@@ -76,4 +84,19 @@ public abstract class AbstractLoginPage extends AbstractPage {
}
}
public Optional<String> getInfoMessage() {
try {
return Optional.of(loginInfoMessage.getText());
} catch (NoSuchElementException e) {
return Optional.empty();
}
}
public Optional<String> getErrorMessage() {
try {
return Optional.of(loginErrorMessage.getText());
} catch (NoSuchElementException e) {
return Optional.empty();
}
}
}
@@ -1,5 +1,7 @@
package org.keycloak.testframework.ui.page;
import java.util.Optional;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.openqa.selenium.By;
@@ -30,8 +32,8 @@ public class LoginPage extends AbstractLoginPage {
@FindBy(id = "input-error-username")
private WebElement userNameInputError;
@FindBy(className = "pf-m-danger")
private WebElement loginErrorMessage;
@FindBy(id = "input-error-password")
private WebElement passwordInputError;
public LoginPage(ManagedWebDriver driver) {
super(driver);
@@ -44,6 +46,11 @@ public class LoginPage extends AbstractLoginPage {
passwordInput.sendKeys(password);
}
public void fillPassword(String password) {
passwordInput.clear();
passwordInput.sendKeys(password);
}
public void submit() {
submitButton.click();
}
@@ -86,6 +93,10 @@ public class LoginPage extends AbstractLoginPage {
return usernameInput.getAttribute("value");
}
public String getUsernameAutocomplete() {
return usernameInput.getDomAttribute("autocomplete");
}
public void clearUsernameInput() {
usernameInput.clear();
}
@@ -98,12 +109,11 @@ public class LoginPage extends AbstractLoginPage {
}
}
public String getError() {
public Optional<String> getPasswordInputError() {
try {
return loginErrorMessage.getText();
return Optional.of(passwordInputError.getText());
} catch (NoSuchElementException e) {
return null;
return Optional.empty();
}
}
}
@@ -2,6 +2,7 @@ package org.keycloak.testframework.ui.page;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
@@ -13,14 +14,37 @@ public class LoginUsernamePage extends AbstractLoginPage {
@FindBy(css = "[type=submit]")
private WebElement submitButton;
@FindBy(id = "input-error-username")
private WebElement userNameInputError;
@FindBy(id = "rememberMe")
private WebElement rememberMe;
public LoginUsernamePage(ManagedWebDriver driver) {
super(driver);
}
public void fillLoginWithUsernameOnly(String username) {
usernameInput.clear();
usernameInput.sendKeys(username);
}
public String getUsername() {
return usernameInput.getAttribute("value");
}
public String getUsernameAutocomplete() {
return usernameInput.getDomAttribute("autocomplete");
}
public String getUsernameInputError() {
try {
return userNameInputError.getText();
} catch (NoSuchElementException e) {
return null;
}
}
public void submit() {
submitButton.click();
}
@@ -29,4 +53,15 @@ public class LoginUsernamePage extends AbstractLoginPage {
public String getExpectedPageId() {
return "login-login-username";
}
public void rememberMe(boolean value) {
boolean selected = isRememberMe();
if ((value && !selected) || !value && selected) {
rememberMe.click();
}
}
public boolean isRememberMe() {
return rememberMe.isSelected();
}
}