[java-idp-integration-tests] branch main updated: Work on OIDC test
Tom Zeller
tzeller at dragonacea.biz
Thu Feb 22 23:58:22 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=7fa600e59ebec05428da9ca0c7e6b79f0d6c0bb0
The following commit(s) were added to refs/heads/main by this push:
new 7fa600e Work on OIDC test
7fa600e is described below
commit 7fa600e59ebec05428da9ca0c7e6b79f0d6c0bb0
Author: Tom Zeller <tzeller at dragonacea.biz>
AuthorDate: Thu Feb 22 17:58:06 2024 -0600
Work on OIDC test
Still disabled, but should work
---
pom.xml | 2 +-
src/test/docker/shib-tests-rp/Dockerfile | 3 +-
src/test/docker/shib-tests-rp/docker-compose.yml | 1 +
.../etc/httpd/conf.modules.d/10-auth_openidc.conf | 8 +-
.../idp/integration/tests/BaseIntegrationTest.java | 97 +++++
.../idp/integration/tests/oidc/OIDCTest.java | 481 ++++++++++++++++++++-
.../idp/integration/tests/oidc/RPContainer.java | 36 ++
src/test/oidc/jetty-base/etc/rewrite-rules.xml | 16 +
.../oidc/shibboleth-idp/metadata/oidc-client.json | 13 +
src/test/plugins/.gitignore | 2 +
10 files changed, 655 insertions(+), 4 deletions(-)
diff --git a/pom.xml b/pom.xml
index 2c32b68..c557918 100644
--- a/pom.xml
+++ b/pom.xml
@@ -449,7 +449,7 @@
</goals>
<configuration>
<!-- Run only if DNS system property is true -->
- <target if="DNS">
+ <target if="tests_cert">
<!-- Copy pfx file -->
<copy
file="${env.tests_pfx_filepath}"
diff --git a/src/test/docker/shib-tests-rp/Dockerfile b/src/test/docker/shib-tests-rp/Dockerfile
index ae73c08..ceff775 100644
--- a/src/test/docker/shib-tests-rp/Dockerfile
+++ b/src/test/docker/shib-tests-rp/Dockerfile
@@ -32,8 +32,9 @@ RUN sed -i -e 's/#ServerName www.example.com:443/ServerName ${ServerName}:443/'
# Copy demo web pages, non-secure displays "Hello world" while secure displays "Secure".
COPY var/www/html/index.html /var/www/html/index.html
-COPY var/www/html/secure/index.html /var/www/html/secureindex.html
+COPY var/www/html/secure/index.html /var/www/html/secure/index.html
COPY var/www/cgi-bin/printenv /var/www/cgi-bin/printenv
+RUN chmod ugo+x /var/www/cgi-bin/printenv
# Expose http and https ports.
EXPOSE 80 443
diff --git a/src/test/docker/shib-tests-rp/docker-compose.yml b/src/test/docker/shib-tests-rp/docker-compose.yml
index 2d50f1b..f593657 100644
--- a/src/test/docker/shib-tests-rp/docker-compose.yml
+++ b/src/test/docker/shib-tests-rp/docker-compose.yml
@@ -12,6 +12,7 @@ services:
build: .
environment:
- ServerName=${ServerName:-rp.tests.shibboleth.net}
+ - OIDCProviderMetadataURL=${OIDCProviderMetadataURL:-https://idp.tests.shibboleth.net:8443/.well-known/openid-configuration}
extra_hosts:
- "idp.tests.shibboleth.net:host-gateway"
ports:
diff --git a/src/test/docker/shib-tests-rp/etc/httpd/conf.modules.d/10-auth_openidc.conf b/src/test/docker/shib-tests-rp/etc/httpd/conf.modules.d/10-auth_openidc.conf
index 8c71e1b..2365614 100644
--- a/src/test/docker/shib-tests-rp/etc/httpd/conf.modules.d/10-auth_openidc.conf
+++ b/src/test/docker/shib-tests-rp/etc/httpd/conf.modules.d/10-auth_openidc.conf
@@ -1,7 +1,8 @@
# Test configuration for mod_auth_openidc RP
LoadModule auth_openidc_module modules/mod_auth_openidc.so
-OIDCProviderMetadataURL https://idp.tests.shibboleth.net:8443/.well-known/openid-configuration
+# OIDCProviderMetadataURL https://idp.tests.shibboleth.net:8443/.well-known/openid-configuration
+OIDCProviderMetadataURL ${OIDCProviderMetadataURL}
OIDCClientID test_oidc_rp
OIDCClientSecret topsecret
@@ -21,3 +22,8 @@ OIDCResponseType id_token
AuthType openid-connect
Require valid-user
</Location>
+
+<Location /cgi-bin/printenv>
+ AuthType openid-connect
+ Require valid-user
+</Location>
diff --git a/src/test/java/net/shibboleth/idp/integration/tests/BaseIntegrationTest.java b/src/test/java/net/shibboleth/idp/integration/tests/BaseIntegrationTest.java
index 95ac6ad..0702a20 100644
--- a/src/test/java/net/shibboleth/idp/integration/tests/BaseIntegrationTest.java
+++ b/src/test/java/net/shibboleth/idp/integration/tests/BaseIntegrationTest.java
@@ -3070,4 +3070,101 @@ public abstract class BaseIntegrationTest {
logProcess(process, "Remove plugin :");
}
+ /**
+ * Install plugin already downloaded to src/test/plugins.
+ *
+ * @param plugin
+ * the plugin id
+ * @param file
+ * the plugin distribution
+ * @throws IOException
+ * if an error occurs
+ */
+ public void installLocalPlugin(@Nonnull final String plugin, @Nonnull final String file) throws IOException {
+
+ // Path to the project build directory.
+ final Path buildPath = Paths.get(TEST_DISTRIBUTIONS_DIRECTORY);
+ assert buildPath.toAbsolutePath().toFile().exists() : "Path to build directory not found";
+
+ // Path to project directory
+ final Path project = buildPath.toAbsolutePath().toFile().getParentFile().toPath();
+ assert project.toAbsolutePath().toFile().exists() : "Path to project not found";
+
+ // Path to src/test/plugins
+ final Path pathToPlugins = project.resolve(Paths.get("src", "test", "plugins"));
+ assert pathToPlugins.toAbsolutePath().toFile().exists() : "Path to test plugins not found";
+
+ // Path to plugin
+ final Path pathToPlugin = pathToPlugins.resolve(file);
+ log.debug("Path to plugin '{}'", pathToPlugin.toAbsolutePath());
+ assert pathToPlugins.toAbsolutePath().toFile().exists() : "Path to plugin not found";
+
+ // Path to plugin truststore
+ final Path pathToTruststore = pathToTruststores.resolve(plugin).resolve("truststore.asc");
+ log.debug("Path to plugin truststore '{}'", pathToTruststore);
+ assert pathToTruststore.toAbsolutePath().toFile().exists() : "Path to plugin truststore not found";
+
+ final String truststore = pathToTruststore.toString();
+
+ final String[] commands = new String[] { //
+ pluginCLI, //
+ "--noRebuild", //
+ "--noPrompt", //
+ "--input", pathToPlugin.toString(), //
+ "--truststore ", truststore };
+
+ final Process process = new ProcessBuilder() //
+ .command(commands)
+ .directory(idpHome)
+ .start();
+
+ logProcess(process, "Install local plugin :");
+ }
+
+ /**
+ * Add module to Jetty.
+ *
+ * @param module
+ * the module to add
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void enableJettyModule(@Nonnull final String module) throws IOException {
+
+ // Path to Java, either idp.java.home or java.home system property
+ final String javaHome = System.getProperty("idp.java.home", System.getProperty("java.home"));
+
+ final Path pathToJava = Paths.get(javaHome, "bin", "java");
+
+ assert pathToJava.toFile().exists() : "Path to java not found";
+
+ final String javaCLI = pathToJava.toAbsolutePath().toString();
+
+ log.debug("Path to Java '{}'", javaCLI);
+
+ // Path to Jetty start.jar
+ final Path pathToStartJAR = pathToJettyHome.toAbsolutePath().resolve("start.jar");
+
+ assert pathToStartJAR.toFile().exists() : "Path to start.jar not found";
+
+ final String startCLI = pathToStartJAR.toAbsolutePath().toString();
+
+ log.debug("Path to start.jar '{}'", startCLI);
+
+ // Add module to Jetty
+ final String[] commands = new String[] { //
+ javaCLI, //
+ "-jar", //
+ startCLI, //
+ "--add-module=" + module };
+
+ final Process process = new ProcessBuilder() //
+ .command(commands)
+ .directory(pathToJettyBase.toAbsolutePath().toFile())
+ .redirectErrorStream(true)
+ .start();
+
+ logProcess(process, "Install Jetty '" + module + "' module :");
+ }
+
}
diff --git a/src/test/java/net/shibboleth/idp/integration/tests/oidc/OIDCTest.java b/src/test/java/net/shibboleth/idp/integration/tests/oidc/OIDCTest.java
index 4635372..6ed13cf 100644
--- a/src/test/java/net/shibboleth/idp/integration/tests/oidc/OIDCTest.java
+++ b/src/test/java/net/shibboleth/idp/integration/tests/oidc/OIDCTest.java
@@ -17,6 +17,12 @@
package net.shibboleth.idp.integration.tests.oidc;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -24,11 +30,13 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.containers.Container.ExecResult;
import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import net.shibboleth.idp.integration.tests.BaseIntegrationTest;
import net.shibboleth.idp.integration.tests.BrowserData;
+import net.shibboleth.shared.component.ComponentInitializationException;
// WIP
public class OIDCTest extends BaseIntegrationTest {
@@ -37,6 +45,14 @@ public class OIDCTest extends BaseIntegrationTest {
@Nonnull
private final Logger log = LoggerFactory.getLogger(OIDCTest.class);
+ /** CLI to generate keys. */
+ @Nullable
+ protected String jwtgenCLI;
+
+ /** RP Docker container. */
+ @Nullable
+ protected RPContainer rp = null;
+
@BeforeClass
public void setUpURLs() throws Exception {
@@ -44,6 +60,387 @@ public class OIDCTest extends BaseIntegrationTest {
}
+ /**
+ * Enable OIDC credentials.
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void enableOIDCCredentials() throws IOException {
+
+ final Path pathToCredentialsXML = pathToIdPHome.resolve(Paths.get("conf", "credentials.xml"));
+
+ assert pathToCredentialsXML.toAbsolutePath().toFile().exists() : "Path to credentials.xml not found";
+
+ final String oldText = "</beans>";
+
+ final StringBuilder newText = new StringBuilder();
+
+ newText.append("<!-- OIDC extension default credential definitions -->\n");
+
+ newText.append("<import resource=\"oidc-credentials.xml\" />\n");
+
+ newText.append(oldText + "\n");
+
+ replaceFile(pathToCredentialsXML, oldText, newText.toString());
+ }
+
+ /**
+ * Enable OIDC attributes / claim rules.
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void enableOIDCAttributes() throws IOException {
+
+ final Path pathToDefaultRulesXML = pathToIdPHome.resolve(Paths.get("conf", "attributes", "default-rules.xml"));
+
+ assert pathToDefaultRulesXML.toAbsolutePath().toFile().exists() : "Path to default-rules.xml not found";
+
+ final String oldText = "</beans>";
+
+ final StringBuilder newText = new StringBuilder();
+
+ newText.append(" <import resource=\"oidc-claim-rules.xml\" />\n");
+
+ newText.append(oldText + "\n");
+
+ replaceFile(pathToDefaultRulesXML, oldText, newText.toString());
+ }
+
+ /**
+ * Generate OIDC credentials.
+ *
+ * See : {@link #createOIDCCredentials1()} and {@link #createOIDCCredentials2()}
+ * and {@link #createOIDCCredentials3()}.
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void createOIDCCredentials() throws IOException {
+
+ final Path pathToJWTGen = pathToBin.resolve(isWindows() ? "jwtgen.bat" : "jwtgen.sh");
+
+ assert pathToJWTGen.toFile().exists() : "Path to jwtgen not found";
+
+ jwtgenCLI = pathToJWTGen.toAbsolutePath().toString();
+
+ createOIDCCredentials1();
+
+ createOIDCCredentials2();
+
+ createOIDCCredentials3();
+ }
+
+ /**
+ * Generate idp-signing-rs.jwk
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void createOIDCCredentials1() throws IOException {
+
+ final String[] commands = new String[] { //
+ jwtgenCLI, //
+ "--type", "RSA", //
+ "--size", "2048", //
+ "--usage", "sig", //
+ "--id", "defaultRSASign", //
+ "--output", "credentials/idp-signing-rs.jwk" };
+
+ final Process process = new ProcessBuilder() //
+ .command(commands)
+ .directory(idpHome)
+ .start();
+
+ logProcess(process, "Generate idp-signing-rs.jwk :");
+ }
+
+ /**
+ * Generate idp-signing-es.jwk
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void createOIDCCredentials2() throws IOException {
+
+ final String[] commands = new String[] { //
+ jwtgenCLI, //
+ "--type", "EC", //
+ "--curve", "P-256", //
+ "--usage", "sig", //
+ "--id", "defaultECSign", //
+ "--output", "credentials/idp-signing-es.jwk" };
+
+ final Process process = new ProcessBuilder() //
+ .command(commands)
+ .directory(idpHome)
+ .start();
+
+ logProcess(process, "Generate idp-signing-es.jwk :");
+ }
+
+ /**
+ * Generate idp-encryption-rsa.jwk
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void createOIDCCredentials3() throws IOException {
+
+ final String[] commands = new String[] { //
+ jwtgenCLI, //
+ "--type", "RSA", //
+ "--size", "2048", //
+ "--usage", "enc", //
+ "--id", "defaultRSAEnc", //
+ "--output", "credentials/idp-encryption-rsa.jwk" };
+
+ final Process process = new ProcessBuilder() //
+ .command(commands)
+ .directory(idpHome)
+ .start();
+
+ logProcess(process, "Generate idp-encryption-rsa.jwk :");
+ }
+
+ /**
+ * Add OIDC.Keyset and OIDC.Configuration to unverified relying party.
+ *
+ * Add default OIDC profiles to default relying party.
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void enableOIDCProfiles() throws IOException {
+
+ final Path pathToRelyingPartyXML = pathToIdPHome.resolve(Paths.get("conf", "relying-party.xml"));
+
+ assert pathToRelyingPartyXML.toAbsolutePath().toFile().exists() : "Path to relying-party.xml not found";
+
+ // Add <ref bean="OIDC.Keyset" /> to shibboleth.UnverifiedRelyingParty
+ // Add <ref bean="OIDC.Configuration" /> to shibboleth.UnverifiedRelyingParty
+
+ final String unverifiedRPText = "<!-- <bean parent=\"SAML2.SSO\" p:encryptAssertions=\"false\" /> -->";
+
+ final StringBuilder addToUnverified = new StringBuilder();
+ addToUnverified.append("<ref bean=\"OIDC.Keyset\" />\n");
+ addToUnverified.append("<ref bean=\"OIDC.Configuration\" />\n");
+
+ replaceFile(pathToRelyingPartyXML, unverifiedRPText, unverifiedRPText + "\n" + addToUnverified.toString());
+
+ // Add default OIDC profiles to default relying party
+
+ final String defaultRPText = "<ref bean=\"SAML2.ArtifactResolution\" />";
+
+ final StringBuilder addToDefault = new StringBuilder();
+ addToDefault.append("<ref bean=\"OIDC.SSO\" />\n");
+ addToDefault.append("<ref bean=\"OIDC.UserInfo\" />\n");
+ addToDefault.append("<ref bean=\"OAUTH2.Token\" />\n");
+ addToDefault.append("<ref bean=\"OAUTH2.Revocation\" />\n");
+ addToDefault.append("<ref bean=\"OAUTH2.Introspection\" />\n");
+
+ replaceFile(pathToRelyingPartyXML, defaultRPText, defaultRPText + "\n" + addToDefault.toString());
+ }
+
+ /**
+ * Enable client registration.
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void registerRP1() throws IOException {
+
+ final Path pathToOIDCClientInfoResolversXML = pathToIdPHome
+ .resolve(Paths.get("conf", "oidc-clientinfo-resolvers.xml"));
+
+ assert pathToOIDCClientInfoResolversXML.toFile().exists() : "Path to oidc-clientinfo-resolvers.xml not found";
+
+ // Uncomment ExampleFileResolver
+ final String toUncomment = "<bean id=\"ExampleFileResolver\" parent=\"shibboleth.oidc.FilesystemClientInformationResolver\"\\\n"
+ + " c:metadata=\"%\\{idp.home\\}/metadata/oidc-client.json\" />";
+
+ uncommentFile(pathToOIDCClientInfoResolversXML, toUncomment);
+
+ // Uncomment <ref bean="ExampleFileResolver" />
+ uncommentFile(pathToOIDCClientInfoResolversXML, "<ref bean=\"ExampleFileResolver\" />");
+ }
+
+ /**
+ * Register client by copying metadata/oidc-client.json.
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void registerRP2() throws IOException {
+
+ final Path pathToOIDCClientJSON = Paths.get("src", "test", "oidc", "shibboleth-idp", "metadata",
+ "oidc-client.json");
+
+ assert pathToOIDCClientJSON.toFile().exists() : "Path to oidc-client.json not found";
+
+ final Path destPath = pathToIdPHome.resolve(Paths.get("metadata", "oidc-client.json"));
+
+ Files.copy(pathToOIDCClientJSON, destPath, StandardCopyOption.REPLACE_EXISTING);
+ }
+
+ /**
+ * Set up static/openid-configuration.json.
+ *
+ * Set up dynamic publication by enabling the Jetty 'rewrite' module.
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ // TODO Jetty only
+ protected void enableOIDCDiscovery() 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 service_name with IdP's FQDN and port
+ final String serviceName = "idp.tests.shibboleth.net:" + securePort;
+
+ replaceFile(pathToOpenIDConfiguration, "\\{\\{ service_name \\}\\}", serviceName);
+
+ // Remove port from issuer URL
+ replaceFile(pathToOpenIDConfiguration, //
+ "\"issuer\":\"https://idp.tests.shibboleth.net:" + securePort + "\"", //
+ "\"issuer\":\"https://idp.tests.shibboleth.net\"");
+
+ enableJettyModule("rewrite");
+
+ final Path pathToSourceRewriteRulesXML = Paths.get("src", "test", "oidc", "jetty-base", "etc",
+ "rewrite-rules.xml");
+
+ assert pathToSourceRewriteRulesXML.toFile().exists() : "Path to rewrite-rules.xml not found";
+
+ final Path pathToTargetRewriteRulesXML = pathToJettyBase.resolve(Paths.get("etc", "rewrite-rules.xml"));
+
+ Files.copy(pathToSourceRewriteRulesXML, pathToTargetRewriteRulesXML, StandardCopyOption.REPLACE_EXISTING);
+ }
+
+ /**
+ * Use example OIDC attribute resolver and filter.
+ *
+ * @throws IOException
+ */
+ protected void setUpIdPAttributes() throws IOException {
+
+ Files.move( //
+ pathToIdPHome.resolve(Paths.get("conf", "examples", "oidc-attribute-resolver.xml")), //
+ pathToIdPHome.resolve(Paths.get("conf", "attribute-resolver.xml")), //
+ StandardCopyOption.REPLACE_EXISTING);
+
+ Files.move(//
+ pathToIdPHome.resolve(Paths.get("conf", "examples", "oidc-attribute-filter.xml")), //
+ pathToIdPHome.resolve(Paths.get("conf", "attribute-filter.xml")), //
+ StandardCopyOption.REPLACE_EXISTING);
+ }
+
+ /**
+ * Set the Open ID Connect issuer property.
+ *
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void setUpOPIssuer() 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");
+ }
+
+ /**
+ * Start RP.
+ *
+ * @throws ComponentInitializationException if an error occurs
+ */
+ protected void startRP() throws ComponentInitializationException {
+
+ rp = new RPContainer();
+
+ rp.setId("rp.tests.shibboleth.net");
+
+ rp.setOPPort(securePort.toString());
+
+ rp.initialize();
+
+ rp.start();
+ }
+
+ /**
+ * Update client port in their metadata.
+ *
+ * @param port
+ * the client port
+ * @throws IOException
+ * if an error occurs
+ */
+ protected void updateClientPort(@Nonnull final String port) throws IOException {
+ final Path pathToOIDCClientJSON = pathToIdPHome.resolve(Paths.get("metadata", "oidc-client.json"));
+
+ assert pathToOIDCClientJSON.toFile().exists() : "Path to oidc-client.json not found";
+
+ replaceFile(pathToOIDCClientJSON, "40443", port);
+ }
+
+ /**
+ * Get /.well-known/openid-configuration and verify that the issuer is correct.
+ */
+ protected void getOpenIDConfigurationFromBrowser() {
+
+ final String baseURL = "https://idp.tests.shibboleth.net:" + securePort;
+
+ final String openidConfigurationURL = baseURL + "/.well-known/openid-configuration";
+
+ log.debug("Attempting to get openid-configuration URL '{}'", openidConfigurationURL);
+
+ driver.get(openidConfigurationURL);
+
+ final String pageSource = getPageSource();
+
+ // TODO why quoted / ?
+ final String expectedIssuer = "\"issuer\":\"https:\\/\\/idp.tests.shibboleth.net\"";
+
+ Assert.assertTrue(pageSource.contains(expectedIssuer), "Expected issuer not found");
+ }
+
+ /**
+ * Get /.well-known/openid-configuration and verify that the issuer is correct.
+ *
+ * @throws InterruptedException
+ * @throws IOException
+ * @throws UnsupportedOperationException
+ */
+ protected void getOpenIDConfigurationFromContainer()
+ throws UnsupportedOperationException, IOException, InterruptedException {
+
+ final String baseURL = "https://idp.tests.shibboleth.net:" + securePort;
+
+ final String openidConfigurationURL = baseURL + "/.well-known/openid-configuration";
+
+ log.debug("Attempting to get openid-configuration URL '{}'", openidConfigurationURL);
+
+ final ExecResult result = rp.container.execInContainer( //
+ "curl", //
+ "-vvv", //
+ openidConfigurationURL);
+
+ final String response = result.getStdout();
+
+ log.debug("Response openid-configuration from container\n{}\n", response);
+
+ // TODO why quoted / ?
+ final String expectedIssuer = "\"issuer\":\"https:\\/\\/idp.tests.shibboleth.net\"";
+
+ Assert.assertTrue(response.contains(expectedIssuer), "Expected issuer not found");
+ }
+
@Test(dataProvider = "sauceOnDemandBrowserDataProvider", enabled = false)
public void testRP(@Nullable final BrowserData browserData) throws Exception {
@@ -83,10 +480,92 @@ public class OIDCTest extends BaseIntegrationTest {
final String pageSource = getPageSource();
log.debug("Print env from browser\n{}\n", pageSource);
-
+
Assert.assertTrue(pageSource.contains(expectedServerNameFromEnv), "Expected ServerName not found");
rp.stop();
}
+ @Test(dataProvider = "sauceOnDemandBrowserDataProvider", enabled = false)
+ public void testAuthn(@Nullable final BrowserData browserData) throws Exception {
+
+ // Install OIDC OP plugin
+
+ // TODO local install
+ installLocalPlugin("net.shibboleth.oidc.common", "oidc-common-dist-3.0.1.tar.gz");
+ installLocalPlugin("net.shibboleth.idp.plugin.oidc.config", "idp-plugin-oidc-config-dist-2.0.0.tar.gz");
+ installLocalPlugin("net.shibboleth.idp.plugin.oidc.op", "idp-plugin-oidc-op-distribution-4.0.0.tar.gz");
+
+ // TODO remote install
+ 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();
+
+ registerRP1();
+
+ registerRP2();
+
+ enableOIDCDiscovery();
+
+ setUpIdPAttributes();
+
+ setUpOPIssuer();
+
+ startRP();
+
+ updateClientPort(rp.httpsPort.toString());
+
+ startServer();
+
+ assertPluginsAreOnStatusPage(plugins);
+
+ secureBaseURL = "https://idp.tests.shibboleth.net:" + securePort;
+
+ startSeleniumClient(browserData);
+
+ getOpenIDConfigurationFromBrowser();
+
+ getOpenIDConfigurationFromContainer();
+
+ driver.get(rp.getBaseURL() + "/secure");
+
+ waitForLoginPage();
+
+ login();
+
+ waitForPageURLContains("/secure");
+
+ Assert.assertTrue(getPageSource().contains("Secure"));
+
+ driver.get(rp.getBaseURL() + "/cgi-bin/printenv");
+
+ Assert.assertTrue(getPageSource().contains("OIDC_CLAIM_iss=\"https://idp.tests.shibboleth.net\""));
+
+ // TODO more asserts
+ }
+
+ /**
+ * Stop the server.
+ */
+ @AfterMethod(dependsOnMethods = { "failTestClass" })
+ public void stopRP() {
+ if (rp != null && rp.isRunning()) {
+ rp.stop();
+ }
+ }
+
}
diff --git a/src/test/java/net/shibboleth/idp/integration/tests/oidc/RPContainer.java b/src/test/java/net/shibboleth/idp/integration/tests/oidc/RPContainer.java
index bf3030e..3baaaea 100644
--- a/src/test/java/net/shibboleth/idp/integration/tests/oidc/RPContainer.java
+++ b/src/test/java/net/shibboleth/idp/integration/tests/oidc/RPContainer.java
@@ -35,6 +35,7 @@ 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 an OpenID Connect Relying Party (RP) Docker container.
@@ -78,6 +79,10 @@ public class RPContainer extends AbstractIdentifiableInitializableComponent impl
@NonnullAfterInit
private Path pathToRP;
+ /** Port used by the OP. */
+ @NonnullAfterInit
+ private String opPort;
+
/** System property to set path to TLS cert. */
final static String pathToTLSCertSystemProperty = "tlsCert";
@@ -191,6 +196,8 @@ public class RPContainer extends AbstractIdentifiableInitializableComponent impl
*
* Set container name and hostname to id.
*
+ * Set OIDCProviderMetadataURL using OP port.
+ *
* Expose ports 80 and 443.
*
* {@inheritDoc}
@@ -200,6 +207,10 @@ public class RPContainer extends AbstractIdentifiableInitializableComponent impl
super.doInitialize();
+ if (opPort == null) {
+ throw new ComponentInitializationException("OP port cannot be null");
+ }
+
log.debug("{} Initializing", getLogPrefix());
// Do not delete image on exit
@@ -236,6 +247,11 @@ public class RPContainer extends AbstractIdentifiableInitializableComponent impl
// Set 'ServerName' environment variable to the id
container.withEnv("ServerName", getId());
+ // set OIDCProviderMetadataURL
+ final String OIDCProviderMetadataURL = //
+ "https://idp.tests.shibboleth.net:" + opPort + "/.well-known/openid-configuration";
+ container.withEnv("OIDCProviderMetadataURL", OIDCProviderMetadataURL);
+
// Expose ports 80 and 443
container.addExposedPort(80);
container.addExposedPort(443);
@@ -243,6 +259,15 @@ public class RPContainer extends AbstractIdentifiableInitializableComponent impl
log.debug("{} Initialized", getLogPrefix());
}
+ /**
+ * Get base URL of the form "https://rp.tests.shibboleth.net:<port>".
+ *
+ * @return base URL
+ */
+ public String getBaseURL() {
+ return "https://rp.tests.shibboleth.net:" + httpsPort.toString();
+ }
+
/**
* Return a prefix for logging messages for this component.
*
@@ -258,6 +283,17 @@ public class RPContainer extends AbstractIdentifiableInitializableComponent impl
return logPrefix;
}
+ /**
+ * Set the OP port used to construct the OIDCProviderMetadataURL.
+ *
+ * @param port
+ * OP port
+ */
+ public void setOPPort(@Nonnull final String port) {
+ Constraint.isNotNull(port, "OP port cannot be null");
+ opPort = port;
+ }
+
/**
* Start container and wait for web server to be available.
*
diff --git a/src/test/oidc/jetty-base/etc/rewrite-rules.xml b/src/test/oidc/jetty-base/etc/rewrite-rules.xml
new file mode 100644
index 0000000..bcaf376
--- /dev/null
+++ b/src/test/oidc/jetty-base/etc/rewrite-rules.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
+<Configure id="Rewrite" class="org.eclipse.jetty.rewrite.handler.RuleContainer">
+
+ <!-- OIDC Discovery -->
+ <Call name="addRule">
+ <Arg>
+ <New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
+ <Set name="pattern">/.well-known/openid-configuration</Set>
+ <Set name="replacement">/idp/profile/oidc/configuration</Set>
+ </New>
+ </Arg>
+ </Call>
+
+</Configure>
+
diff --git a/src/test/oidc/shibboleth-idp/metadata/oidc-client.json b/src/test/oidc/shibboleth-idp/metadata/oidc-client.json
new file mode 100644
index 0000000..996fd9c
--- /dev/null
+++ b/src/test/oidc/shibboleth-idp/metadata/oidc-client.json
@@ -0,0 +1,13 @@
+[
+ {
+ "scope": "openid email",
+ "redirect_uris": [ "https://rp.tests.shibboleth.net:40443/redirect_uri" ],
+ "client_id": "test_oidc_rp",
+ "client_secret": "topsecret",
+ "response_types": [
+ "code",
+ "id_token",
+ "id_token token"
+ ]
+ }
+]
diff --git a/src/test/plugins/.gitignore b/src/test/plugins/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/src/test/plugins/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list