[java-idp-integration-tests] 08/10: JOIDC-147 - Initial OP plugin Conformance Suite tests
Tom Zeller
tzeller at dragonacea.biz
Wed Aug 28 22:38:36 UTC 2024
This is an automated email from the git hooks/post-receive script.
tzeller pushed a commit to branch main
in repository java-idp-integration-tests.
View the commit online:
http://git.shibboleth.net/view/?p=java-idp-integration-tests.git;a=commit;h=f8f8a5233f4f8a70be5181f0641b0b0674301eee
commit f8f8a5233f4f8a70be5181f0641b0b0674301eee
Author: Tom Zeller <tzeller at dragonacea.biz>
AuthorDate: Wed Aug 28 00:42:07 2024 -0500
JOIDC-147 - Initial OP plugin Conformance Suite tests
Try running a couple of OIDF Conformance Suite tests
https://shibboleth.atlassian.net/browse/JOIDC-147
---
.../idp/integration/tests/oidc/AbstractOPTest.java | 66 +
.../tests/oidc/ConformanceSuiteContainer.java | 480 +++++++
.../integration/tests/oidc/OPConformanceTest.java | 310 +++++
.../skip-oidcc-idtoken-unsigned.json | 7 +
.../skip-oidcc-server-rotate-keys.json | 10 +
.../conformance-suite/testop-config-logout.json | 1393 ++++++++++++++++++++
src/test/oidc/conformance-suite/testop-config.json | 562 ++++++++
7 files changed, 2828 insertions(+)
diff --git a/src/test/java/net/shibboleth/idp/integration/tests/oidc/AbstractOPTest.java b/src/test/java/net/shibboleth/idp/integration/tests/oidc/AbstractOPTest.java
index 8afe77e..1423971 100644
--- a/src/test/java/net/shibboleth/idp/integration/tests/oidc/AbstractOPTest.java
+++ b/src/test/java/net/shibboleth/idp/integration/tests/oidc/AbstractOPTest.java
@@ -168,6 +168,23 @@ public class AbstractOPTest extends BaseIntegrationTest {
logProcess(process, "Generate idp-encryption-rsa.jwk :");
}
+ /**
+ * Enable dynamic client registration.
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void enableDynamicClientRegistration() throws IOException {
+
+ final Path pathToRelyingPartyXML = Paths.get("conf", "relying-party.xml");
+
+ final String oldText = "<ref bean=\"OIDC.Configuration\" />\n";
+
+ final String newText = "<ref bean=\"OIDC.Registration\" />\n";
+
+ replaceIdPHomeFile(pathToRelyingPartyXML, oldText, oldText + newText);
+ }
+
/**
* Enable OIDC attributes / claim rules.
*
@@ -242,6 +259,23 @@ public class AbstractOPTest extends BaseIntegrationTest {
replaceFile(pathToOpenIDConfiguration, "\\{\\{ service_name \\}\\}", hostname + ":" + securePort);
}
+ /**
+ * Set up static/openid-configuration.json using hostname and port.
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void enableOIDCDiscoveryIncludingPort() throws IOException {
+
+ // static/openid-configuration.json
+ final Path pathToOpenIDConfiguration = pathToIdPHome.resolve(Paths.get("static", "openid-configuration.json"));
+
+ assert pathToOpenIDConfiguration.toFile().exists() : "Path to openid-configuration.json not found";
+
+ // Replace template endpoint "{{ service_name }}" with OP host and port
+ replaceFile(pathToOpenIDConfiguration, "\\{\\{ service_name \\}\\}", hostname + ":" + securePort);
+ }
+
/**
* Set up rewrite for static/openid-configuration.json.
*
@@ -402,6 +436,23 @@ public class AbstractOPTest extends BaseIntegrationTest {
Assert.assertTrue(response.contains(expectedIssuer), "Expected issuer not found");
}
+ /**
+ * Ignore TLS certificate checks.
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void ignoreCertificateChecks() throws IOException {
+
+ final Path pathToServicesProperties = Paths.get("conf", "services.properties");
+
+ final String oldText = "#idp.httpclient.connectionDisregardTLSCertificate = false";
+
+ final String newText = "idp.httpclient.connectionDisregardTLSCertificate = true";
+
+ replaceIdPHomeFile(pathToServicesProperties, oldText, newText);
+ }
+
/**
* Use example OIDC attribute resolver and filter.
*
@@ -435,6 +486,21 @@ public class AbstractOPTest extends BaseIntegrationTest {
replaceFile(pathToOIDCProperties, "https://your.issuer.example.org", "https://idp.tests.shibboleth.net");
}
+ /**
+ * Set the Open ID Connect issuer property.
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void setUpOPIssuerIncludingPort() throws IOException {
+
+ final Path pathToOIDCProperties = pathToIdPHome.resolve(Paths.get("conf", "oidc.properties"));
+
+ assert pathToOIDCProperties.toFile().exists() : "Path to oidc.properties not found";
+
+ replaceFile(pathToOIDCProperties, "https://your.issuer.example.org", "https://idp.tests.shibboleth.net:" + securePort);
+ }
+
/**
* Set path to RP keystore to be credentials/idp-userfacing.p12 in either
* jetty-base/ or tomcat-base/ directories.
diff --git a/src/test/java/net/shibboleth/idp/integration/tests/oidc/ConformanceSuiteContainer.java b/src/test/java/net/shibboleth/idp/integration/tests/oidc/ConformanceSuiteContainer.java
new file mode 100644
index 0000000..0519339
--- /dev/null
+++ b/src/test/java/net/shibboleth/idp/integration/tests/oidc/ConformanceSuiteContainer.java
@@ -0,0 +1,480 @@
+
+package net.shibboleth.idp.integration.tests.oidc;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.Lifecycle;
+import org.springframework.util.FileSystemUtils;
+import org.testcontainers.containers.DockerComposeContainer;
+import org.testcontainers.containers.wait.strategy.Wait;
+import org.testng.Assert;
+
+import net.shibboleth.idp.integration.tests.BaseIntegrationTest;
+import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.logic.Constraint;
+
+/**
+ * Start and stop the OIDF conformance suite Docker container.
+ *
+ * https://shibboleth.atlassian.net/wiki/spaces/DEV/pages/3187376129
+ *
+ * https://gitlab.com/openid/conformance-suite/-/wikis/Developers/Build-&-Run
+ *
+ * https://gitlab.com/openid/conformance-suite.git
+ */
+public class ConformanceSuiteContainer extends AbstractIdentifiableInitializableComponent implements Lifecycle {
+
+ /** Class logger. */
+ @Nonnull
+ private final Logger log = LoggerFactory.getLogger(ConformanceSuiteContainer.class);
+
+ /** Cached log prefix. */
+ @Nullable
+ private String logPrefix;
+
+ /** The Docker container. */
+ @NonnullAfterInit
+ public DockerComposeContainer<?> container;
+
+ /** Path to 'conformance-suite' directory */
+
+ protected Path pathToConformanceSuite;
+
+ protected Path pathToDockerComposeYML;
+
+ protected Path pathToPerTestDirectory;
+
+ protected Path pathToPythonVenv;
+
+ protected Path pathToPythonBinActivate;
+
+ /** Path to 'test-distributions' directory */
+ protected Path pathToTestDistributions;
+
+ /** OP hostname or FQDN, defaults to "idp.tests.shibboleth.net" */
+ @Nonnull
+ protected String opHost = "idp.tests.shibboleth.net";
+
+ /** OP port, defaults to 443 */
+ @Nonnull
+ protected String opPort = "443";
+
+ @Override
+ protected void doInitialize() throws ComponentInitializationException {
+
+ super.doInitialize();
+
+ log.debug("{} Initializing ...", getLogPrefix());
+
+ if (pathToPerTestDirectory == null) {
+ throw new ComponentInitializationException("Path to per-test directory cannot be null");
+ }
+
+ if (!pathToPerTestDirectory.toAbsolutePath().toFile().exists()) {
+ throw new ComponentInitializationException("Path to per-test directory does not exist");
+ }
+
+ pathToConformanceSuite = pathToPerTestDirectory.resolve(Paths.get("conformance-suite"));
+
+ // TODO "docker-compose-dev-mac.yml"
+ pathToDockerComposeYML = pathToConformanceSuite.resolve("docker-compose.yml");
+
+ pathToTestDistributions = Paths.get(BaseIntegrationTest.TEST_DISTRIBUTIONS_DIRECTORY);
+
+ pathToPythonVenv = pathToTestDistributions.resolve("conformance-suite-venv");
+
+ pathToPythonBinActivate = pathToPythonVenv.resolve(Paths.get("bin", "activate"));
+
+ try {
+
+ checkoutConformanceSuite();
+
+ buildConformanceSuite();
+
+ configureConformanceSuite();
+
+ allowHostAccess();
+
+ createPythonVenv();
+
+ setUpPythonVenv();
+
+ } catch (IOException e) {
+ log.error("Unable to initialize container", e);
+ throw new ComponentInitializationException(e);
+ }
+
+ // id = "shib-test-conformance-suite"
+
+ // TODO does wait here work propertly ?
+ // TODO closeable
+ container = new DockerComposeContainer(getId(), pathToDockerComposeYML.toFile()) //
+ .withExposedService( //
+ "httpd", //
+ 8443, //
+ Wait.forHttps("/") //
+ .allowInsecure());
+
+ log.debug("{} Initialized", getLogPrefix());
+ }
+
+ /**
+ * Set the hostname or FQDN of the OP.
+ *
+ * @param port
+ * OP port
+ */
+ public void setOPHost(@Nonnull final String host) {
+ Constraint.isNotNull(host, "OP host cannot be null");
+ opHost = host;
+ }
+
+ /**
+ * Set the OP port.
+ *
+ * @param port
+ * OP port
+ */
+ public void setOPPort(@Nonnull final String port) {
+ Constraint.isNotNull(port, "OP port cannot be null");
+ opPort = port;
+ }
+
+ /**
+ * Set the path to the per-test directory.
+ *
+ * @param path
+ * path to the per-test directory
+ */
+ public void setPathToPerTestDirectory(@Nonnull final Path path) {
+ Constraint.isNotNull(path, "Path to per-test directory cannot be null");
+ pathToPerTestDirectory = path;
+ }
+
+ /**
+ * Checkout conformance suite from
+ *
+ * https://gitlab.com/openid/conformance-suite.git
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void checkoutConformanceSuite() throws IOException {
+
+ final String[] commands = new String[] { //
+ "git", //
+ "clone", //
+ "https://gitlab.com/openid/conformance-suite.git" };
+
+ final Process process = new ProcessBuilder() //
+ .command(commands)
+ .directory(pathToPerTestDirectory.toFile())
+ .redirectErrorStream(true)
+ .start();
+
+ logProcess(process, "Checkout openid/conformance-suite :");
+ }
+
+ /**
+ * Build conformance suite using Maven.
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void buildConformanceSuite() throws IOException {
+
+ final String[] commands = new String[] { //
+ "mvn", //
+ "clean", //
+ "package", //
+ "-DskipTests", //
+ "-Dcheckstyle.skip", //
+ "-Dpmd.skip=true" };
+
+ final Process process = new ProcessBuilder() //
+ .command(commands)
+ .directory(pathToConformanceSuite.toAbsolutePath().toFile())
+ .redirectErrorStream(true)
+ .start();
+
+ logProcess(process, "Build openid/conformance-suite :");
+ }
+
+ /**
+ * Configure conformance suite.
+ *
+ * Copy test configuration files to conformance suite directory.
+ *
+ * Replace OP host and port.
+ *
+ * Replace test username and password.
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void configureConformanceSuite() throws IOException {
+
+ final Path pathToSourceDir = Paths.get("src", "test", "oidc", "conformance-suite");
+
+ FileSystemUtils.copyRecursively(pathToSourceDir, pathToConformanceSuite);
+
+ final Path pathToTestOPConfigJSON = pathToConformanceSuite.resolve("testop-config.json");
+
+ replaceFile(pathToTestOPConfigJSON, "testop.funet.fi", opHost + ":" + opPort);
+
+ replaceFile(pathToTestOPConfigJSON, "teppo", "jdoe"); // username
+
+ replaceFile(pathToTestOPConfigJSON, "testaaja", "changeit"); // password
+
+ final Path pathToTestOPConfigLogoutJSON = pathToConformanceSuite.resolve("testop-config-logout.json");
+
+ replaceFile(pathToTestOPConfigLogoutJSON, "testop.funet.fi", opHost + ":" + opPort);
+
+ replaceFile(pathToTestOPConfigLogoutJSON, "teppo", "jdoe"); // username
+
+ replaceFile(pathToTestOPConfigLogoutJSON, "testaaja", "changeit"); // password
+ }
+
+ /**
+ * Allow 'server' Docker service to access OP running on host network.
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void allowHostAccess() throws IOException {
+
+ final String oldText = " context: ./server-dev\n";
+
+ final String newText = " extra_hosts:\n" + //
+ " - \"idp.tests.shibboleth.net:host-gateway\"\n";
+
+ replaceFile(pathToDockerComposeYML, oldText, oldText + newText);
+ }
+
+ /**
+ * Create Python virtual environment in 'test-distributions' directory.
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void createPythonVenv() throws IOException {
+
+ final String[] commands = new String[] { //
+ "python3", //
+ "-m", //
+ "venv", //
+ "conformance-suite-venv" };
+
+ final Process process = new ProcessBuilder() //
+ .command(commands)
+ .directory(pathToTestDistributions.toAbsolutePath().toFile())
+ .redirectErrorStream(true)
+ .start();
+
+ logProcess(process, "Create Python venv :");
+ }
+
+ /**
+ * Install httpx module to Python virtual environment.
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void setUpPythonVenv() throws IOException {
+
+ final String pythonCommand = "source " + pathToPythonBinActivate.toAbsolutePath().toString()
+ + " && pip3 install httpx";
+
+ final String[] commands = new String[] { //
+ "bash", //
+ "-c", //
+ pythonCommand };
+
+ final Process process = new ProcessBuilder() //
+ .command(commands)
+ .directory(pathToTestDistributions.toAbsolutePath().toFile())
+ .redirectErrorStream(true)
+ .start();
+
+ logProcess(process, "Set up Python venv :");
+ }
+
+ public String getProcessOutput(@Nonnull final Process process, @Nullable final String prefix) throws IOException {
+ final StringBuffer output = new StringBuffer();
+ final BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+ String line = "";
+ while ((line = reader.readLine()) != null) {
+ log.debug("{} {}", prefix, line);
+ output.append(line + "\n");
+ }
+ return output.toString();
+ }
+
+ @Override
+ public void start() {
+ log.info("{} Starting ...", getLogPrefix());
+
+ container.start();
+
+ log.debug("{} Started container : '{}'", getLogPrefix(), getId());
+
+ log.debug("{} Waiting for \"/\" to be available ...", getLogPrefix());
+
+ // TODO does this work ?
+ container.waitingFor("httpd", Wait.forHttps("/"));
+
+ log.info("{} Started", getLogPrefix());
+ }
+
+ @Override
+ public void stop() {
+ log.debug("{} Stopping ...", getLogPrefix());
+ container.stop();
+ log.info("{} Stopped", getLogPrefix());
+ }
+
+ @Override
+ public boolean isRunning() {
+ boolean isRunning = container.getContainerByServiceName("httpd").get().isRunning();
+ log.info("{} Is running '{}'", getLogPrefix(), isRunning);
+ return isRunning;
+ }
+
+ /**
+ * Log output of process.
+ *
+ * @param process the process to be logged
+ * @param prefix the prefix of the message to be logged
+ * @throws IOException
+ */
+ public void logProcess(@Nonnull final Process process, @Nullable final String prefix) throws IOException {
+ final BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+ String line = "";
+ while ((line = reader.readLine()) != null) {
+ log.debug("{} {}", prefix, line);
+ }
+ }
+
+ public static void replaceFile(@Nonnull final Path pathToFile, @Nonnull @NotEmpty final String regex,
+ @Nonnull @NotEmpty final String replacement) throws IOException {
+ BaseIntegrationTest.replaceFile(pathToFile, regex, replacement);
+ }
+
+ /**
+ * Return a prefix for logging messages for this component.
+ *
+ * @return a string for insertion at the beginning of any log messages
+ */
+ @Nonnull
+ @NotEmpty
+ protected String getLogPrefix() {
+ if (logPrefix == null) {
+ logPrefix = "OIDF conformance suite :";
+ }
+ assert logPrefix != null;
+ return logPrefix;
+ }
+
+ protected void runTest(final String description, final String testPlan) throws IOException {
+
+ final String binActivate = pathToPythonBinActivate.toAbsolutePath().toString();
+
+ final String command = "source " + binActivate + " && " + testPlan;
+
+ log.debug("Run {} test using command : '{}'", description, command);
+
+ final String[] commands = new String[] { //
+ "bash", //
+ "-c", //
+ command };
+
+ final Process process = new ProcessBuilder() //
+ .command(commands)
+ .directory(pathToConformanceSuite.toAbsolutePath().toFile())
+ .redirectErrorStream(true)
+ .start();
+
+ final String output = getProcessOutput(process, "Run test :");
+
+ log.debug("Ran {} test using command : '{}'", description, command);
+
+ // final Path pathToSavedOutput =
+ // pathToConformanceSuite.resolve("basicCertificationProfileAuthorizationTest.log");
+ final String outputFileName = description.replaceAll(" ", "-") + ".log";
+
+ final Path pathToSavedOutput = pathToConformanceSuite.resolve(outputFileName);
+
+ log.debug("Save {} test output to '{}'", description, pathToSavedOutput);
+
+ Files.write(pathToSavedOutput, output.getBytes());
+
+ final boolean success = isSuccess(output);
+
+ if (!success) {
+ Assert.fail("Test failure : " + description + " see " + pathToSavedOutput);
+ }
+ }
+
+ protected boolean isSuccess(final String output) {
+
+ boolean success = true;
+
+ if (!output.contains("All tests ran to completion.")) {
+ success = false;
+ }
+
+ log.debug("test success = '{}'", success);
+
+ // Overall totals: ran 38 test modules. Conditions: 2065 successes, 0 failures,
+ // 0 warnings.
+ // Pattern pattern = Pattern.compile("\\d{2}-\\d{2}-\\d{4}");
+ final Pattern pattern = Pattern.compile(
+ "Overall totals: ran (\\d+) test modules. Conditions: (\\d+) successes, (\\d+) failures, (\\d+) warnings\\.");
+
+ final Matcher matcher = pattern.matcher(output);
+
+ Assert.assertTrue(matcher.find());
+
+ final String modules = matcher.group(1);
+ final String successes = matcher.group(2);
+ final String failures = matcher.group(3);
+ final String warnings = matcher.group(4);
+
+ log.debug("matcher 1 modules = '{}'", modules);
+ log.debug("matcher 2 successes = '{}'", successes);
+ log.debug("matcher 4 failures = '{}'", failures);
+ log.debug("matcher 3 warnings = '{}'", warnings);
+
+ if (successes.equals("0")) {
+ success = false;
+ }
+
+ if (!failures.equals("0")) {
+ success = false;
+ }
+
+ if (!warnings.equals("0")) {
+ success = false;
+ }
+
+ log.debug("test success = '{}'", success);
+
+ return success;
+ }
+
+}
diff --git a/src/test/java/net/shibboleth/idp/integration/tests/oidc/OPConformanceTest.java b/src/test/java/net/shibboleth/idp/integration/tests/oidc/OPConformanceTest.java
new file mode 100644
index 0000000..24dba59
--- /dev/null
+++ b/src/test/java/net/shibboleth/idp/integration/tests/oidc/OPConformanceTest.java
@@ -0,0 +1,310 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You 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 net.shibboleth.idp.integration.tests.oidc;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import javax.annotation.Nonnull;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import net.shibboleth.shared.component.ComponentInitializationException;
+
+/**
+ * Test the OIDC OP plugin against the OIDF Conformance Suite.
+ */
+public class OPConformanceTest extends AbstractOPTest {
+
+ /** Class logger. */
+ @Nonnull
+ private final Logger log = LoggerFactory.getLogger(OPConformanceTest.class);
+
+ /** OIDF Conformance Suite Docker container. */
+ @Nonnull
+ protected ConformanceSuiteContainer conformanceSuite;
+
+ /**
+ * Add eventId to error.vm view.
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void addEventIdToErrorVM() throws IOException {
+
+ final Path pathToErrorVM = Paths.get("views", "error.vm");
+
+ final String oldText = " <p>#evaluate\\(\\$message\\)</p>";
+
+ final String newText = " <p>eventId: \\$eventId</p>";
+
+ replaceIdPHomeFile(pathToErrorVM, oldText, oldText + "\n" + newText);
+ }
+
+ /**
+ * Change attribute-filter.xml to always release displayName.
+ *
+ * @throws IOException if an error occurs
+ */
+ protected void releaseDisplayNameWheneverRequested() throws IOException {
+
+ final Path pathToAttributeFilterXML = Paths.get("conf", "attribute-filter.xml");
+
+ final String oldText = //
+ " <AttributeRule attributeID=\"displayName\">\n" + //
+ " <PermitValueRule xsi:type=\"oidc:AttributeInOIDCRequestedClaims\" matchOnlyUserInfo=\"true\"\n\s*" + //
+ " onlyIfEssential=\"true\" />\n\s*" +
+ " </AttributeRule>";
+
+ final String newText = //
+ " <AttributeRule attributeID=\"displayName\">\n" + //
+ " <PermitValueRule xsi:type=\"oidc:AttributeInOIDCRequestedClaims\"\n" + //
+ " onlyIfEssential=\"true\" />\n" +
+ " </AttributeRule>";
+
+ replaceIdPHomeFile(pathToAttributeFilterXML, oldText, newText);
+ }
+
+ /**
+ * Add 'oidc/password' to supported authn principals.
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void configurePasswordACRValueForThePasswordFlow() throws IOException {
+
+ final Path pathToAuthnProperties = Paths.get("conf", "authn", "authn.properties");
+
+ final String oldText = //
+ "#idp.authn.Password.supportedPrincipals = \\\\\n" + //
+ "# saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport, \\\\\n" + //
+ "# saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:Password, \\\\\n" +
+ "# saml1/urn:oasis:names:tc:SAML:1.0:am:password";
+
+ final String newText = //
+ "idp.authn.Password.supportedPrincipals = \\\\\n" + //
+ " saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport, \\\\\n" + //
+ " saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:Password, \\\\\n" +
+ " saml1/urn:oasis:names:tc:SAML:1.0:am:password, \\\\\n" +
+ " oidc/password";
+
+ replaceIdPHomeFile(pathToAuthnProperties, oldText, oldText + "\n" + newText);
+ }
+
+ /**
+ * Add password 'acr_values_supported' to static/openid-configuration.json.
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void addACRValuesToOpenidConfiguration() throws IOException {
+
+ final Path pathToOpenIDConfiguration = Paths.get("static", "openid-configuration.json");
+
+ final String oldText = "\"frontchannel_logout_session_supported\":true\n";
+
+ final String newText = "\"frontchannel_logout_session_supported\":true,\n" +
+ " \"acr_values_supported\":[\"password\"]\n";
+
+ replaceIdPHomeFile(pathToOpenIDConfiguration, oldText, newText);
+ }
+
+ /**
+ * Set up OP for conformance suite.
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void setUpOPForConformanceSuite() throws IOException {
+
+ addEventIdToErrorVM();
+
+ releaseDisplayNameWheneverRequested();
+
+ configurePasswordACRValueForThePasswordFlow();
+
+ addACRValuesToOpenidConfiguration();
+
+ ignoreCertificateChecks();
+
+ enableDynamicClientRegistration();
+ }
+
+ /**
+ * Start the OP server.
+ *
+ * @throws Exception
+ * if an error occurs
+ */
+ @BeforeClass
+ protected void startOP() throws Exception {
+
+ final String[] plugins = new String[] { //
+ "net.shibboleth.oidc.common", //
+ "net.shibboleth.idp.plugin.oidc.config", //
+ "net.shibboleth.idp.plugin.oidc.op" };
+
+ installPlugins(plugins);
+
+ assertPluginsAreInstalled(plugins);
+
+ buildWAR();
+
+ enableOIDCCredentials();
+
+ enableOIDCAttributes();
+
+ createOIDCCredentials();
+
+ enableOIDCProfiles();
+
+ enableStaticClientRegistration();
+
+ copyStaticClientRegistrations();
+
+ enableOIDCDiscoveryIncludingPort();
+
+ enableOIDCDiscoveryRewrite();
+
+ setUpIdPAttributes();
+
+ setUpOPIssuerIncludingPort();
+
+ setUpOPForConformanceSuite();
+
+ startServer();
+
+ assertPluginsAreOnStatusPage(plugins);
+ }
+
+ /**
+ * Start the conformance suite.
+ *
+ * @throws IOException
+ * if an error occurs
+ * @throws ComponentInitializationException
+ * if container can not be set up
+ */
+ @BeforeClass(dependsOnMethods = { "startOP" })
+ protected void startConformanceSuite() throws IOException, ComponentInitializationException {
+
+ conformanceSuite = new ConformanceSuiteContainer();
+
+ conformanceSuite.setId("shib-tests-oidf-conformance-suite");
+
+ conformanceSuite.setOPHost(hostname);
+
+ conformanceSuite.setOPPort(securePort.toString());
+
+ conformanceSuite.setPathToPerTestDirectory(pathToPerTestDirectory);
+
+ conformanceSuite.initialize();
+
+ conformanceSuite.start();
+ }
+
+ /**
+ * Start browser before tests have run.
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ @BeforeClass(dependsOnMethods = { "startConformanceSuite" })
+ public void startBrowser() throws IOException {
+ setUpFirefoxDriver();
+ }
+
+ @Test
+ public void testBasicCertificationProfileAuthorization() throws Exception {
+
+ if (isWindows() || idpVersion.startsWith("4")) {
+ log.debug("Skipping OP conformance suite test, only runs IdP V5 on Linux with Jetty");
+ return;
+ }
+ final String description = "basic certification profile authorization test";
+
+ final String testPlan = //
+ "scripts/run-test-plan.py " + //
+ "--expected-skips-file skip-oidcc-idtoken-unsigned.json " + //
+ "'oidcc-basic-certification-test-plan[server_metadata=discovery][client_registration=dynamic_client]' " + //
+ "testop-config.json";
+
+ conformanceSuite.runTest(description, testPlan);
+ }
+
+ @Test
+ public void testConfigCertificationProfileAuthorization() throws Exception {
+
+ if (isWindows() || idpVersion.startsWith("4")) {
+ log.debug("Skipping OP conformance suite test, only runs IdP V5 on Linux with Jetty");
+ return;
+ }
+
+ final String description = "config certification profile authorization test";
+
+ final String testPlan = //
+ "scripts/run-test-plan.py --verbose " + //
+ "'oidcc-config-certification-test-plan' testop-config.json";
+
+ conformanceSuite.runTest(description, testPlan);
+ }
+
+ /**
+ * Do not stop browser after each test.
+ */
+ @Override
+ @AfterMethod(enabled = false)
+ public void stopBrowser() {
+ // do not stop browser after each test
+ }
+
+ /**
+ * Quit the web driver after all tests in class have run.
+ */
+ @AfterClass
+ public void stopBrowserAfterClass() {
+ log.debug("Stop browser after all tests in class have run");
+ super.stopBrowser();
+ }
+
+ /**
+ * Do not stop server after each test.
+ */
+ @Override
+ // @AfterMethod(dependsOnMethods = { "failTestClass", "stopBrowser" }, enabled = false)
+ @AfterMethod(enabled = false)
+ public void stopServer() {
+ // do not stop server after each test
+ }
+
+ /**
+ * Stop the server after all tests in class have run.
+ */
+ @AfterClass
+ public void stopServerAfterClass() {
+ log.debug("Stop server after all tests in class have run");
+ super.stopServer();
+ }
+
+}
diff --git a/src/test/oidc/conformance-suite/skip-oidcc-idtoken-unsigned.json b/src/test/oidc/conformance-suite/skip-oidcc-idtoken-unsigned.json
new file mode 100644
index 0000000..b32992a
--- /dev/null
+++ b/src/test/oidc/conformance-suite/skip-oidcc-idtoken-unsigned.json
@@ -0,0 +1,7 @@
+[
+ {
+ "test-name":"oidcc-idtoken-unsigned",
+ "configuration-filename":"*",
+ "variant":"*"
+ }
+]
diff --git a/src/test/oidc/conformance-suite/skip-oidcc-server-rotate-keys.json b/src/test/oidc/conformance-suite/skip-oidcc-server-rotate-keys.json
new file mode 100644
index 0000000..6943837
--- /dev/null
+++ b/src/test/oidc/conformance-suite/skip-oidcc-server-rotate-keys.json
@@ -0,0 +1,10 @@
+[
+ {
+ "test-name":"oidcc-server-rotate-keys",
+ "configuration-filename":"*",
+ "variant":"*",
+ "condition":"VerifyNewJwksHasNewSigningKey",
+ "current-block":"",
+ "expected-result":"failure"
+ }
+]
diff --git a/src/test/oidc/conformance-suite/testop-config-logout.json b/src/test/oidc/conformance-suite/testop-config-logout.json
new file mode 100644
index 0000000..84801f6
--- /dev/null
+++ b/src/test/oidc/conformance-suite/testop-config-logout.json
@@ -0,0 +1,1393 @@
+{
+ "description": "oidc-provider OIDC",
+ "server": {
+ "discoveryUrl": "https://testop.funet.fi/.well-known/openid-configuration"
+ },
+ "client": {
+ "client_name": "first-openid-client"
+ },
+ "client2": {
+ "client_name": "second-openid-client"
+ },
+ "browser": [
+ {
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Login",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "text",
+ "name",
+ "j_username",
+ "teppo",
+ "optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_password",
+ "testaaja",
+ "optional"
+ ],
+ [
+ "click",
+ "name",
+ "_eventId_proceed"
+ ]
+ ]
+ },
+ {
+ "task": "Consent",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "click",
+ "class",
+ "login-submit"
+ ]
+ ]
+ },
+ {
+ "task": "Verify Complete",
+ "match": "*/test/*",
+ "commands": [
+ [
+ "wait",
+ "id",
+ "submission_complete",
+ 10
+ ]
+ ]
+ }
+ ]
+ }
+ ],
+ "override": {
+ "oidcc-prompt-login": {
+ "browser": [
+ {
+ "comment": "updates placeholder during the second authorization",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Login",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "Forgot your password",
+ "update-image-placeholder-optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_username",
+ "teppo",
+ "optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_password",
+ "testaaja",
+ "optional"
+ ],
+ [
+ "click",
+ "name",
+ "_eventId_proceed"
+ ]
+ ]
+ },
+ {
+ "task": "Consent",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "click",
+ "class",
+ "login-submit"
+ ]
+ ]
+ },
+ {
+ "task": "Verify Complete",
+ "match": "*/test/*",
+ "commands": [
+ [
+ "wait",
+ "id",
+ "submission_complete",
+ 10
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-max-age-1": {
+ "browser": [
+ {
+ "comment": "updates placeholder during the second authorization",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Login",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "Forgot your password",
+ "update-image-placeholder-optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_username",
+ "teppo",
+ "optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_password",
+ "testaaja",
+ "optional"
+ ],
+ [
+ "click",
+ "name",
+ "_eventId_proceed"
+ ]
+ ]
+ },
+ {
+ "task": "Consent",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "click",
+ "class",
+ "login-submit"
+ ]
+ ]
+ },
+ {
+ "task": "Verify Complete",
+ "match": "*/test/*/callback*",
+ "commands": [
+ [
+ "wait",
+ "id",
+ "submission_complete",
+ 10
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-response-type-missing": {
+ "browser": [
+ {
+ "comment": "expect an immediate error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Expect redirect uri mismatch error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "UnableToDecode",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-ensure-request-without-nonce-fails": {
+ "browser": [
+ {
+ "comment": "expect an immediate error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Expect redirect uri mismatch error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "UnableToDecode",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-ensure-registered-redirect-uri": {
+ "browser": [
+ {
+ "comment": "expect an immediate error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Expect redirect uri mismatch error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "InvalidRedirectionURI",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-ensure-redirect-uri-in-authorization-request": {
+ "browser": [
+ {
+ "comment": "expect an immediate error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Expect redirect uri mismatch error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "UnableToDecode",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-redirect-uri-query-added": {
+ "browser": [
+ {
+ "comment": "expect an immediate error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Expect redirect uri mismatch error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "InvalidRedirectionURI",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-redirect-uri-query-mismatch": {
+ "browser": [
+ {
+ "comment": "expect an immediate error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Expect redirect uri mismatch error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "InvalidRedirectionURI",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-registration-logo-uri": {
+ "browser": [
+ {
+ "comment": "expect a login page with logo",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Expect a login page with logo",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "Forgot your password",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-registration-policy-uri": {
+ "browser": [
+ {
+ "comment": "expect a login page with policy document link",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Expect a login page with policy document link",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "Forgot your password",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-registration-tos-uri": {
+ "browser": [
+ {
+ "comment": "expect a login page with TOS document link",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Expect a login page with TOS document link",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "Forgot your password",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-rp-initiated-logout-bad-post-logout-redirect-uri": {
+ "browser": [
+ {
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Login",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "text",
+ "name",
+ "j_username",
+ "teppo",
+ "optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_password",
+ "testaaja",
+ "optional"
+ ],
+ [
+ "click",
+ "name",
+ "_eventId_proceed"
+ ]
+ ]
+ },
+ {
+ "task": "Consent",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "click",
+ "class",
+ "login-submit"
+ ]
+ ]
+ },
+ {
+ "task": "Verify Complete",
+ "match": "*/test/*/callback*",
+ "commands": [
+ [
+ "wait",
+ "id",
+ "submission_complete",
+ 10
+ ]
+ ]
+ }
+ ]
+ },
+ {
+ "comment": "expect an error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/end-session*",
+ "tasks": [
+ {
+ "task": "Expect a login page with TOS document link",
+ "match": "https://testop.funet.fi/idp/profile/oidc/end-session*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "InvalidRedirectionURI",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+
+ ]
+ },
+ "oidcc-rp-initiated-logout-modified-id-token-hint": {
+ "browser": [
+ {
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Login",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "text",
+ "name",
+ "j_username",
+ "teppo",
+ "optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_password",
+ "testaaja",
+ "optional"
+ ],
+ [
+ "click",
+ "name",
+ "_eventId_proceed"
+ ]
+ ]
+ },
+ {
+ "task": "Consent",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "click",
+ "class",
+ "login-submit"
+ ]
+ ]
+ },
+ {
+ "task": "Verify Complete",
+ "match": "*/test/*/callback*",
+ "commands": [
+ [
+ "wait",
+ "id",
+ "submission_complete",
+ 10
+ ]
+ ]
+ }
+ ]
+ },
+ {
+ "comment": "expect an error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/end-session*",
+ "tasks": [
+ {
+ "task": "Expect a login page with TOS document link",
+ "match": "https://testop.funet.fi/idp/profile/oidc/end-session*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "InvalidMessageContext",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+
+ ]
+ },
+ "oidcc-rp-initiated-logout-no-id-token-hint": {
+ "browser": [
+ {
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Login",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "text",
+ "name",
+ "j_username",
+ "teppo",
+ "optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_password",
+ "testaaja",
+ "optional"
+ ],
+ [
+ "click",
+ "name",
+ "_eventId_proceed"
+ ]
+ ]
+ },
+ {
+ "task": "Consent",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "click",
+ "class",
+ "login-submit"
+ ]
+ ]
+ },
+ {
+ "task": "Verify Complete",
+ "match": "*/test/*/callback*",
+ "commands": [
+ [
+ "wait",
+ "id",
+ "submission_complete",
+ 10
+ ]
+ ]
+ }
+ ]
+ },
+ {
+ "comment": "expect an error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/end-session*",
+ "tasks": [
+ {
+ "task": "Expect a login page with TOS document link",
+ "match": "https://testop.funet.fi/idp/profile/*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 15,
+ "Attempting to log out of the following services",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+
+ ]
+ }
+
+ ]
+ },
+ "oidcc-rp-initiated-logout-no-params": {
+ "browser": [
+ {
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Login",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "text",
+ "name",
+ "j_username",
+ "teppo",
+ "optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_password",
+ "testaaja",
+ "optional"
+ ],
+ [
+ "click",
+ "name",
+ "_eventId_proceed"
+ ]
+ ]
+ },
+ {
+ "task": "Consent",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "click",
+ "class",
+ "login-submit"
+ ]
+ ]
+ },
+ {
+ "task": "Verify Complete",
+ "match": "*/test/*/callback*",
+ "commands": [
+ [
+ "wait",
+ "id",
+ "submission_complete",
+ 10
+ ]
+ ]
+ }
+ ]
+ },
+ {
+ "comment": "expect an error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/end-session*",
+ "tasks": [
+ {
+ "task": "Expect a login page with TOS document link",
+ "match": "https://testop.funet.fi/idp/profile/*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 15,
+ "Attempting to log out of the following services",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+
+ ]
+ }
+
+ ]
+ },
+ "oidcc-rp-initiated-logout-no-post-logout-redirect-uri": {
+ "browser": [
+ {
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Login",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "text",
+ "name",
+ "j_username",
+ "teppo",
+ "optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_password",
+ "testaaja",
+ "optional"
+ ],
+ [
+ "click",
+ "name",
+ "_eventId_proceed"
+ ]
+ ]
+ },
+ {
+ "task": "Consent",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "click",
+ "class",
+ "login-submit"
+ ]
+ ]
+ },
+ {
+ "task": "Verify Complete",
+ "match": "*/test/*/callback*",
+ "commands": [
+ [
+ "wait",
+ "id",
+ "submission_complete",
+ 10
+ ]
+ ]
+ }
+ ]
+ },
+ {
+ "comment": "expect an error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/end-session*",
+ "tasks": [
+ {
+ "task": "Expect the logout page",
+ "match": "https://testop.funet.fi/idp/profile*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 15,
+ "The logout operation is complete",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+
+ ]
+ }
+
+ ]
+ },
+ "oidcc-rp-initiated-logout-only-state": {
+ "browser": [
+ {
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Login",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "text",
+ "name",
+ "j_username",
+ "teppo",
+ "optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_password",
+ "testaaja",
+ "optional"
+ ],
+ [
+ "click",
+ "name",
+ "_eventId_proceed"
+ ]
+ ]
+ },
+ {
+ "task": "Consent",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "click",
+ "class",
+ "login-submit"
+ ]
+ ]
+ },
+ {
+ "task": "Verify Complete",
+ "match": "*/test/*/callback*",
+ "commands": [
+ [
+ "wait",
+ "id",
+ "submission_complete",
+ 10
+ ]
+ ]
+ }
+ ]
+ },
+ {
+ "comment": "expect an error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/end-session*",
+ "tasks": [
+ {
+ "task": "Expect a login page with TOS document link",
+ "match": "https://testop.funet.fi/idp/profile/*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 15,
+ "Attempting to log out of the following services",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+
+ ]
+ }
+
+ ]
+ },
+ "oidcc-rp-initiated-logout-bad-id-token-hint": {
+ "browser": [
+ {
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Login",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "text",
+ "name",
+ "j_username",
+ "teppo",
+ "optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_password",
+ "testaaja",
+ "optional"
+ ],
+ [
+ "click",
+ "name",
+ "_eventId_proceed"
+ ]
+ ]
+ },
+ {
+ "task": "Consent",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "click",
+ "class",
+ "login-submit"
+ ]
+ ]
+ },
+ {
+ "task": "Verify Complete",
+ "match": "*/test/*/callback*",
+ "commands": [
+ [
+ "wait",
+ "id",
+ "submission_complete",
+ 10
+ ]
+ ]
+ }
+ ]
+ },
+ {
+ "comment": "expect an error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/end-session*",
+ "tasks": [
+ {
+ "task": "Expect a login page with TOS document link",
+ "match": "https://testop.funet.fi/idp/profile/*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 15,
+ "Unsupported Request",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+
+ ]
+ }
+
+ ]
+ },
+ "oidcc-rp-initiated-logout": {
+ "browser": [
+ {
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Login",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "text",
+ "name",
+ "j_username",
+ "teppo",
+ "optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_password",
+ "testaaja",
+ "optional"
+ ],
+ [
+ "click",
+ "name",
+ "_eventId_proceed"
+ ]
+ ]
+ },
+ {
+ "task": "Consent",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "click",
+ "class",
+ "login-submit"
+ ]
+ ]
+ },
+ {
+ "task": "Verify Complete 1",
+ "optional": true,
+ "match": "*/test/*/callback*",
+ "commands": [
+ [
+ "wait",
+ "id",
+ "submission_complete",
+ 10
+ ]
+ ]
+ }
+ ]
+ },
+ {
+ "comment": "expect an error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/end-session*",
+ "tasks": [
+ {
+ "task": "Verify Complete 4",
+ "match": "https://testop.funet.fi/idp/profile/oidc/end-session*",
+ "optional" : true,
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 18,
+ "Attempting to log out of the following services",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-frontchannel-rp-initiated-logout": {
+ "browser": [
+ {
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Login",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "text",
+ "name",
+ "j_username",
+ "teppo",
+ "optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_password",
+ "testaaja",
+ "optional"
+ ],
+ [
+ "click",
+ "name",
+ "_eventId_proceed"
+ ]
+ ]
+ },
+ {
+ "task": "Consent",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "click",
+ "class",
+ "login-submit"
+ ]
+ ]
+ },
+ {
+ "task": "Verify Complete 1",
+ "optional": true,
+ "match": "*/test/*/callback*",
+ "commands": [
+ [
+ "wait",
+ "id",
+ "submission_complete",
+ 10
+ ]
+ ]
+ }
+ ]
+ },
+ {
+ "comment": "expect an error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/end-session*",
+ "tasks": [
+ {
+ "task": "Verify Complete 4",
+ "match": "https://testop.funet.fi/idp/profile/oidc/end-session*",
+ "optional" : true,
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 18,
+ "Attempting to log out of the following services",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-backchannel-rp-initiated-logout": {
+ "browser": [
+ {
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Login",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "text",
+ "name",
+ "j_username",
+ "teppo",
+ "optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_password",
+ "testaaja",
+ "optional"
+ ],
+ [
+ "click",
+ "name",
+ "_eventId_proceed"
+ ]
+ ]
+ },
+ {
+ "task": "Consent",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "click",
+ "class",
+ "login-submit"
+ ]
+ ]
+ },
+ {
+ "task": "Verify Complete 1",
+ "optional": true,
+ "match": "*/test/*/callback*",
+ "commands": [
+ [
+ "wait",
+ "id",
+ "submission_complete",
+ 10
+ ]
+ ]
+ }
+ ]
+ },
+ {
+ "comment": "expect an error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/end-session*",
+ "tasks": [
+ {
+ "task": "Verify Complete 4",
+ "match": "https://testop.funet.fi/idp/profile/oidc/end-session*",
+ "optional" : true,
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 18,
+ "Attempting to log out of the following services",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-rp-initiated-logout-query-added-to-post-logout-redirect-uri": {
+ "browser": [
+ {
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Login",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "text",
+ "name",
+ "j_username",
+ "teppo",
+ "optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_password",
+ "testaaja",
+ "optional"
+ ],
+ [
+ "click",
+ "name",
+ "_eventId_proceed"
+ ]
+ ]
+ },
+ {
+ "task": "Consent",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "click",
+ "class",
+ "login-submit"
+ ]
+ ]
+ },
+ {
+ "task": "Verify Complete 1",
+ "optional": true,
+ "match": "*/test/*/callback*",
+ "commands": [
+ [
+ "wait",
+ "id",
+ "submission_complete",
+ 10
+ ]
+ ]
+ }
+ ]
+ },
+ {
+ "comment": "expect an immediate error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/end-session*",
+ "tasks": [
+ {
+ "task": "Expect redirect uri mismatch error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/end-session*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "InvalidRedirectionURI",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-rp-initiated-logout-no-state": {
+ "browser": [
+ {
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Login",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "text",
+ "name",
+ "j_username",
+ "teppo",
+ "optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_password",
+ "testaaja",
+ "optional"
+ ],
+ [
+ "click",
+ "name",
+ "_eventId_proceed"
+ ]
+ ]
+ },
+ {
+ "task": "Consent",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "click",
+ "class",
+ "login-submit"
+ ]
+ ]
+ },
+ {
+ "task": "Verify Complete 1",
+ "optional": true,
+ "match": "*/test/*/callback*",
+ "commands": [
+ [
+ "wait",
+ "id",
+ "submission_complete",
+ 10
+ ]
+ ]
+ }
+ ]
+ },
+ {
+ "comment": "expect an error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/end-session*",
+ "tasks": [
+ {
+ "task": "Verify Complete 4",
+ "match": "https://testop.funet.fi/idp/profile/oidc/end-session*",
+ "optional" : true,
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 18,
+ "Attempting to log out of the following services",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ }
+}
+
diff --git a/src/test/oidc/conformance-suite/testop-config.json b/src/test/oidc/conformance-suite/testop-config.json
new file mode 100644
index 0000000..494ed00
--- /dev/null
+++ b/src/test/oidc/conformance-suite/testop-config.json
@@ -0,0 +1,562 @@
+{
+ "description": "oidc-provider OIDC",
+ "server": {
+ "discoveryUrl": "https://testop.funet.fi/.well-known/openid-configuration"
+ },
+ "client": {
+ "client_name": "first-openid-client"
+ },
+ "client2": {
+ "client_name": "second-openid-client"
+ },
+ "browser": [
+ {
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Login",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "text",
+ "name",
+ "j_username",
+ "teppo",
+ "optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_password",
+ "testaaja",
+ "optional"
+ ],
+ [
+ "click",
+ "name",
+ "_eventId_proceed"
+ ]
+ ]
+ },
+ {
+ "task": "Consent",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "click",
+ "class",
+ "login-submit"
+ ]
+ ]
+ },
+ {
+ "task": "Verify Complete",
+ "match": "*/test/*/callback*",
+ "commands": [
+ [
+ "wait",
+ "id",
+ "submission_complete",
+ 10
+ ]
+ ]
+ }
+ ]
+ }
+ ],
+ "override": {
+ "oidcc-prompt-login": {
+ "browser": [
+ {
+ "comment": "updates placeholder during the second authorization",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Login",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "Forgot your password",
+ "update-image-placeholder-optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_username",
+ "teppo",
+ "optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_password",
+ "testaaja",
+ "optional"
+ ],
+ [
+ "click",
+ "name",
+ "_eventId_proceed"
+ ]
+ ]
+ },
+ {
+ "task": "Consent",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "click",
+ "class",
+ "login-submit"
+ ]
+ ]
+ },
+ {
+ "task": "Verify Complete",
+ "match": "*/test/*/callback*",
+ "commands": [
+ [
+ "wait",
+ "id",
+ "submission_complete",
+ 10
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-max-age-1": {
+ "browser": [
+ {
+ "comment": "updates placeholder during the second authorization",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Login",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "Forgot your password",
+ "update-image-placeholder-optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_username",
+ "teppo",
+ "optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_password",
+ "testaaja",
+ "optional"
+ ],
+ [
+ "click",
+ "name",
+ "_eventId_proceed"
+ ]
+ ]
+ },
+ {
+ "task": "Consent",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "click",
+ "class",
+ "login-submit"
+ ]
+ ]
+ },
+ {
+ "task": "Verify Complete",
+ "match": "*/test/*/callback*",
+ "commands": [
+ [
+ "wait",
+ "id",
+ "submission_complete",
+ 10
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-response-type-missing": {
+ "browser": [
+ {
+ "comment": "expect an immediate error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Expect redirect uri mismatch error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "UnableToDecode",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-ensure-request-without-nonce-fails": {
+ "browser": [
+ {
+ "comment": "expect an immediate error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Expect redirect uri mismatch error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "UnableToDecode",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-ensure-registered-redirect-uri": {
+ "browser": [
+ {
+ "comment": "expect an immediate error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Expect redirect uri mismatch error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "InvalidRedirectionURI",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-ensure-redirect-uri-in-authorization-request": {
+ "browser": [
+ {
+ "comment": "expect an immediate error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Expect redirect uri mismatch error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "UnableToDecode",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-redirect-uri-query-added": {
+ "browser": [
+ {
+ "comment": "expect an immediate error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Expect redirect uri mismatch error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "InvalidRedirectionURI",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-redirect-uri-query-mismatch": {
+ "browser": [
+ {
+ "comment": "expect an immediate error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Expect redirect uri mismatch error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "InvalidRedirectionURI",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-registration-logo-uri": {
+ "browser": [
+ {
+ "comment": "expect a login page with logo",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Expect a login page with logo",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "Forgot your password",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-registration-policy-uri": {
+ "browser": [
+ {
+ "comment": "expect a login page with policy document link",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Expect a login page with policy document link",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "Forgot your password",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-registration-tos-uri": {
+ "browser": [
+ {
+ "comment": "expect a login page with TOS document link",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Expect a login page with TOS document link",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "Forgot your password",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-rp-initiated-logout-bad-post-logout-redirect-uri": {
+ "browser": [
+ {
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Login",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "text",
+ "name",
+ "j_username",
+ "teppo",
+ "optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_password",
+ "testaaja",
+ "optional"
+ ],
+ [
+ "click",
+ "name",
+ "_eventId_proceed"
+ ]
+ ]
+ },
+ {
+ "task": "Consent",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "click",
+ "class",
+ "login-submit"
+ ]
+ ]
+ },
+ {
+ "task": "Verify Complete",
+ "match": "*/test/*/callback*",
+ "commands": [
+ [
+ "wait",
+ "id",
+ "submission_complete",
+ 10
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "oidcc-rp-initiated-logout-query-added-to-post-logout-redirect-uri": {
+ "browser": [
+ {
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Login",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "text",
+ "name",
+ "j_username",
+ "teppo",
+ "optional"
+ ],
+ [
+ "text",
+ "name",
+ "j_password",
+ "testaaja",
+ "optional"
+ ],
+ [
+ "click",
+ "name",
+ "_eventId_proceed"
+ ]
+ ]
+ },
+ {
+ "task": "Consent",
+ "optional": true,
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "commands": [
+ [
+ "click",
+ "class",
+ "login-submit"
+ ]
+ ]
+ },
+ {
+ "task": "Verify Complete",
+ "match": "*/test/*/callback*",
+ "commands": [
+ [
+ "wait",
+ "id",
+ "submission_complete",
+ 10
+ ]
+ ]
+ }
+ ]
+ },
+ {
+ "comment": "expect an immediate error page",
+ "match": "https://testop.funet.fi/idp/profile/oidc/authorize*",
+ "tasks": [
+ {
+ "task": "Expect error page",
+ "match": "https://oidcc-provider:3000/session/end*",
+ "commands": [
+ [
+ "wait",
+ "xpath",
+ "//*",
+ 10,
+ "post_logout_redirect_uri not registered",
+ "update-image-placeholder"
+ ]
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ }
+}
+
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list