[java-idp-plugin-oidc-rp] branch main updated: Flesh out a flow, integrate with new commons metadata provider

Phil Smart philip.smart at jisc.ac.uk
Fri Oct 15 07:38:58 UTC 2021


This is an automated email from the git hooks/post-receive script.

philsmart pushed a commit to branch main
in repository java-idp-plugin-oidc-rp.

View the commit online:
http://git.shibboleth.net/view/?p=java-idp-plugin-oidc-rp.git;a=commit;h=b9b2af53b28190d1963ee9f9196a9bef1d4cb2d9

The following commit(s) were added to refs/heads/main by this push:
     new b9b2af5  Flesh out a flow, integrate with new commons metadata provider
b9b2af5 is described below

commit b9b2af53b28190d1963ee9f9196a9bef1d4cb2d9
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Fri Oct 15 08:38:55 2021 +0100

    Flesh out a flow, integrate with new commons metadata provider
---
 idp-oidc-rp-impl/pom.xml                           |  68 ++++-
 .../idp/plugin/authn/oidc/rp/OIDCRPModule.java     |   1 +
 .../oidc/rp/impl/AuthorizationController.java      |  28 +-
 .../authn/oidc/rp/impl/SetOIDCInformation.java     |   7 +-
 .../impl/DefaultIssuerIDLookupFunction.java        |  30 +++
 .../impl/OIDCProviderMetadataLookupHandler.java    | 106 ++++++++
 .../META-INF/net.shibboleth.idp/postconfig.xml     |  47 +++-
 ...eans.xml => oidc-relying-party-authn-beans.xml} |  78 +++++-
 .../oidc-relying-party-authn-flow.xml              | 111 ++++++++
 .../OIDCRelyingParty/oidc-relying-party-flow.xml   |  55 ----
 .../authn/providermetadata-resolver-system.xml     |  69 +++++
 .../plugin/authn/oidc/rp/impl/OIDCRPFlowTest.java  | 203 +++++++++++++++
 .../conf/authn/oidc-providermetadata-resolvers.xml |  29 +++
 .../src/test/resources/logback-test.xml            |  19 ++
 .../resources/metadata/openid-configuration.json   |  55 ++++
 pom.xml                                            | 285 +++++++++++----------
 16 files changed, 980 insertions(+), 211 deletions(-)

diff --git a/idp-oidc-rp-impl/pom.xml b/idp-oidc-rp-impl/pom.xml
index 21c33e4..55f433a 100644
--- a/idp-oidc-rp-impl/pom.xml
+++ b/idp-oidc-rp-impl/pom.xml
@@ -9,28 +9,33 @@
     </parent>
 
     <artifactId>idp-plugin-oidc-rp-impl</artifactId>
-    <packaging>jar</packaging>    
+    <packaging>jar</packaging>
     <name>Shibboleth IdP :: Plugins :: OIDC RP Login Flow Impl</name>
     <description>IdP java-idp-oidc-rp plugin implementation.</description>
-    
+
     <properties>
         <checkstyle.configLocation>${project.basedir}/../checkstyle.xml</checkstyle.configLocation>
         <automatic.module.name>net.shibboleth.idp.plugin.authn.oidc.rp.impl</automatic.module.name>
     </properties>
-    
+
     <dependencies>
-        
-         <!-- compile time intra project dependencies -->
+
+        <!-- compile time intra project dependencies -->
         <dependency>
             <groupId>net.shibboleth.idp.plugin.authn</groupId>
             <artifactId>idp-plugin-oidc-rp-api</artifactId>
         </dependency>
-         <!-- provided dependencies -->
-         <dependency>
+        <!-- provided dependencies -->
+        <dependency>
             <groupId>com.nimbusds</groupId>
             <artifactId>oauth2-oidc-sdk</artifactId>
             <scope>provided</scope>
-        </dependency>    
+        </dependency>
+         <dependency>
+            <groupId>${slf4j.groupId}</groupId>
+            <artifactId>jcl-over-slf4j</artifactId>
+            <scope>provided</scope>
+        </dependency>
         <dependency>
             <groupId>com.google.code.findbugs</groupId>
             <artifactId>jsr305</artifactId>
@@ -46,7 +51,7 @@
             <artifactId>httpcore</artifactId>
             <scope>provided</scope>
         </dependency>
-         <dependency>
+        <dependency>
             <groupId>com.nimbusds</groupId>
             <artifactId>nimbus-jose-jwt</artifactId>
             <scope>provided</scope>
@@ -60,12 +65,31 @@
             <groupId>net.shibboleth.oidc</groupId>
             <artifactId>oidc-common-crypto-api</artifactId>
             <scope>provided</scope>
+        </dependency>
+         <dependency>
+            <groupId>net.shibboleth.oidc</groupId>
+            <artifactId>oidc-common-metadata-impl</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>net.shibboleth.oidc</groupId>
+            <artifactId>oidc-common-metadata-api</artifactId>
+            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>javax.servlet</groupId>
             <artifactId>javax.servlet-api</artifactId>
             <scope>provided</scope>
         </dependency>
+        <!-- Tmp OP deps until things move to commons -->
+        <!-- <dependency>
+            <groupId>net.shibboleth.idp.plugin.oidc</groupId>
+            <artifactId>idp-plugin-oidc-op-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.shibboleth.idp.plugin.oidc</groupId>
+            <artifactId>idp-plugin-oidc-op-impl</artifactId>
+        </dependency> -->
         <!-- Service API and Plugin Description dependency -->
         <dependency>
             <groupId>${idp.groupId}</groupId>
@@ -76,11 +100,33 @@
             <groupId>${idp.groupId}</groupId>
             <artifactId>idp-admin-impl</artifactId>
             <scope>provided</scope>
-        </dependency>    
+        </dependency>
+        <!-- Test dependency -->
+        <dependency>
+            <groupId>net.shibboleth.idp.plugin.authn.test</groupId>
+            <artifactId>idp-webflow-execution-test</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+            <type>test-jar</type>
+        </dependency>
+        <dependency>
+            <groupId>${spring.groupId}</groupId>
+            <artifactId>spring-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>net.shibboleth.idp</groupId>
+            <artifactId>idp-conf</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>net.shibboleth.idp</groupId>
+            <artifactId>idp-conf-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
-        <plugins>            
+        <plugins>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-jar-plugin</artifactId>
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/OIDCRPModule.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/OIDCRPModule.java
index ecff9a9..90397e7 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/OIDCRPModule.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/OIDCRPModule.java
@@ -2,6 +2,7 @@ package net.shibboleth.idp.plugin.authn.oidc.rp;
 
 import java.io.IOException;
 
+import net.shibboleth.idp.module.IdPModule;
 import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.impl.PluginIdPModule;
 
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AuthorizationController.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AuthorizationController.java
index bb9fd43..49fcd41 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AuthorizationController.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AuthorizationController.java
@@ -53,9 +53,9 @@ import net.shibboleth.utilities.java.support.primitive.StringSupport;
  * <p>Adds the {@link OpenIDConnectContext} to the {@link HttpSession} for extraction after the OAuth 2.0 
  * authorisation code response has been consumed, and control as returned to the IdP.</p>
  * 
- * <p>Servlet compatible with the @link {@link ExternalAuthentication} interface that consumes the HTTP Request from 
+ * <p>Servlet also consumes the HTTP Request from 
  * an OpenID Connect provider (OAuth 2.0 authorization endpoint), which was issued in response to the Authorization 
- * Code request made by the {@link OpenIDConnectStartServlet}. </p>
+ * Code request. </p>
  * <p>
  * The {@link HttpServletRequest} is placed inside the {@link OpenIDConnectContext} for interrogation later in the flow.
  * </p>
@@ -84,6 +84,17 @@ public class AuthorizationController {
     @Nonnull private final Logger log = LoggerFactory.getLogger(AuthorizationController.class);
 
 
+    /**
+     * Begin an authorization request to the configured OP. 
+     * 
+     * TODO FINISH
+     * 
+     * @param httpRequest the servlet request.
+     * @param httpResponse the servlet response.
+     * 
+     * @throws ServletException throw if there is an error constructing an authz request.      
+     * @throws IOException throw if there is an error constructing an authz request.
+     */
     @GetMapping("/auth")
     public void authorizationRequest(@Nonnull final HttpServletRequest httpRequest, 
             @Nonnull final HttpServletResponse httpResponse) throws ServletException, IOException {
@@ -98,12 +109,12 @@ public class AuthorizationController {
                 throw new ExternalAuthenticationException("Could not access profileRequestContext from the request");
             }
             final AuthenticationContext authenticationContext =
-                    (AuthenticationContext) profileRequestContext.getSubcontext(AuthenticationContext.class);
+                    profileRequestContext.getSubcontext(AuthenticationContext.class);
             if (authenticationContext == null) {
                 throw new ExternalAuthenticationException("Could not get AuthenticationContext from the request");
             }
             final OpenIDConnectContext openIDConnectContext =
-                    (OpenIDConnectContext) authenticationContext
+                     authenticationContext
                             .getSubcontext(OpenIDConnectContext.class);
             if (openIDConnectContext == null) {
                 throw new ExternalAuthenticationException(
@@ -120,6 +131,15 @@ public class AuthorizationController {
        
     }
     
+    /**
+     * Callback endpoint to accept the authorization request response.
+     * 
+     * @param httpRequest the servlet request.
+     * @param httpResponse the servlet response.
+     * 
+     * @throws ServletException throw if there is an error accepting the authz response.      
+     * @throws IOException throw if there is an error accepting the authz response.
+     */
     @GetMapping("/callback")
     public void authorizationCallback(@Nonnull final HttpServletRequest httpRequest,
             @Nonnull final HttpServletResponse httpResponse) throws ServletException, IOException {
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/SetOIDCInformation.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/SetOIDCInformation.java
index 7f10122..021e46a 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/SetOIDCInformation.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/SetOIDCInformation.java
@@ -193,7 +193,7 @@ public class SetOIDCInformation extends AbstractAuthenticationAction {
      * is set, the JWT will also be signed.
      *
      * <p>The key of the mapping is the name of the requested claim. The value of the requested claim
-     * is either:
+     * is either:</p>
      * <ul>
      * <li>Null, if the claim is being requested in a default manor</li>
      * <li><code>{"essential":true}</code> if the value is essential. The default is
@@ -201,10 +201,11 @@ public class SetOIDCInformation extends AbstractAuthenticationAction {
      * <li>A specific value for the claim. This value must be a valid value for that claim.</li>
      * <li>A specific set of values for the claim. These values must be valid value for that claim.</li>
      * </ul>
-     * </p>
+     * 
      * <p>
      * If used, the OpenID Connect Provider must support it, as specified in the
      * <code>request_parameter_supported</code> parameter of the Providers discovery metadata.
+     * </p>
      *
      * @param claims map of requested claims
      */
@@ -301,7 +302,7 @@ public class SetOIDCInformation extends AbstractAuthenticationAction {
     }
 
     /**
-     * Setter for OpenId Scope values. New ones are be added to the {@value OIDCScopeValue#OPENID} scope.
+     * Setter for OpenId Scope values. New ones are be added to the {@code OIDCScopeValue#OPENID} scope.
      *
      * @param oidcScopes OpenID Connect Scope values, can be <code>null</code> and will be ignored.
      */
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/metadata/impl/DefaultIssuerIDLookupFunction.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/metadata/impl/DefaultIssuerIDLookupFunction.java
new file mode 100644
index 0000000..8791c87
--- /dev/null
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/metadata/impl/DefaultIssuerIDLookupFunction.java
@@ -0,0 +1,30 @@
+package net.shibboleth.idp.plugin.authn.oidc.rp.metadata.impl;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.context.navigate.ContextDataLookupFunction;
+import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext;
+
+/**
+ * Strategy to pull out the ID of the OIDC proxy issuer/provider.
+ */
+//TODO is this where the OP ID should be? confusing
+//TODO should resolve a Nimbus issuer?
+ at ThreadSafe
+public class DefaultIssuerIDLookupFunction implements ContextDataLookupFunction<MessageContext, String> {
+
+    /** {@inheritDoc} */
+    @Nullable public String apply(@Nullable final MessageContext input) {
+        if (input == null) {
+            return null;
+        }
+        
+        final SAMLPeerEntityContext context = input.getSubcontext(SAMLPeerEntityContext.class);
+        if (context == null) {
+            return null;
+        }
+        return context.getEntityId();
+    }
+}
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/metadata/impl/OIDCProviderMetadataLookupHandler.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/metadata/impl/OIDCProviderMetadataLookupHandler.java
new file mode 100644
index 0000000..369fbfa
--- /dev/null
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/metadata/impl/OIDCProviderMetadataLookupHandler.java
@@ -0,0 +1,106 @@
+package net.shibboleth.idp.plugin.authn.oidc.rp.metadata.impl;
+
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.handler.AbstractMessageHandler;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.nimbusds.oauth2.sdk.id.Issuer;
+import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
+
+import net.shibboleth.oidc.metadata.ProviderMetadataResolver;
+import net.shibboleth.oidc.metadata.criterion.IssuerIDCriterion;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+
+
+/**
+ * Handler for inbound OIDC protocol messages that attempts to locate OIDC metadata for a OP (issuer), and attaches it with a
+ * {@link OIDCMetadataContext} as a child of a pre-existing instance of {@link MessageContext}.
+ */
+//TODO should this be conflated with the OIDCMetadataLookupHandler service
+public class OIDCProviderMetadataLookupHandler extends AbstractMessageHandler {
+    
+    /** Logger. */
+    @Nonnull private final Logger log = LoggerFactory.getLogger(OIDCProviderMetadataLookupHandler.class);
+    
+    /** Resolver used to look up OIDC client information. */
+    @NonnullAfterInit private ProviderMetadataResolver providerResolver;
+    
+    /** Strategy used to obtain the issuer id value for the inbound message context. */
+    @Nonnull  private Function<MessageContext,String> issuerIDLookupStrategy;
+    
+    /**
+     * Constructor.
+     */
+    public OIDCProviderMetadataLookupHandler() {
+        issuerIDLookupStrategy = new DefaultIssuerIDLookupFunction();
+    }
+    
+    /**
+     * Set the strategy used to locate the client id of the request.
+     * 
+     * @param strategy lookup strategy
+     */
+    public void setIssuerIDLookupStrategy(@Nonnull final Function<MessageContext, String> strategy) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        issuerIDLookupStrategy =
+                Constraint.isNotNull(strategy, "IssuerIDLookupStrategy lookup strategy cannot be null");
+    }
+    
+    /**
+    * Set the {@link ProviderMetadataResolver} to use.
+    * 
+    * @param resolver The resolver to use.
+    */
+   public void setProviderMetadataResolver(@Nonnull final ProviderMetadataResolver resolver) {
+       ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+       providerResolver = Constraint.isNotNull(resolver, "IssuerMetadataResolver cannot be null");
+   }
+   
+   /** {@inheritDoc} */
+   @Override
+   protected void doInitialize() throws ComponentInitializationException {
+       super.doInitialize();
+
+       if (providerResolver == null) {
+           throw new ComponentInitializationException("IssuerMetadataResolver cannot be null");
+       }
+   }
+
+    @Override
+    protected void doInvoke(MessageContext messageContext) throws MessageHandlerException {
+        ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
+        
+        // Resolve issuer id from inbound message
+        //TODO should resolve an Issuer directly here?
+        final String issuerId = issuerIDLookupStrategy.apply(messageContext);
+        
+        final IssuerIDCriterion issuerCriterion = new IssuerIDCriterion(new Issuer(issuerId));
+        final CriteriaSet criteria = new CriteriaSet(issuerCriterion);
+        try {
+            final OIDCProviderMetadata issuerMetadata = providerResolver.resolveSingle(criteria);
+            if (issuerMetadata == null) {
+                log.debug("{} No provider metadata returned for {}",getLogPrefix(), issuerId);
+                return;
+            }
+            log.debug("{} Found provider metadata for '{}'", getLogPrefix(), issuerId);
+//            final OIDCMetadataContext oidcCtx = new OIDCMetadataContext();
+//            oidcCtx.setClientInformation(clientInformation);
+//            messageContext.addSubcontext(oidcCtx);
+        } catch (final ResolverException e) {
+            log.error("{} ResolverException thrown during provider metadata lookup", getLogPrefix(), e);
+        }
+    }
+
+}
diff --git a/idp-oidc-rp-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml b/idp-oidc-rp-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
index 6bf6aee..883d26d 100644
--- a/idp-oidc-rp-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
+++ b/idp-oidc-rp-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
@@ -40,9 +40,54 @@
                 c:_0="#{'%{idp.authn.OIDC.RP.supportedPrincipals:}'.trim()}" />
         </property>
     </bean>
+   
     
     <!-- Controller implementation -->
-    <bean id="shibboleth.OpenIDConnectStartServlet"
+    <bean id="shibboleth.oidc.rp.OpenIDConnectStartServlet"
         class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.AuthorizationController" />
+       
+    <!-- TODO these bean names need to change - otherwise they may class with the OP plugin if installed
+    at the same time -->
+      
+    <!-- OIDC OP information resolver service beans. -->
+    
+    <bean id="shibboleth.oidc.rp.ProviderMetadataResolver"
+        class="net.shibboleth.oidc.metadata.impl.ReloadingProviderMetadataProvider"
+        c:resolverService-ref="shibboleth.oidc.rp.ProviderMetadataResolverService" />
+    
+   <!--  TODO add this back? depends-on="shibboleth.AttributeResolverService"-->
+
+    <bean id="shibboleth.oidc.rp.ProviderMetadataResolverService"
+        class="net.shibboleth.ext.spring.service.ReloadableSpringService"
+     
+        p:serviceConfigurations-ref="ExtendedProviderMetadataResolverResources"
+        p:failFast="%{idp.service.providermetadata.failFast:%{idp.service.failFast:false}}"
+        p:reloadCheckDelay="%{idp.service.providermetadata.checkInterval:PT0S}"
+        p:beanPostProcessors-ref="shibboleth.IdentifiableBeanPostProcessor"
+        p:beanFactoryPostProcessors-ref="shibboleth.PropertySourcesPlaceholderConfigurer">
+        <constructor-arg name="claz"
+            value="net.shibboleth.oidc.metadata.ProviderMetadataResolver" />
+        <constructor-arg name="strategy">
+            <bean class="net.shibboleth.oidc.profile.spring.relyingparty.metadata.impl.ProviderMetadataResolverServiceStrategy" />
+        </constructor-arg>
+    </bean>
+    <!-- TODO ADD BACK THE CONDITION (GET TO WORK WITH TEST) <util:list id="shibboleth.DefaultProviderMetadataResolverResources">
+        <value>conditional:%{idp.home}/conf/oidc-providermetadata-resolvers.xml</value>
+        OR <value>classpath:/conf/oidc-providermetadata-resolvers.xml</value>
+    </util:list> -->
+    <util:list id="shibboleth.DefaultProviderMetadataResolverResources">
+        <value>%{idp.home}/conf/authn/oidc-providermetadata-resolvers.xml</value>
+    </util:list>
+    <!-- Auto-append system config file to resource set. -->
+    <bean id ="ExtendedProviderMetadataResolverResources" class="net.shibboleth.ext.spring.factory.CombiningListFactoryBean"
+            p:firstList="#{getObject('%{idp.service.providermetadata.resources:shibboleth.ProviderMetadataResolverResources}'.trim()) ?:
+                getObject('shibboleth.DefaultProviderMetadataResolverResources')}">
+        <property name="secondList">
+            <util:list >
+                <value>classpath:/net/shibboleth/idp/plugin/authn/oidc/rp/conf/authn/providermetadata-resolver-system.xml</value>
+            </util:list>
+        </property>
+    </bean>
+        
   
 </beans>
\ No newline at end of file
diff --git a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-beans.xml b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-beans.xml
similarity index 71%
rename from idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-beans.xml
rename to idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-beans.xml
index 953fd9d..29e4eaa 100644
--- a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-beans.xml
+++ b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-beans.xml
@@ -18,11 +18,83 @@
     <bean class="net.shibboleth.ext.spring.config.IdentifiableBeanPostProcessor" />
     <bean class="net.shibboleth.idp.profile.impl.ProfileActionBeanPostProcessor" />
     
+    
+    <!-- Initial discovery step -->
+    <bean id="PropertyDrivenDiscovery" parent="shibboleth.Functions.Constant"
+        c:target="#{'%{idp.authn.oidc.rp.proxyIssuer:}'.trim()}" />  
+    
+    
+    
     <!-- Spring controller to start the authentication request and recieve the response -->
     <bean id="shibboleth.authn.OpenIDConnect.externalAuthnPath" class="java.lang.String"
         c:_0="servletRelative:/Authn/OIDC/RP/auth">
     </bean>
     
+
+        
+        
+   <!-- Parent beans for indirecting into nested PRC. -->
+    
+    <bean id="NestedWebFlowMessageHandlerAdaptor" abstract="true"
+        class="net.shibboleth.idp.profile.impl.WebFlowMessageHandlerAdaptor" scope="prototype"
+        p:profileContextLookupStrategy-ref="shibboleth.ChildLookup.ProxyProfileRequestContext" />
+
+    <bean id="NestedWebFlowProfileActionAdaptor" abstract="true"
+        class="net.shibboleth.idp.profile.impl.WebFlowProfileActionAdaptor" scope="prototype"
+        p:profileContextLookupStrategy-ref="shibboleth.ChildLookup.ProxyProfileRequestContext" />
+        
+    <bean id="ParentAuthenticiationContextLookup" class="org.opensaml.messaging.context.navigate.ParentContextLookup"
+        c:type="net.shibboleth.idp.authn.context.AuthenticationContext" />
+    
+    <!--  Action beans -->
+    
+    <!-- Explicitly wrapped by a non-nested action adaptor. -->
+    
+     <!-- FIXME (add this back) p:profileId="#{T(net.shibboleth.idp.plugin.oidc.op.config.OIDCCoreProtocolConfiguration).PROFILE_ID}"-->
+    <bean id="InitializeProxyProfileRequestContext"
+        class="net.shibboleth.idp.authn.proxy.impl.InitializeProxyProfileRequestContext"       
+        p:profileId="http://shibboleth.net/ns/profiles/oidc/sso/browser"
+        p:loggingId="%{idp.service.logging.oidcsso:OIDC.SSO}"
+        p:browserProfile="true" />
+        
+   <bean id="FlowStartPopulateAuditContext" parent="shibboleth.AbstractPopulateAuditContext"
+        p:fieldExtractors="#{getObject('shibboleth.FlowStartAuditExtractors') ?: getObject('shibboleth.DefaultFlowStartAuditExtractors')}" />
+   
+   
+   <bean id="PrepareInboundMessageContext"
+            class="net.shibboleth.idp.saml.session.impl.PrepareInboundMessageContext" scope="prototype"
+            p:profileContextLookupStrategy-ref="shibboleth.ChildLookup.ProxyProfileRequestContext">
+        <property name="relyingPartyLookupStrategy">
+           <bean parent="shibboleth.Functions.Compose" c:f-ref="ParentAuthenticiationContextLookup">
+               <constructor-arg name="g">
+                   <bean parent="shibboleth.Functions.Expression" c:expression="#input.getAuthenticatingAuthority()" />
+               </constructor-arg>
+           </bean>
+        </property>
+    </bean>
+    
+    <bean id="OIDCMetadataLookup" parent="NestedWebFlowMessageHandlerAdaptor"
+        scope="prototype" c:executionDirection="INBOUND">
+        <constructor-arg name="messageHandler">
+            <bean class="net.shibboleth.idp.plugin.authn.oidc.rp.metadata.impl.OIDCProviderMetadataLookupHandler" scope="prototype">
+               <property name="providerMetadataResolver">
+                    <ref bean="shibboleth.oidc.rp.ProviderMetadataResolver" />
+                </property>
+                <property name="issuerIDLookupStrategy">
+                    <ref bean="shibboleth.oidc.rp.IssuerIDLookupStrategy" />
+                </property>
+            </bean>
+        </constructor-arg>
+    </bean>
+    
+     <bean id="shibboleth.oidc.rp.IssuerIDLookupStrategy"
+        class="net.shibboleth.idp.plugin.authn.oidc.rp.metadata.impl.DefaultIssuerIDLookupFunction"
+        scope="prototype" />
+    
+    
+    
+    <!-- OLD STUFF -->
+    
     <!-- TODO Add user import here
     <import resource="openidconnect-authn-config.xml" /> -->
 
@@ -37,15 +109,15 @@
     <!-- Populate RP UI info from metadata? -->
     <util:constant id="shibboleth.authn.oidc.rp.populateUIInfo" static-field="java.lang.Boolean.FALSE" />
 
-    <bean id="SetOIDCInformation" class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.SetOIDCInformation"
+   <!--  <bean id="SetOIDCInformation" class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.SetOIDCInformation"
         p:redirectURI="%{idp.oidc.rp.redirectURI:}"
         p:clientID="%{idp.oidc.rp.clientID:null}"
         p:clientSecret="%{idp.oidc.rp.clientSecret:null}"
         p:providerMetadataLocation="%{idp.oidc.rp.providerConfigurationDocument:null}"
         p:scope="%{idp.oidc.rp.scope:null}">
             
-        <!-- <property name="responseType" value="id_token token"/> -->
-    </bean>
+        <property name="responseType" value="id_token token"/>
+    </bean> -->
 
     <bean id="ValidateOIDCAuthenticationResponse"
         class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.ValidateOIDCAuthenticationResponse"
diff --git a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-flow.xml b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-flow.xml
new file mode 100644
index 0000000..9d3ac58
--- /dev/null
+++ b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-flow.xml
@@ -0,0 +1,111 @@
+<flow xmlns="http://www.springframework.org/schema/webflow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow.xsd"
+	parent="authn.abstract, authn/conditions">
+	
+	<!-- This is a login flow for proxied authentication implemented via OIDC -->
+    
+    <!-- OP discovery? -->
+    <on-start>
+        <!-- If installed, this can bypass discovery. -->
+        <evaluate expression="flowRequestContext.getActiveFlow().getApplicationContext().containsBean('shibboleth.authn.oidc.rp.discoveryFunction') ? flowRequestContext.getActiveFlow().getApplicationContext().getBean('shibboleth.authn.oidc.rp.discoveryFunction') : PropertyDrivenDiscovery" result="flowScope.customDiscovery" />
+        <evaluate expression="opensamlProfileRequestContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext)).setAuthenticatingAuthority(customDiscovery.apply(opensamlProfileRequestContext))" />
+    </on-start>
+    
+    <action-state id="Start">
+        <evaluate expression="'proceed'" />
+        <transition on="proceed" to="DoDiscovery" />
+    </action-state>
+    
+    <action-state id="PostDiscovery">
+        <!-- Nest new PRC inside AC -->
+        <evaluate expression="InitializeProxyProfileRequestContext" />
+        
+        <evaluate expression="FlowStartPopulateAuditContext" />
+        
+        <!-- this is nice to get the rp out of the authenticating auth and setup a msg context
+        but do we need it for a SAMLPeerEntityContext? -->
+        <evaluate expression="PrepareInboundMessageContext" />
+        
+        <!--  <evaluate expression="SAMLProtocolAndRole" />  maybe we need an OIDC role selector here, to say this is an
+        OP over the normal RP -->
+        <evaluate expression="OIDCMetadataLookup" />
+        
+        <!-- 
+        <evaluate expression="SAMLMetadataLookup" />
+
+        <evaluate expression="InitializeRelyingPartyContextFromSAMLPeer" />
+        <evaluate expression="SelectRelyingPartyConfiguration" />
+
+        <evaluate expression="PostLookupPopulateAuditContext" />
+        
+        <evaluate expression="SelectProfileConfiguration" />
+        
+        <evaluate expression="InitializeOutboundMessageContext" />
+        <evaluate expression="InitializeMessageChannelSecurityContext" />
+        <evaluate expression="PopulateBindingAndEndpointContexts" />
+
+        <evaluate expression="PopulateRequestSignatureSigningParameters" />
+        
+        <evaluate expression="AddAuthnRequest" />
+        <evaluate expression="PostRequestPopulateAuditContext" />
+        <evaluate expression="WriteAuditLog" /> -->
+        <evaluate expression="'proceed'" />
+        
+        <transition on="proceed" to="AuthRequest" />
+    </action-state>
+    
+    
+    
+    <!-- Discovery done -->
+<!-- 
+	<action-state id="SetRPUIInformation">
+        <evaluate expression="SetRPUIInformation" />
+        <evaluate expression="'proceed'" />
+        <transition on="proceed" to="SetOIDCInformation" /> 
+    </action-state>
+
+    <action-state id="SetOIDCInformation">
+        <evaluate expression="SetOIDCInformation" />
+        <evaluate expression="'proceed'" />
+        <transition on="proceed" to="ExternalTransfer" />
+    </action-state> -->
+
+    <view-state id="AuthRequest"
+        view="externalRedirect:#{T(net.shibboleth.idp.authn.ExternalAuthentication).getExternalRedirect(flowRequestContext.getActiveFlow().getApplicationContext().getBean('shibboleth.authn.OpenIDConnect.externalAuthnPath'), flowExecutionContext.getKey().toString())}">
+        <attribute name="csrf_excluded" value="true" type="boolean" />       
+        <on-render>
+            <evaluate
+                expression="opensamlProfileRequestContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext)).addSubcontext(new net.shibboleth.idp.authn.context.ExternalAuthenticationContext(new net.shibboleth.idp.authn.impl.ExternalAuthenticationImpl(false)), true).setFlowExecutionUrl(flowExecutionUrl + '&_eventId_proceed=1')" />
+          </on-render>
+        <transition to="ValidateResponse" />
+    </view-state>
+
+    <action-state id="ValidateResponse">
+        <evaluate expression="ValidateOIDCAuthenticationResponse" />
+        <evaluate expression="'proceed'" />
+        <transition on="proceed" to="GetToken" />
+    </action-state>
+
+    <action-state id="GetToken">
+        <evaluate expression="GetOIDCTokenResponse" />
+        <evaluate expression="'proceed'" />
+        <transition on="proceed" to="ValidateOIDCTokenResponse" />
+    </action-state>
+
+    <action-state id="ValidateOIDCTokenResponse">
+        <evaluate expression="ValidateIDTokenSignature" />
+        <evaluate expression="ValidateTokenClaims" />        
+        <evaluate expression="'proceed'" />
+        <transition on="proceed" to="SetPrincipal" />
+    </action-state>
+
+
+    <action-state id="SetPrincipal">
+        <evaluate expression="ValidateOIDCAuthentication" />
+        <evaluate expression="'proceed'" />
+        <transition on="proceed" to="proceed" />
+    </action-state>
+
+    <bean-import resource="oidc-relying-party-authn-beans.xml" />
+
+</flow>
diff --git a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-flow.xml b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-flow.xml
deleted file mode 100644
index 76ec7df..0000000
--- a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-flow.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-<flow xmlns="http://www.springframework.org/schema/webflow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow.xsd"
-	parent="authn.abstract, authn/conditions">
-
-	<action-state id="SetRPUIInformation">
-        <evaluate expression="SetRPUIInformation" />
-        <evaluate expression="'proceed'" />
-        <transition on="proceed" to="SetOIDCInformation" /> 
-    </action-state>
-
-    <action-state id="SetOIDCInformation">
-        <evaluate expression="SetOIDCInformation" />
-        <evaluate expression="'proceed'" />
-        <transition on="proceed" to="ExternalTransfer" />
-    </action-state>
-
-    <view-state id="ExternalTransfer"
-        view="externalRedirect:#{T(net.shibboleth.idp.authn.ExternalAuthentication).getExternalRedirect(flowRequestContext.getActiveFlow().getApplicationContext().getBean('shibboleth.authn.OpenIDConnect.externalAuthnPath'), flowExecutionContext.getKey().toString())}">
-        <attribute name="csrf_excluded" value="true" type="boolean" />       
-        <on-render>
-            <evaluate
-                expression="opensamlProfileRequestContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext)).addSubcontext(new net.shibboleth.idp.authn.context.ExternalAuthenticationContext(new net.shibboleth.idp.authn.impl.ExternalAuthenticationImpl(false)), true).setFlowExecutionUrl(flowExecutionUrl + '&_eventId_proceed=1')" />
-          </on-render>
-        <transition to="ValidateResponse" />
-    </view-state>
-
-    <action-state id="ValidateResponse">
-        <evaluate expression="ValidateOIDCAuthenticationResponse" />
-        <evaluate expression="'proceed'" />
-        <transition on="proceed" to="GetToken" />
-    </action-state>
-
-    <action-state id="GetToken">
-        <evaluate expression="GetOIDCTokenResponse" />
-        <evaluate expression="'proceed'" />
-        <transition on="proceed" to="ValidateOIDCTokenResponse" />
-    </action-state>
-
-    <action-state id="ValidateOIDCTokenResponse">
-        <evaluate expression="ValidateIDTokenSignature" />
-        <evaluate expression="ValidateTokenClaims" />        
-        <evaluate expression="'proceed'" />
-        <transition on="proceed" to="SetPrincipal" />
-    </action-state>
-
-
-    <action-state id="SetPrincipal">
-        <evaluate expression="ValidateOIDCAuthentication" />
-        <evaluate expression="'proceed'" />
-        <transition on="proceed" to="proceed" />
-    </action-state>
-
-    <bean-import resource="oidc-relying-party-beans.xml" />
-
-</flow>
diff --git a/idp-oidc-rp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/oidc/rp/conf/authn/providermetadata-resolver-system.xml b/idp-oidc-rp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/oidc/rp/conf/authn/providermetadata-resolver-system.xml
new file mode 100644
index 0000000..d3e71a9
--- /dev/null
+++ b/idp-oidc-rp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/oidc/rp/conf/authn/providermetadata-resolver-system.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xmlns:p="http://www.springframework.org/schema/p"
+       xmlns:c="http://www.springframework.org/schema/c"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
+                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+                           
+       default-init-method="initialize"
+       default-destroy-method="destroy"
+       default-lazy-init="true">
+       
+    <!-- Loaded by the postconfig.xml file as global beans -->
+
+     <bean id="shibboleth.oidc.rp.ProviderMetadataProvider" lazy-init="false"
+        class="net.shibboleth.oidc.metadata.ProviderMetadataProviderContainer"
+        p:embeddedResolver-ref="shibboleth.oidc.rp.ChainingProviderMetadataResolver">
+    </bean>
+
+    <bean id="shibboleth.oidc.rp.ChainingProviderMetadataResolver"
+        class="net.shibboleth.oidc.metadata.impl.ChainingProviderMetadataResolver"
+        p:id="InternalEmbeddedChainResolver" 
+        p:resolvers="#{getObject('shibboleth.oidc.rp.ProviderMetadataResolvers')}"/>
+
+    <!-- abstract beans for the user space config to extend -->
+    <bean id="shibboleth.oidc.rp.FilesystemProviderMetadataResolver" abstract="true"
+        class="net.shibboleth.oidc.metadata.impl.FilesystemProviderMetadataResolver"/>
+        
+   <bean id="shibboleth.oidc.rp.HTTPProviderMetadataResolver" abstract="true"
+        class="net.shibboleth.oidc.metadata.impl.DynamicOIDCProviderMetadataResolver"
+        c:metadataCache="#{getObject('shibboleth.oidc.rp.OIDCProviderMetadataCache')}"/>
+        
+    <bean id="shibboleth.oidc.rp.DefaultHTTPProviderConfigurationMetadataFetchingStrategy"
+        class="net.shibboleth.oidc.metadata.impl.HTTPProviderConfigurationFetchingStrategy"
+        c:client-ref="shibboleth.InternalHttpClient"
+        c:handler-ref="shibboleth.oidc.rp.DefaultHTTProviderConfigurationMetadataResponseHandler"
+        />
+
+    <bean id="shibboleth.oidc.rp.DefaultHTTProviderConfigurationMetadataResponseHandler"
+        class="net.shibboleth.oidc.metadata.impl.HTTPProviderConfigurationFetchingStrategy.OIDCProviderMetadataResponseHandler"
+    />
+
+   <bean id="shibboleth.oidc.rp.OIDCProviderMetadataCache" 
+        class="net.shibboleth.oidc.metadata.cache.impl.OIDCProviderMetadataCacheFactoryBean"
+        p:cacheOperationMode="#{T(net.shibboleth.oidc.metadata.cache.impl.MetadataCacheBuilder.CacheOperationMode).DYNAMIC}"
+        p:fetchStrategy="#{getObject('shibboleth.oidc.rp.DefaultHTTPProviderConfigurationMetadataFetchingStrategy')}"
+        p:criteriaToIdentifierStrategy="#{getObject('DefaultOIDCProviderMetadataCriteriaToIdentifierStrategy')}"
+        p:metadataExpirationTimeStrategy="#{getObject('DefaultMetadataExpirationTimeStrategy')}"
+        p:identifierExtractionStrategy="#{getObject('DefaultMetadataIdentifierExtractionStrategy')}"
+        />
+       
+    <bean id="DefaultMetadataExpirationTimeStrategy" 
+        class="net.shibboleth.oidc.metadata.cache.impl.DefaultOIDCProviderMetadataExpirationTimeStrategy"
+        c:duration="PT10M"/>
+    
+    <bean id="DefaultMetadataIdentifierExtractionStrategy"
+        class="net.shibboleth.oidc.metadata.cache.impl.DefaultOIDCProviderMetadataIdentifierExtractionStrategy"/>
+        
+    <bean id="DefaultOIDCProviderMetadataCriteriaToIdentifierStrategy"
+        class="net.shibboleth.oidc.metadata.cache.impl.DefaultOIDCProviderMetadataCriteriaToIdentifierStrategy"/>
+
+    <!-- Wildcard import hook for plugins. -->
+    <!-- TODO: Not sure we need this -->
+    <import resource="classpath*:/META-INF/net/shibboleth/idp/plugin/oidc/op/service/clientinfo/postconfig.xml" />
+
+</beans>
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowTest.java
new file mode 100644
index 0000000..d389108
--- /dev/null
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowTest.java
@@ -0,0 +1,203 @@
+package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.ResponseHandler;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.protocol.HttpContext;
+import org.junit.Test;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.webflow.core.collection.LocalAttributeMap;
+import org.springframework.webflow.engine.Flow;
+import org.springframework.webflow.execution.FlowExecution;
+import org.springframework.webflow.test.MockFlowBuilderContext;
+
+import com.nimbusds.oauth2.sdk.ParseException;
+import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
+
+import net.shibboleth.ext.spring.config.IdentifiableBeanPostProcessor;
+import net.shibboleth.idp.plugin.authn.test.flow.AbstractAuthnXmlFlowExecutionTests;
+import net.shibboleth.idp.plugin.authn.test.flow.mock.MockFlowBuilder;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.annotation.constraint.Unmodifiable;
+
+/** Test the OIDC relying party flow.*/
+public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
+    
+    private final String GOOD_PROVIDER_CONFIGURATION_INFO = "{\n"
+            + "\"issuer\": \"https://op.example.com\",\n"
+            + "\"authorization_endpoint\": \"https://example.oidc.op.org/o/oauth2/v2/auth\",\n"
+            + "\"device_authorization_endpoint\": \"https://oauth2.googleapis.com/device/code\",\n"
+            + "\"token_endpoint\": \"https://oauth2.googleapis.com/token\",\n"
+            + "\"userinfo_endpoint\": \"https://openidconnect.googleapis.com/v1/userinfo\",\n"
+            + "\"revocation_endpoint\": \"https://oauth2.googleapis.com/revoke\",\n"
+            + "\"jwks_uri\": \"https://www.googleapis.com/oauth2/v3/certs\",\n"
+            + "\"response_types_supported\": [\n"
+            + "\"code\",\n"
+            + "\"token\",\n"
+            + "\"id_token\",\n"
+            + "\"code token\",\n"
+            + "\"code id_token\",\n"
+            + "\"token id_token\",\n"
+            + "\"code token id_token\",\n"
+            + "\"none\"\n"
+            + "],\n"
+            + "\"subject_types_supported\": [\n"
+            + "\"public\"\n"
+            + "],\n"
+            + "\"id_token_signing_alg_values_supported\": [\n"
+            + "\"RS256\"\n"
+            + "],\n"
+            + "\"scopes_supported\": [\n"
+            + "\"openid\",\n"
+            + "\"email\",\n"
+            + "\"profile\"\n"
+            + "],\n"
+            + "\"token_endpoint_auth_methods_supported\": [\n"
+            + "\"client_secret_post\",\n"
+            + "\"client_secret_basic\"\n"
+            + "],\n"
+            + "\"claims_supported\": [\n"
+            + "\"aud\",\n"
+            + "\"email\",\n"
+            + "\"email_verified\",\n"
+            + "\"exp\",\n"
+            + "\"family_name\",\n"
+            + "\"given_name\",\n"
+            + "\"iat\",\n"
+            + "\"iss\",\n"
+            + "\"locale\",\n"
+            + "\"name\",\n"
+            + "\"picture\",\n"
+            + "\"sub\"\n"
+            + "],\n"
+            + "\"code_challenge_methods_supported\": [\n"
+            + "\"plain\",\n"
+            + "\"S256\"\n"
+            + "],\n"
+            + "\"grant_types_supported\": [\n"
+            + "\"authorization_code\",\n"
+            + "\"refresh_token\",\n"
+            + "\"urn:ietf:params:oauth:grant-type:device_code\",\n"
+            + "\"urn:ietf:params:oauth:grant-type:jwt-bearer\"\n"
+            + "]\n"
+            + "}";
+    
+    
+    /** Path to the flow to be tested.*/
+    @Nonnull private static final String FLOW = 
+            "/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-flow.xml";
+    
+    /** Class logger. */
+    @Nonnull private final Logger log = LoggerFactory.getLogger(OIDCRPFlowTest.class);
+    
+    /** List of mocked subflows.*/
+    @Nonnull @NonnullElements @Unmodifiable private final List<Flow> subflows = 
+            List.of(MockFlowBuilder.MockNoOpFlow("c14n"));
+    
+    /** 
+     * Map of flow resources that support building the flow to test.
+     * These are only for parent flows, not subflows.
+     */
+    @Nonnull @NonnullElements @Unmodifiable private final Map<String,String> flowResources = 
+            Map.of(
+            "classpath:/net/shibboleth/idp/flows/authn/authn-abstract-flow.xml","authn.abstract",
+            "classpath:/flows/authn/conditions/conditions-flow.xml","authn/conditions",
+            "classpath:/conf/authn/authn-events-flow.xml","authn.events");
+    
+    
+    @Override
+    protected void registerMockPropertySource(@Nonnull final MockFlowBuilderContext builderContext) {
+        super.registerMockPropertySource(builderContext);
+    }
+    
+    @Override
+    protected void registerMockBeanDefinitions(@Nonnull final MockFlowBuilderContext builderContext) {
+        super.registerMockBeanDefinitions(builderContext);
+        
+        addBeanDefinition(builderContext, "shibboleth.DefaultFlowStartAuditExtractors",BeanDefinitionBuilder.
+                genericBeanDefinition(HashMap.class).getBeanDefinition());
+        
+        addBeanDefinition(builderContext, "shibboleth.AbstractPopulateAuditContext",BeanDefinitionBuilder.
+                genericBeanDefinition(net.shibboleth.idp.profile.audit.impl.PopulateAuditContext.class)
+                .setAbstract(true).getBeanDefinition());
+        
+        
+        addBeanDefinition(builderContext, "shibboleth.PropertySourcesPlaceholderConfigurer",BeanDefinitionBuilder.
+                genericBeanDefinition(org.springframework.context.support.PropertySourcesPlaceholderConfigurer.class)
+                .addPropertyValue("placeholderPrefix", "%{")
+                .addPropertyValue("placeholderSuffix", "}").getBeanDefinition());
+        
+        addBeanDefinition(builderContext, "shibboleth.IdentifiableBeanPostProcessor",BeanDefinitionBuilder.
+                genericBeanDefinition(IdentifiableBeanPostProcessor.class).getBeanDefinition());
+        
+
+        //create Mock HttpClient
+        final HttpClient httpClient = mock(HttpClient.class);
+        addBeanSingleton(builderContext, "shibboleth.InternalHttpClient", httpClient);
+        
+        try {
+            when(httpClient.
+                    execute(any(HttpUriRequest.class),any(ResponseHandler.class),any(HttpContext.class)))
+                    .thenReturn(OIDCProviderMetadata.parse(GOOD_PROVIDER_CONFIGURATION_INFO));
+        } catch (ParseException | IOException e) {
+            log.error("Could not mock HTTP response",e);
+        }
+
+        
+        loadBeanDefinitionsFromXmlFile(builderContext, new ClassPathResource("META-INF/net.shibboleth.idp/postconfig.xml"));
+        
+        
+    }
+    
+    @Override
+    @Nonnull protected ProfileRequestContext buildProfileRequestContext(@Nonnull final String flowId,
+            @Nonnull final boolean forceAuthn,
+            @Nonnull final boolean addC14Context) {
+        return super.buildProfileRequestContext(flowId, forceAuthn, addC14Context);
+    }
+
+    @Test
+    public void testFlowToRedirect() {
+        setFlowPath(FLOW);
+        setFlowModelResources(flowResources);
+        setSubflows(subflows);
+        
+        final Map<String,String> mockProperties = Map.of(
+                "idp.service.clientinfo.failFast","false",
+                "idp.oidc.rp.clientID","clientId",
+                "idp.oidc.rp.clientSecret","secret",
+                "idp.oidc.rp.providerConfigurationDocument","provider_location",
+                "idp.oidc.rp.redirectURI","https://localhost:8443/idp/profile/Authn/OIDC/RP/callback",
+                "idp.oidc.rp.scope","email",
+                "idp.authn.oidc.rp.proxyIssuer","https://op.example.com");
+        
+        setMockProperties(mockProperties);
+        
+        final LocalAttributeMap<Object> inputMap = new LocalAttributeMap<Object>();
+        inputMap.put("calledAsSubflow", true);
+
+        final FlowExecution flowExecution = getFlowExecutionFactory().createFlowExecution(getFlowDefinition());  
+        flowExecution.getConversationScope()
+                    .put("opensamlProfileRequestContext", buildProfileRequestContext("authn/OIDCRelyingParty",false,true));
+        updateFlowExecution(flowExecution);
+        flowExecution.start(inputMap, externalContext);    
+        //TODO: only check it has ended, should check correct state - but it does not allow this
+        //find a way to check last state of an ended flow.
+        assertFlowExecutionEnded();
+    }
+}
diff --git a/idp-oidc-rp-impl/src/test/resources/conf/authn/oidc-providermetadata-resolvers.xml b/idp-oidc-rp-impl/src/test/resources/conf/authn/oidc-providermetadata-resolvers.xml
new file mode 100644
index 0000000..5b69c78
--- /dev/null
+++ b/idp-oidc-rp-impl/src/test/resources/conf/authn/oidc-providermetadata-resolvers.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xmlns:p="http://www.springframework.org/schema/p"
+       xmlns:c="http://www.springframework.org/schema/c"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
+                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+                           
+       default-init-method="initialize"
+       default-destroy-method="destroy">
+
+     <util:list id="shibboleth.oidc.rp.ProviderMetadataResolvers">
+       <ref bean="ExampleHTTPResolver" /> 
+    </util:list>
+
+   
+    <bean id="ExampleFileResolver" parent="shibboleth.oidc.rp.FilesystemProviderMetadataResolver"
+        c:metadata="%{idp.home}/metadata/openid-configuration.json" />
+        
+    <bean id="ExampleHTTPResolver" parent="shibboleth.oidc.rp.HTTPProviderMetadataResolver"
+         />
+   
+
+    
+    
+</beans>
\ No newline at end of file
diff --git a/idp-oidc-rp-impl/src/test/resources/logback-test.xml b/idp-oidc-rp-impl/src/test/resources/logback-test.xml
new file mode 100644
index 0000000..3eabacc
--- /dev/null
+++ b/idp-oidc-rp-impl/src/test/resources/logback-test.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<configuration>
+    <logger name="net.shibboleth" level="DEBUG"/>
+    <logger name="org.springframework" level="DEBUG"/>
+
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>%level [%logger:%line] - %msg%n</pattern>
+            <charset>UTF-8</charset>
+        </encoder>
+    </appender>
+
+    <root>
+        <level value="WARN" />
+        <appender-ref ref="STDOUT" />
+    </root>
+    
+</configuration>
\ No newline at end of file
diff --git a/idp-oidc-rp-impl/src/test/resources/metadata/openid-configuration.json b/idp-oidc-rp-impl/src/test/resources/metadata/openid-configuration.json
new file mode 100644
index 0000000..912ff94
--- /dev/null
+++ b/idp-oidc-rp-impl/src/test/resources/metadata/openid-configuration.json
@@ -0,0 +1,55 @@
+{
+"issuer": "https://op.example.com",
+"authorization_endpoint": "https://op.example.com/o/oauth2/v2/auth",
+"token_endpoint": "https://oauth2.op.example.com/token",
+"userinfo_endpoint": "https://openidconnect.op.example.com/v1/userinfo",
+"revocation_endpoint": "https://oauth2.op.example.com/revoke",
+"jwks_uri": "https://op.example.com/oauth2/v3/certs",
+"response_types_supported": [
+"code",
+"token",
+"id_token",
+"code token",
+"code id_token",
+"token id_token",
+"code token id_token",
+"none"
+],
+"subject_types_supported": [
+"public"
+],
+"id_token_signing_alg_values_supported": [
+"RS256"
+],
+"scopes_supported": [
+"openid",
+"email",
+"profile"
+],
+"token_endpoint_auth_methods_supported": [
+"client_secret_post",
+"client_secret_basic"
+],
+"claims_supported": [
+"aud",
+"email",
+"email_verified",
+"exp",
+"family_name",
+"given_name",
+"iat",
+"iss",
+"locale",
+"name",
+"picture",
+"sub"
+],
+"code_challenge_methods_supported": [
+"plain",
+"S256"
+],
+"grant_types_supported": [
+"authorization_code",
+"refresh_token"
+]
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 5d5a87d..22f6b7a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,145 +1,162 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-	<parent>
-		<groupId>net.shibboleth</groupId>
-		<artifactId>parent</artifactId>
-		<version>11.2.2-SNAPSHOT</version>
-	</parent>
-	<groupId>net.shibboleth.idp.plugin.authn</groupId>
-	<artifactId>idp-plugin-oidc-rp-parent</artifactId>
-	<version>0.0.1-SNAPSHOT</version>
-	<name>Shibboleth IdP :: Plugins :: OIDC RP Login Flow</name>
-	<packaging>pom</packaging>
-	<description>Java OIDC RP authentication plugin for the Shibboleth IdP.</description>
-	
-	<properties>
-		<idp.groupId>net.shibboleth.idp</idp.groupId>
-		<idp.version>4.1.0</idp.version>
-		<opensaml.groupId>org.opensaml</opensaml.groupId>
-		<opensaml.version>4.1.0</opensaml.version>
-		<oidc.common.version>1.1.0-SNAPSHOT</oidc.common.version>
-		<checkstyle.configLocation>${project.basedir}/checkstyle.xml</checkstyle.configLocation>
-	</properties>
-	
-	<distributionManagement>
-		<site>
-			<id>site</id>
-			<url>scp:${shibboleth.site.deploy.url}java-idp-plugin-oidc-rp/${project.version}/</url>
-		</site>
-	</distributionManagement>
-	
-	<repositories>
-		<repository>
-			<id>shib-release</id>
-			<url>https://build.shibboleth.net/nexus/content/groups/public</url>
-			<snapshots>
-				<enabled>false</enabled>
-			</snapshots>
-		</repository>
-		<repository>
-			<id>shib-snapshot</id>
-			<url>https://build.shibboleth.net/nexus/content/repositories/snapshots</url>
-			<releases>
-				<enabled>false</enabled>
-			</releases>
-		</repository>
-	</repositories>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>net.shibboleth</groupId>
+        <artifactId>parent</artifactId>
+        <version>11.2.2-SNAPSHOT</version>
+    </parent>
+    <groupId>net.shibboleth.idp.plugin.authn</groupId>
+    <artifactId>idp-plugin-oidc-rp-parent</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>Shibboleth IdP :: Plugins :: OIDC RP Login Flow</name>
+    <packaging>pom</packaging>
+    <description>Java OIDC RP authentication plugin for the Shibboleth IdP.</description>
 
-	<modules>
-		<module>idp-oidc-rp-impl</module>
-		<module>idp-oidc-rp-api</module>
-		<!-- All DIST modules must come after the -api and -impl modules -->
-		<module>idp-oidc-rp-dist</module>
-	</modules>
+    <properties>
+        <idp.groupId>net.shibboleth.idp</idp.groupId>
+        <idp.version>4.1.0</idp.version>
+        <opensaml.groupId>org.opensaml</opensaml.groupId>
+        <opensaml.version>4.1.0</opensaml.version>
+        <oidc.common.version>1.1.1-SNAPSHOT</oidc.common.version>
+        <!-- This is tmp until certain classes move over to commons -->
+        <oidc.op.version>3.0.1</oidc.op.version>
+        <checkstyle.configLocation>${project.basedir}/checkstyle.xml</checkstyle.configLocation>
+    </properties>
 
-	<scm>
-		<connection>scm:git:...</connection>
-		<developerConnection>scm:git:...</developerConnection>
-		<url>...</url>
-	</scm>
-	
-	<dependencies>
-		<!-- Project wide test Dependencies -->
-		<dependency>
-			<groupId>org.testng</groupId>
-			<artifactId>testng</artifactId>
-			<scope>test</scope>
-		</dependency>
-		<dependency>
-			<groupId>${slf4j.groupId}</groupId>
-			<artifactId>slf4j-api</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.mockito</groupId>
-			<artifactId>mockito-core</artifactId>
-			<scope>test</scope>
-		</dependency>
-	</dependencies>
-	<dependencyManagement>
-		<!-- java-idp-oidc-rp project dependencies -->
-		<dependencies>
-			<dependency>
-				<groupId>net.shibboleth.idp.plugin.authn</groupId>
-				<artifactId>idp-plugin-oidc-rp-api</artifactId>
-				<version>${project.version}</version>
-			</dependency>
-			<dependency>
-				<groupId>net.shibboleth.idp.plugin.authn</groupId>
-				<artifactId>idp-plugin-oidc-rp-impl</artifactId>
-				<version>${project.version}</version>
-			</dependency>
-			<!-- OIDC Common BOM when importing OIDC dependencies -->
-             <dependency>
+    <distributionManagement>
+        <site>
+            <id>site</id>
+            <url>scp:${shibboleth.site.deploy.url}java-idp-plugin-oidc-rp/${project.version}/</url>
+        </site>
+    </distributionManagement>
+
+    <repositories>
+        <repository>
+            <id>shib-release</id>
+            <url>https://build.shibboleth.net/nexus/content/groups/public</url>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+        </repository>
+        <repository>
+            <id>shib-snapshot</id>
+            <url>https://build.shibboleth.net/nexus/content/repositories/snapshots</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+        </repository>
+    </repositories>
+
+    <modules>
+        <module>idp-oidc-rp-impl</module>
+        <module>idp-oidc-rp-api</module>
+        <!-- All DIST modules must come after the -api and -impl modules -->
+        <module>idp-oidc-rp-dist</module>
+    </modules>
+
+    <scm>
+        <connection>scm:git:...</connection>
+        <developerConnection>scm:git:...</developerConnection>
+        <url>...</url>
+    </scm>
+
+    <dependencies>
+        <!-- Project wide test Dependencies -->
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${slf4j.groupId}</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <dependencyManagement>
+        <!-- java-idp-oidc-rp project dependencies -->
+        <dependencies>
+            <dependency>
+                <groupId>net.shibboleth.idp.plugin.authn</groupId>
+                <artifactId>idp-plugin-oidc-rp-api</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>net.shibboleth.idp.plugin.authn</groupId>
+                <artifactId>idp-plugin-oidc-rp-impl</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <!-- Tmp OP deps until things move to commons -->
+            <dependency>
+                <groupId>net.shibboleth.idp.plugin.oidc</groupId>
+                <artifactId>idp-plugin-oidc-op-api</artifactId>
+                <version>${oidc.op.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>net.shibboleth.idp.plugin.oidc</groupId>
+                <artifactId>idp-plugin-oidc-op-impl</artifactId>
+                <version>${oidc.op.version}</version>
+            </dependency>
+            <!-- OIDC Common BOM when importing OIDC dependencies -->
+            <dependency>
                 <groupId>net.shibboleth.oidc</groupId>
                 <artifactId>oidc-common-bom</artifactId>
                 <version>${oidc.common.version}</version>
                 <type>pom</type>
                 <scope>import</scope>
             </dependency>
-			<!-- Shibboleth IdP BOM for importing IdP dependencies -->
-			<dependency>
-				<groupId>net.shibboleth.idp</groupId>
-				<artifactId>idp-bom</artifactId>
-				<version>${idp.version}</version>
-				<type>pom</type>
-				<scope>import</scope>
-			</dependency>
-			<!-- Provided shibboleth support dependencies -->
-			<dependency>
-				<groupId>net.shibboleth.utilities</groupId>
-				<artifactId>java-support</artifactId>
-				<version>${java-support.version}</version>
-				<scope>provided</scope>
-			</dependency>
-			<!-- Test bom dependencies -->
-			<dependency>
-				<groupId>${idp.groupId}</groupId>
-				<artifactId>idp-tests-bom</artifactId>
-				<version>${idp.version}</version>
-				<type>pom</type>
-				<scope>import</scope>
-			</dependency>
-		</dependencies>
-	</dependencyManagement>
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-jar-plugin</artifactId>
-				<configuration>
-					<archive>
-						<index>true</index>
-						<manifestEntries>
-							<Automatic-Module-Name>${automatic.module.name}</Automatic-Module-Name>
-							<Sealed>true</Sealed>
-						</manifestEntries>
-					</archive>
-				</configuration>
-			</plugin>
-		</plugins>
-	</build>
+            <!-- Shibboleth IdP BOM for importing IdP dependencies -->
+            <dependency>
+                <groupId>net.shibboleth.idp</groupId>
+                <artifactId>idp-bom</artifactId>
+                <version>${idp.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <!-- Provided shibboleth support dependencies -->
+            <dependency>
+                <groupId>net.shibboleth.utilities</groupId>
+                <artifactId>java-support</artifactId>
+                <version>${java-support.version}</version>
+                <scope>provided</scope>
+            </dependency>
+            <!-- Test bom dependencies -->
+            <dependency>
+                <groupId>${idp.groupId}</groupId>
+                <artifactId>idp-tests-bom</artifactId>
+                <version>${idp.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <index>true</index>
+                        <manifestEntries>
+                            <Automatic-Module-Name>${automatic.module.name}</Automatic-Module-Name>
+                            <Sealed>true</Sealed>
+                        </manifestEntries>
+                    </archive>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 
 </project>

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list