package org.keycloak.testsuite.console.page.clients.settings; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.testsuite.console.page.clients.CreateClientForm; import org.keycloak.testsuite.console.page.fragment.OnOffSwitch; import org.keycloak.testsuite.page.Form; import org.keycloak.testsuite.util.Timer; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.ui.Select; import static org.keycloak.testsuite.util.WaitUtils.pause; import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement; /** * @author tkyjovsk */ public class ClientSettingsForm extends CreateClientForm { @FindBy(id = "name") private WebElement nameInput; @FindBy(id = "baseUrl") private WebElement baseUrlInput; @FindBy(id = "adminUrl") private WebElement adminUrlInput; @FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='enabled']]") private OnOffSwitch enabledSwitch; @FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='consentRequired']]") private OnOffSwitch consentRequiredSwitch; @FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='standardFlowEnabled']]") private OnOffSwitch standardFlowEnabledSwitch; @FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='implicitFlowEnabled']]") private OnOffSwitch implicitFlowEnabledSwitch; @FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='directAccessGrantsEnabled']]") private OnOffSwitch directAccessGrantsEnabledSwitch; @FindBy(id = "accessType") private Select accessTypeSelect; @FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='serviceAccountsEnabled']]") private OnOffSwitch serviceAccountsEnabledSwitch; @FindBy(id = "newRedirectUri") private WebElement newRedirectUriInput; @FindBy(xpath = ".//button[contains(@data-ng-click,'addRedirectUri')]") private WebElement newRedirectUriSubmit; @FindBy(xpath = ".//input[@ng-model='client.redirectUris[i]']") private List<WebElement> redirectUriInputs; @FindBy(xpath = ".//button[contains(@data-ng-click, 'deleteRedirectUri')]") private List<WebElement> deleteRedirectUriIcons; @FindBy(id = "newWebOrigin") private WebElement newWebOriginInput; @FindBy(xpath = ".//button[contains(@data-ng-click,'addWebOrigin')]") private WebElement newWebOriginSubmit; @FindBy(xpath = ".//input[ng-model='client.webOrigins[i]']") private List<WebElement> webOriginInputs; @FindBy(xpath = ".//button[contains(@data-ng-click, 'deleteWebOrigin')]") private List<WebElement> deleteWebOriginIcons; @FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='authorizationServicesEnabled']]") private OnOffSwitch authorizationSettingsEnabledSwitch; @FindBy(xpath = ACTIVE_DIV_XPATH + "/button[text()='Disable Authorization Settings']") private WebElement confirmDisableAuthorizationSettingsButton; public enum OidcAccessType { BEARER_ONLY("bearer-only"), PUBLIC("public"), CONFIDENTIAL("confidential"); private final String name; private OidcAccessType(String name) { this.name = name; } public String getName() { return name; } } public void setBaseUrl(String baseUrl) { setInputValue(baseUrlInput, baseUrl); } public String getBaseUrl() { return getInputValue(baseUrlInput); } public void setAdminUrl(String adminUrl) { setInputValue(adminUrlInput, adminUrl); } public String getAdminUrl() { return getInputValue(adminUrlInput); } public void addWebOrigin(String redirectUri) { newWebOriginInput.sendKeys(redirectUri); newWebOriginSubmit.click(); } public List<String> getWebOrigins() { List<String> values = new ArrayList<>(); for (WebElement input : webOriginInputs) { values.add(getInputValue(input)); } return values; } public void setWebOrigins(List<String> webOrigins) { while (!deleteWebOriginIcons.isEmpty()) { deleteWebOriginIcons.get(0).click(); pause(100); } if (webOrigins != null) { for (String redirectUri : webOrigins) { addWebOrigin(redirectUri); pause(100); } } } public String getName() { return getInputValue(nameInput); } public void setName(String name) { setInputValue(nameInput, name); } public boolean isEnabled() { return enabledSwitch.isOn(); } public void setEnabled(boolean enabled) { enabledSwitch.setOn(enabled); } public boolean isConsentRequired() { return consentRequiredSwitch.isOn(); } public void setConsentRequired(boolean consentRequired) { consentRequiredSwitch.setOn(consentRequired); } public void setAccessType(OidcAccessType accessType) { accessTypeSelect.selectByVisibleText(accessType.getName()); } public void addRedirectUri(String redirectUri) { newRedirectUriInput.sendKeys(redirectUri); newRedirectUriSubmit.click(); } public List<String> getRedirectUris() { List<String> values = new ArrayList<>(); for (WebElement input : redirectUriInputs) { values.add(getInputValue(input)); } return values; } public void setRedirectUris(List<String> redirectUris) { Timer.DEFAULT.reset(); while (!deleteRedirectUriIcons.isEmpty()) { deleteRedirectUriIcons.get(0).click(); pause(100); } Timer.DEFAULT.reset("deleteRedirectUris"); if (redirectUris != null) { for (String redirectUri : redirectUris) { addRedirectUri(redirectUri); pause(100); } } Timer.DEFAULT.reset("addRedirectUris"); } public boolean isStandardFlowEnabled() { return standardFlowEnabledSwitch.isOn(); } public void setStandardFlowEnabled(boolean standardFlowEnabled) { standardFlowEnabledSwitch.setOn(standardFlowEnabled); } public boolean isImplicitFlowEnabled() { return implicitFlowEnabledSwitch.isOn(); } public void setImplicitFlowEnabled(boolean implicitFlowEnabled) { implicitFlowEnabledSwitch.setOn(implicitFlowEnabled); } public boolean isDirectAccessGrantsEnabled() { return directAccessGrantsEnabledSwitch.isOn(); } public void setDirectAccessGrantsEnabled(boolean directAccessGrantsEnabled) { directAccessGrantsEnabledSwitch.setOn(directAccessGrantsEnabled); } public boolean isServiceAccountsEnabled() { return serviceAccountsEnabledSwitch.isOn(); } public void setServiceAccountsEnabled(boolean serviceAccountsEnabled) { serviceAccountsEnabledSwitch.setOn(serviceAccountsEnabled); } public void setAuthorizationSettingsEnabled(boolean enabled) { authorizationSettingsEnabledSwitch.setOn(enabled); } public boolean isAuthorizationSettingsEnabled() { return authorizationSettingsEnabledSwitch.isOn(); } public void confirmDisableAuthorizationSettings() { confirmDisableAuthorizationSettingsButton.click(); } public class SAMLClientSettingsForm extends Form { public static final String SAML_ASSERTION_SIGNATURE = "saml.assertion.signature"; public static final String SAML_AUTHNSTATEMENT = "saml.authnstatement"; public static final String SAML_ONETIMEUSE_CONDITION = "saml.onetimeuse.condition"; public static final String SAML_CLIENT_SIGNATURE = "saml.client.signature"; public static final String SAML_ENCRYPT = "saml.encrypt"; public static final String SAML_FORCE_POST_BINDING = "saml.force.post.binding"; public static final String SAML_MULTIVALUED_ROLES = "saml.multivalued.roles"; public static final String SAML_SERVER_SIGNATURE = "saml.server.signature"; public static final String SAML_SERVER_SIGNATURE_KEYINFO_EXT = "saml.server.signature.keyinfo.ext"; public static final String SAML_SIGNATURE_ALGORITHM = "saml.signature.algorithm"; public static final String SAML_ASSERTION_CONSUMER_URL_POST = "saml_assertion_consumer_url_post"; public static final String SAML_ASSERTION_CONSUMER_URL_REDIRECT = "saml_assertion_consumer_url_redirect"; public static final String SAML_FORCE_NAME_ID_FORMAT = "saml_force_name_id_format"; public static final String SAML_NAME_ID_FORMAT = "saml_name_id_format"; public static final String SAML_SIGNATURE_CANONICALIZATION_METHOD = "saml_signature_canonicalization_method"; public static final String SAML_SINGLE_LOGOUT_SERVICE_URL_POST = "saml_single_logout_service_url_post"; public static final String SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT = "saml_single_logout_service_url_redirect"; @FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='samlAuthnStatement']]") private OnOffSwitch samlAuthnStatement; @FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='samlOneTimeUseCondition']]") private OnOffSwitch samlOneTimeUseCondition; @FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='samlServerSignature']]") private OnOffSwitch samlServerSignature; @FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='samlServerSignatureEnableKeyInfoExtension']]") private OnOffSwitch samlServerSignatureKeyInfoExt; @FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='samlAssertionSignature']]") private OnOffSwitch samlAssertionSignature; @FindBy(id = "signatureAlgorithm") private Select signatureAlgorithm; @FindBy(id = "canonicalization") private Select canonicalization; @FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='samlEncrypt']]") private OnOffSwitch samlEncrypt; @FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='samlClientSignature']]") private OnOffSwitch samlClientSignature; @FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='samlForcePostBinding']]") private OnOffSwitch samlForcePostBinding; @FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='frontchannelLogout']]") private OnOffSwitch frontchannelLogout; @FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='samlForceNameIdFormat']]") private OnOffSwitch samlForceNameIdFormat; @FindBy(id = "samlNameIdFormat") private Select samlNameIdFormat; @FindBy(xpath = "//fieldset[contains(@data-ng-show, 'saml')]//i") private WebElement fineGrainCollapsor; @FindBy(id = "consumerServicePost") private WebElement consumerServicePostInput; @FindBy(id = "consumerServiceRedirect") private WebElement consumerServiceRedirectInput; @FindBy(id = "logoutPostBinding") private WebElement logoutPostBindingInput; @FindBy(id = "logoutRedirectBinding") private WebElement logoutRedirectBindingInput; public void setValues(ClientRepresentation client) { waitUntilElement(fineGrainCollapsor).is().visible(); Map<String, String> attributes = client.getAttributes(); samlAuthnStatement.setOn("true".equals(attributes.get(SAML_AUTHNSTATEMENT))); samlOneTimeUseCondition.setOn("true".equals(attributes.get(SAML_ONETIMEUSE_CONDITION))); samlServerSignature.setOn("true".equals(attributes.get(SAML_SERVER_SIGNATURE))); samlAssertionSignature.setOn("true".equals(attributes.get(SAML_ASSERTION_SIGNATURE))); if (samlServerSignature.isOn() || samlAssertionSignature.isOn()) { signatureAlgorithm.selectByVisibleText(attributes.get(SAML_SIGNATURE_ALGORITHM)); canonicalization.selectByValue("string:" + attributes.get(SAML_SIGNATURE_CANONICALIZATION_METHOD)); samlServerSignatureKeyInfoExt.setOn("true".equals(attributes.get(SAML_SERVER_SIGNATURE_KEYINFO_EXT))); } samlEncrypt.setOn("true".equals(attributes.get(SAML_ENCRYPT))); samlClientSignature.setOn("true".equals(attributes.get(SAML_CLIENT_SIGNATURE))); samlForcePostBinding.setOn("true".equals(attributes.get(SAML_FORCE_POST_BINDING))); frontchannelLogout.setOn(client.isFrontchannelLogout()); samlForceNameIdFormat.setOn("true".equals(attributes.get(SAML_FORCE_NAME_ID_FORMAT))); samlNameIdFormat.selectByVisibleText(attributes.get(SAML_NAME_ID_FORMAT)); fineGrainCollapsor.click(); waitUntilElement(consumerServicePostInput).is().present(); setInputValue(consumerServicePostInput, attributes.get(SAML_ASSERTION_CONSUMER_URL_POST)); setInputValue(consumerServiceRedirectInput, attributes.get(SAML_ASSERTION_CONSUMER_URL_REDIRECT)); setInputValue(logoutPostBindingInput, attributes.get(SAML_SINGLE_LOGOUT_SERVICE_URL_POST)); setInputValue(logoutRedirectBindingInput, attributes.get(SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT)); } } }