[java-idp-plugin-oidc-rp] branch main updated: Add a client (RP proxy) metadata resolution step

Phil Smart philip.smart at jisc.ac.uk
Fri Jan 14 16:59:03 UTC 2022


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=b007d40b0b7a7b92f84d61962e9ef27a6e29a23b

The following commit(s) were added to refs/heads/main by this push:
     new b007d40  Add a client (RP proxy) metadata resolution step
b007d40 is described below

commit b007d40b0b7a7b92f84d61962e9ef27a6e29a23b
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Fri Jan 14 16:58:53 2022 +0000

    Add a client (RP proxy) metadata resolution step
    
    - Resolve client metadata appropriate for (registered with) the current
    authenticating authority (OP)
    - Use a custom issuer field/claim added to the client metadata
    - Created some near duplicates of resolver classes in commons. Needs
    refactoring.
    - Improve AddAuthz request construction to consider both provider and
    client metadata
---
 .../authn/oidc/rp/context/OIDCMetadataContext.java |  59 +++++++
 .../plugin/authn/oidc/rp/impl/AddAuthzRequest.java |  45 ++++--
 .../impl/FilesystemClientInformationResolver.java  | 171 +++++++++++++++++++++
 .../metadata/impl/OIDCMetadataLookupHandler.java   | 130 ++++++++++++++++
 .../impl/OIDCProviderMetadataLookupHandler.java    |   1 +
 .../META-INF/net.shibboleth.idp/postconfig.xml     |  38 ++++-
 .../oidc-relying-party-authn-beans.xml             |  20 ++-
 .../oidc-relying-party-authn-flow.xml              |   6 +-
 .../rp/conf/authn/clientinfo-resolver-system.xml   |  32 ++++
 .../authn/providermetadata-resolver-system.xml     |   2 +-
 .../oidc/rp/impl/AuthorizationControllerTest.java  |   4 +-
 .../conf/authn/oidc-clientinfo-resolvers.xml       |  23 +++
 .../src/test/resources/metadata/oidc-clients.json  |  26 ++++
 13 files changed, 535 insertions(+), 22 deletions(-)

diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/OIDCMetadataContext.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/OIDCMetadataContext.java
new file mode 100644
index 0000000..6bafcbb
--- /dev/null
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/OIDCMetadataContext.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.plugin.authn.oidc.rp.context;
+
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.BaseContext;
+
+import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
+
+/**
+ * Subcontext carrying information on metadata of the relying party. This
+ * context appears as a subcontext of the
+ * {@link org.opensaml.messaging.context.MessageContext} that carries the actual
+ * OIDC request message, in such cases the metadata carried herein applies to
+ * the issuer of that message.
+ * 
+ * This context is just a placeholder for the final solution. At first phase we
+ * use only redirect uris.
+ */
+public class OIDCMetadataContext extends BaseContext {
+
+    /** The client information. */
+    @Nullable private OIDCClientInformation clientInformation;
+    
+    /**
+     * Set the client information.
+     * 
+     * @return The client information.
+     */
+    @Nullable
+    public OIDCClientInformation getClientInformation() {
+        return clientInformation;
+    }
+
+    /**
+     * Set the client information.
+     * 
+     * @param information The client information.
+     */
+    public void setClientInformation(@Nullable final OIDCClientInformation information) {
+        clientInformation = information;
+    }
+}
\ No newline at end of file
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddAuthzRequest.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddAuthzRequest.java
index cfa5255..4d7511c 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddAuthzRequest.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddAuthzRequest.java
@@ -36,6 +36,8 @@ import com.nimbusds.oauth2.sdk.id.ClientID;
 
 import net.shibboleth.idp.authn.AbstractAuthenticationAction;
 import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.idp.plugin.authn.oidc.rp.context.OIDCMetadataContext;
+import net.shibboleth.idp.plugin.authn.oidc.rp.messaging.context.OIDCProviderMetadataContext;
 import net.shibboleth.idp.profile.IdPEventIds;
 import net.shibboleth.idp.profile.context.RelyingPartyContext;
 import net.shibboleth.oidc.profile.config.OIDCAuthorizationConfiguration;
@@ -67,6 +69,12 @@ public class AddAuthzRequest extends AbstractAuthenticationAction {
     /** Applicable profile configuration. */
     @Nullable private OIDCAuthorizationConfiguration profileConfiguration;
     
+    /** The metadata belonging to the client registered with the current OpenID Provider.*/
+    @Nullable private OIDCMetadataContext clientMetadata;
+    
+    /** The metadata belonging to the OpenID Provider.*/
+    @Nullable private OIDCProviderMetadataContext providerMetadata;
+    
     /** Constructor.*/
     public AddAuthzRequest() {
         // Fool the parent class into looking above instead of below the PRC for the context.
@@ -114,6 +122,20 @@ public class AddAuthzRequest extends AbstractAuthenticationAction {
             return false;
         }
         
+        final MessageContext inboundMessageCtx = profileRequestContext.getInboundMessageContext();
+        clientMetadata = inboundMessageCtx.getSubcontext(OIDCMetadataContext.class);
+        if (clientMetadata == null) {
+            log.debug("{} Inbound message context did not contain client metadata", getLogPrefix());
+            ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MSG_CTX);
+            return false;
+        }
+        providerMetadata = inboundMessageCtx.getSubcontext(OIDCProviderMetadataContext.class);
+        if (providerMetadata == null) {
+            log.debug("{} Inbound message context did not contain provider metadata", getLogPrefix());
+            ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MSG_CTX);
+            return false;
+        }
+        
         outboundMessageCtx.setMessage(null);
         
         return true;
@@ -126,19 +148,16 @@ public class AddAuthzRequest extends AbstractAuthenticationAction {
         log.debug("{} Building AuthzRequest for upstream OP ({})", 
                 getLogPrefix(), authenticationContext.getAuthenticatingAuthority());
         
-        try {
-            final OIDCAuthenticationRequest request = new OIDCAuthenticationRequest(new ClientID("clientID"));
-            // FIXME: This needs to be dynamic, is a demo for now
-            request.setResponseType(ResponseType.CODE);
-            request.setEndpointURI(new URI("https://somewhere.com/oauth2/authz"));
-            request.setRedirectURI(new URI("https://localhost:8080/callback"));
-            
-            log.debug("{} Built authorization request for endpoint '{}'",getLogPrefix(), request.getEndpointURI());
-            profileRequestContext.getOutboundMessageContext().setMessage(request);
-        } catch (URISyntaxException e) {
-            log.error("{} Unable to create authorization request for downstream OP '{}'", getLogPrefix(), "OP");
-            
-        }
+        
+        final OIDCAuthenticationRequest request = new OIDCAuthenticationRequest(clientMetadata.getClientInformation().getID());
+
+        request.setResponseType(ResponseType.CODE);
+        request.setEndpointURI(providerMetadata.getProviderInformation().getAuthorizationEndpointURI());
+        request.setRedirectURI(clientMetadata.getClientInformation().getMetadata().getRedirectionURI());
+        
+        log.debug("{} Built authorization request for endpoint '{}'",getLogPrefix(), request.getEndpointURI());
+        profileRequestContext.getOutboundMessageContext().setMessage(request);
+        
         
     }
 
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/metadata/impl/FilesystemClientInformationResolver.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/metadata/impl/FilesystemClientInformationResolver.java
new file mode 100644
index 0000000..524ab13
--- /dev/null
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/metadata/impl/FilesystemClientInformationResolver.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.plugin.authn.oidc.rp.metadata.impl;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Timer;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.io.Resource;
+
+import com.nimbusds.oauth2.sdk.ParseException;
+import com.nimbusds.oauth2.sdk.id.Issuer;
+import com.nimbusds.oauth2.sdk.util.JSONArrayUtils;
+import com.nimbusds.oauth2.sdk.util.JSONObjectUtils;
+import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
+
+import net.minidev.json.JSONArray;
+import net.minidev.json.JSONObject;
+import net.shibboleth.oidc.metadata.RefreshableClientInformationResolver;
+import net.shibboleth.oidc.metadata.criterion.IssuerIDCriterion;
+import net.shibboleth.oidc.metadata.impl.AbstractFileOIDCEntityResolver;
+import net.shibboleth.utilities.java.support.annotation.ParameterName;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+
+/**
+ * A client metadata provider that pulls metadata from a file on the local filesystem.
+ * 
+ * <p>The client information returned is determined from the 'issuer' custom claim.</p>
+ * 
+ */
+public class FilesystemClientInformationResolver extends AbstractFileOIDCEntityResolver<Issuer, OIDCClientInformation>
+        implements RefreshableClientInformationResolver {
+
+    /** Class logger. */
+    private final Logger log = LoggerFactory.getLogger(FilesystemClientInformationResolver.class);
+
+    /**
+     * Constructor.
+     * 
+     * @param metadata the metadata file
+     * 
+     * @throws IOException If the metedata cannot be loaded.
+     */
+    public FilesystemClientInformationResolver(
+            @Nonnull @ParameterName(name="metadata") final Resource metadata) throws IOException {
+        super(metadata);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param metadata the metadata file
+     * @param backgroundTaskTimer timer used to refresh metadata in the background
+     * 
+     * @throws IOException If the metedata cannot be loaded.
+     */
+    public FilesystemClientInformationResolver(@Nullable final Timer backgroundTaskTimer,
+            @Nonnull final Resource metadata) throws IOException {
+        super(backgroundTaskTimer, metadata);
+    }
+    
+    /** {@inheritDoc} */
+    @Override protected void doInitialize() throws ComponentInitializationException {
+        super.doInitialize();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Iterable<OIDCClientInformation> resolve(final CriteriaSet criteria) throws ResolverException {
+        ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
+        ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+        final IssuerIDCriterion issuerIdCriterion = criteria.get(IssuerIDCriterion.class);
+        if (issuerIdCriterion == null || issuerIdCriterion.getIssuerID() == null) {
+            log.trace("No issuer ID criteria found, returning all");
+            return updateKeys(getBackingStore().getOrderedInformation());
+        }
+        // TODO: support other criterion
+        return updateKeys(lookupIdentifier(issuerIdCriterion.getIssuerID()));
+    }
+
+    /**
+     * Updates the key set in the given list of OIDC client informations. The configured remote JWK set cache is
+     * exploited.
+     * 
+     * @param clientInformations The OIDC client informations whose keys are going to be updated.
+     * 
+     * @return The OIDC client informations, containing contents of getJWKSetURI() in getJWKSet().
+     */
+    protected List<OIDCClientInformation> updateKeys(final List<OIDCClientInformation> clientInformations) {
+        final List<OIDCClientInformation> result = new ArrayList<>();
+        for (final OIDCClientInformation clientInformation : clientInformations) {
+            result.add(clientInformation);
+        }
+        return result;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public OIDCClientInformation resolveSingle(@Nullable final CriteriaSet criteria) throws ResolverException {
+        final Iterable<OIDCClientInformation> iterable = resolve(criteria);
+        if (iterable != null) {
+            final Iterator<OIDCClientInformation> iterator = iterable.iterator();
+            if (iterator != null && iterator.hasNext()) {
+                return iterator.next();
+            }
+        }
+        log.warn("Could not find any clients with the given criteria");
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected List<OIDCClientInformation> parse(@Nonnull final byte[] bytes) throws ParseException {
+        final String rawString = new String(bytes);
+        try {
+            final OIDCClientInformation single = OIDCClientInformation.parse(JSONObjectUtils.parse(rawString));
+            log.debug("Found single client information from the file");
+            return Arrays.asList(single);
+        } catch (final ParseException e) {
+            log.debug("Could not parse single client information from the file, checking for array");
+        }
+        try {
+            final JSONArray parsedArray = JSONArrayUtils.parse(rawString);
+            final List<OIDCClientInformation> result = new ArrayList<OIDCClientInformation>();
+            for (final Object object : parsedArray) {
+                final OIDCClientInformation client = OIDCClientInformation.parse((JSONObject) object);
+                result.add(client);
+            }
+            return result;
+        } catch (final ParseException e) {
+            throw new ParseException("Could not parse a single or an array of OIDC client information object(s).");
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected Issuer getKey(@Nonnull final OIDCClientInformation value) {
+        final Object issuerObject = value.getMetadata().getCustomField("issuer");
+        if (issuerObject instanceof String) {
+            return new Issuer((String)issuerObject);
+        }
+        throw new IllegalArgumentException("Client information metadata does not contain an issuer");
+    }
+}
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/metadata/impl/OIDCMetadataLookupHandler.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/metadata/impl/OIDCMetadataLookupHandler.java
new file mode 100644
index 0000000..aff7fdc
--- /dev/null
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/metadata/impl/OIDCMetadataLookupHandler.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.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.rp.OIDCClientInformation;
+
+import net.shibboleth.idp.plugin.authn.oidc.rp.context.OIDCMetadataContext;
+import net.shibboleth.oidc.metadata.ClientInformationResolver;
+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 RP, and attaches it with a
+ * {@link OIDCMetadataContext} as a child of a pre-existing instance of {@link MessageContext}.
+ */
+public class OIDCMetadataLookupHandler extends AbstractMessageHandler {
+
+    /** Logger. */
+    @Nonnull private final Logger log = LoggerFactory.getLogger(OIDCMetadataLookupHandler.class);
+
+    /** Resolver used to look up OIDC client information. */
+    @NonnullAfterInit private ClientInformationResolver clientResolver;
+
+    /** Strategy used to obtain the issuer value for the authorization request. */
+    @Nonnull
+    private Function<MessageContext, String> issuerLookupStrategy;
+
+    /**
+     * Constructor.
+     */
+    public OIDCMetadataLookupHandler() {
+        issuerLookupStrategy = new DefaultIssuerIDLookupFunction();
+    }
+
+    /**
+     * Set the strategy used to locate the issuer (downstream OP) for the request.
+     * 
+     * @param strategy lookup strategy
+     */
+    public void setIssuerLookupStrategy(@Nonnull final Function<MessageContext, String> strategy) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        issuerLookupStrategy =
+                Constraint.isNotNull(strategy, "IssuerLookupStrategy lookup strategy cannot be null");
+    }
+
+    /**
+     * Set the {@link ClientInformationResolver} to use.
+     * 
+     * @param resolver The resolver to use.
+     */
+    public void setClientInformationResolver(@Nonnull final ClientInformationResolver resolver) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+        clientResolver = Constraint.isNotNull(resolver, "ClientInformationResolver cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void doInitialize() throws ComponentInitializationException {
+        super.doInitialize();
+
+        if (clientResolver == null) {
+            throw new ComponentInitializationException("ClientInformationResolver cannot be null");
+        }
+    }
+
+    //TODO test if no client returned
+    /** {@inheritDoc} */
+    @Override
+    protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
+        ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
+        // Resolve issuer from inbound message
+        final String issuerString = issuerLookupStrategy.apply(messageContext);
+        if (issuerString == null) {
+            log.warn("{} Issuer not found, client information can not be resolved", getLogPrefix());
+            return;
+        }
+        // Resolve client metadata for given issuer
+        final IssuerIDCriterion issuerCriterion = new IssuerIDCriterion(new Issuer(issuerString));
+        final CriteriaSet criteria = new CriteriaSet(issuerCriterion);
+        try {
+            final OIDCClientInformation clientInformation = clientResolver.resolveSingle(criteria);
+            if (clientInformation == null) {
+                log.debug("{} No client information returned for issuer {}", getLogPrefix(), issuerString);
+                return;
+            }
+            log.debug("{} Resolved client information for client '{}'", getLogPrefix(), clientInformation.getID());
+            final OIDCMetadataContext oidcCtx = new OIDCMetadataContext();
+            oidcCtx.setClientInformation(clientInformation);
+            messageContext.addSubcontext(oidcCtx);
+            // Based on that info we know 1) client is valid 2) we know valid
+            // redirect uris
+            log.debug("{} {} added to MessageContext as child of {}", getLogPrefix(),
+                    OIDCMetadataContext.class.getName(), messageContext.getClass().getName());
+        } catch (final ResolverException e) {
+            log.error("{} ResolverException thrown during client information lookup", getLogPrefix(), e);
+        }
+    }
+}
\ No newline at end of file
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
index 42f78d8..bf413c2 100644
--- 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
@@ -29,6 +29,7 @@ import net.shibboleth.utilities.java.support.resolver.ResolverException;
  * {@link OIDCMetadataContext} as a child of a pre-existing instance of {@link MessageContext}.
  */
 //TODO should this be conflated with the OIDCMetadataLookupHandler service
+//TODO is commons the correct place to put this?
 public class OIDCProviderMetadataLookupHandler extends AbstractMessageHandler {
     
     /** Logger. */
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 ef18587..c5fe8cc 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
@@ -123,7 +123,7 @@
         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>
+        <value>%{idp.home}/conf/authn/oidc-providermetadata-resolvers.xml</value> <!-- should be a conditional:? -->
     </util:list>
     <!-- Auto-append system config file to resource set. -->
     <bean id ="ExtendedProviderMetadataResolverResources" class="net.shibboleth.ext.spring.factory.CombiningListFactoryBean"
@@ -135,6 +135,42 @@
             </util:list>
         </property>
     </bean>
+    
+    
+    <!-- OIDC client information resolver service beans. -->
+    
+    <!--  TODO add this back? depends-on="shibboleth.AttributeResolverService"-->
+
+    <bean id="shibboleth.oidc.rp.ClientInformationResolverService"
+        class="net.shibboleth.ext.spring.service.ReloadableSpringService"
+        p:serviceConfigurations-ref="ExtendedClientInformationResolverResources"
+        p:failFast="%{idp.service.clientinfo.failFast:%{idp.service.failFast:false}}"
+        p:reloadCheckDelay="%{idp.service.clientinfo.checkInterval:PT0S}"
+        p:beanPostProcessors-ref="shibboleth.IdentifiableBeanPostProcessor"
+        p:beanFactoryPostProcessors-ref="shibboleth.PropertySourcesPlaceholderConfigurer">
+        <constructor-arg name="claz"
+            value="net.shibboleth.oidc.metadata.ClientInformationResolver" />
+        <constructor-arg name="strategy">
+            <bean class="net.shibboleth.oidc.profile.spring.relyingparty.metadata.impl.ClientInformationResolverServiceStrategy" />
+        </constructor-arg>
+    </bean>
+    <util:list id="shibboleth.DefaultClientInformationResolverResources">
+        <value>%{idp.home}/conf/authn/oidc-clientinfo-resolvers.xml</value> <!-- should be a conditional:? -->
+    </util:list>
+    <!-- Auto-append system config file to resource set. -->
+    <bean id ="ExtendedClientInformationResolverResources" class="net.shibboleth.ext.spring.factory.CombiningListFactoryBean"
+            p:firstList="#{getObject('%{idp.service.clientinfo.resources:shibboleth.ClientInformationResolverResources}'.trim()) ?:
+                getObject('shibboleth.DefaultClientInformationResolverResources')}">
+        <property name="secondList">
+            <util:list >
+                <value>classpath:/net/shibboleth/idp/plugin/authn/oidc/rp/conf/authn/clientinfo-resolver-system.xml</value>
+            </util:list>
+        </property>
+    </bean>
+
+    <bean id="shibboleth.oidc.rp.ClientInformationResolver"
+        class="net.shibboleth.oidc.metadata.impl.ReloadingRelyingPartyClientInformationProvider"
+        c:resolverService-ref="shibboleth.oidc.rp.ClientInformationResolverService" />
         
   
 </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-authn-beans.xml b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-beans.xml
index 89c8eb9..4cb940c 100644
--- a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-beans.xml
+++ b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-beans.xml
@@ -70,7 +70,7 @@
         </property>
     </bean>
     
-    <bean id="OIDCMetadataLookup" parent="NestedWebFlowMessageHandlerAdaptor"
+    <bean id="OIDCProviderMetadataLookup" 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">
@@ -84,6 +84,20 @@
         </constructor-arg>
     </bean>
     
+    <bean id="OIDCClientMetadataLookup" parent="NestedWebFlowMessageHandlerAdaptor"
+        scope="prototype" c:executionDirection="INBOUND">
+        <constructor-arg name="messageHandler">
+            <bean class="net.shibboleth.idp.plugin.authn.oidc.rp.metadata.impl.OIDCMetadataLookupHandler" scope="prototype">
+                <property name="clientInformationResolver">
+                    <ref bean="shibboleth.oidc.rp.ClientInformationResolver" />
+                </property>
+             <!--    <property name="clientIDLookupStrategy">
+                    <ref bean="shibboleth.oidc.rp.ClientIDLookupStrategy" />
+                </property> -->
+            </bean>
+        </constructor-arg>
+    </bean>
+    
      <bean id="shibboleth.oidc.rp.IssuerIDLookupStrategy"
         class="net.shibboleth.idp.plugin.authn.oidc.rp.metadata.impl.DefaultIssuerIDLookupFunction"
         scope="prototype" />
@@ -124,10 +138,10 @@
     </util:list>
 
     <bean id="OIDCAuthnRedirectRequestEncoder"
-        class="net.shibboleth.oidc.profile.encoders.impl.HTTPRedirectEncoder" init-method="" scope="prototype"
+        class="net.shibboleth.oidc.profile.encoder.impl.HTTPRedirectAuthnEncoder" init-method="" scope="prototype"
         p:httpServletResponse-ref="shibboleth.HttpServletResponse" />
 
-    <bean id="OIDCAuthnPostRequestEncoder" class="net.shibboleth.oidc.profile.encoders.impl.HTTPPostEncoder"
+    <bean id="OIDCAuthnPostRequestEncoder" class="net.shibboleth.oidc.profile.encoder.impl.HTTPPostAuthnEncoder"
         init-method="" scope="prototype" p:velocityEngine-ref="shibboleth.VelocityEngine"
         p:httpServletResponse-ref="shibboleth.HttpServletResponse" />
 
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
index c58dde7..1935724 100644
--- 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
@@ -27,10 +27,12 @@
         
         <!--  <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="OIDCProviderMetadataLookup" />             
         <evaluate expression="InitializeRelyingPartyContext" />
         <evaluate expression="SelectRelyingPartyConfiguration" />
+         <!--  Get RP information relating to this OP -->
+        <evaluate expression="OIDCClientMetadataLookup" /> 
+        
         <!--  <evaluate expression="PostLookupPopulateAuditContext" /> -->
         <evaluate expression="InitializeOutboundMessageContext" />
         <evaluate expression="SelectProfileConfiguration" />
diff --git a/idp-oidc-rp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/oidc/rp/conf/authn/clientinfo-resolver-system.xml b/idp-oidc-rp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/oidc/rp/conf/authn/clientinfo-resolver-system.xml
new file mode 100644
index 0000000..09dfce8
--- /dev/null
+++ b/idp-oidc-rp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/oidc/rp/conf/authn/clientinfo-resolver-system.xml
@@ -0,0 +1,32 @@
+<?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">
+
+    <bean id="shibboleth.oidc.RelyingPartyClientInformationProvider" lazy-init="false"
+        class="net.shibboleth.oidc.metadata.RelyingPartyClientInformationProvider"
+        p:embeddedResolver-ref="shibboleth.oidc.ChainingClientInformationResolver">
+    </bean>
+
+    <bean id="shibboleth.oidc.ChainingClientInformationResolver"
+        class="net.shibboleth.oidc.metadata.impl.ChainingClientInformationResolver"
+        p:id="InternalEmbeddedChainResolver" 
+        p:resolvers="#{getObject('shibboleth.oidc.ClientInformationResolvers')}"/>
+
+    <bean id="shibboleth.oidc.FilesystemClientInformationResolver" abstract="true"
+        class="net.shibboleth.idp.plugin.authn.oidc.rp.metadata.impl.FilesystemClientInformationResolver"/>
+
+    <!-- Wildcard import hook for plugins. -->
+    <!-- <import resource="classpath*:/META-INF/net/shibboleth/idp/plugin/oidc/op/service/clientinfo/postconfig.xml" /> -->
+
+</beans>
\ No newline at end of file
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
index fe8410a..f5a6720 100644
--- 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
@@ -92,6 +92,6 @@
 
     <!-- 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" />
+    <!-- <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/AuthorizationControllerTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AuthorizationControllerTest.java
index 03006ff..676c62c 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AuthorizationControllerTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AuthorizationControllerTest.java
@@ -60,8 +60,8 @@ import net.shibboleth.idp.session.context.SessionContext;
 import net.shibboleth.idp.ui.context.RelyingPartyUIContext;
 import net.shibboleth.oidc.profile.config.OIDCAuthorizationConfiguration.OIDCHttpRequestMethod;
 import net.shibboleth.oidc.profile.core.OIDCAuthenticationRequest;
-import net.shibboleth.oidc.profile.encoders.impl.AbstractOIDCMessageEncoder;
-import net.shibboleth.oidc.profile.encoders.impl.OIDCMessageEncoder;
+import net.shibboleth.oidc.profile.encoder.OIDCMessageEncoder;
+import net.shibboleth.oidc.profile.encoder.impl.AbstractOIDCMessageEncoder;
 import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
 import net.shibboleth.utilities.java.support.net.HttpServletSupport;
diff --git a/idp-oidc-rp-impl/src/test/resources/conf/authn/oidc-clientinfo-resolvers.xml b/idp-oidc-rp-impl/src/test/resources/conf/authn/oidc-clientinfo-resolvers.xml
new file mode 100644
index 0000000..99f54d9
--- /dev/null
+++ b/idp-oidc-rp-impl/src/test/resources/conf/authn/oidc-clientinfo-resolvers.xml
@@ -0,0 +1,23 @@
+<?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.ClientInformationResolvers">
+        <ref bean="ExampleFileResolver" />
+    </util:list>
+
+    <bean id="ExampleFileResolver"
+        class="net.shibboleth.idp.plugin.authn.oidc.rp.metadata.impl.FilesystemClientInformationResolver" p:id="ExampleFileResolver1"
+        c:metadata="metadata/oidc-clients.json"/>
+    
+</beans>
\ No newline at end of file
diff --git a/idp-oidc-rp-impl/src/test/resources/metadata/oidc-clients.json b/idp-oidc-rp-impl/src/test/resources/metadata/oidc-clients.json
new file mode 100644
index 0000000..0a8e6fa
--- /dev/null
+++ b/idp-oidc-rp-impl/src/test/resources/metadata/oidc-clients.json
@@ -0,0 +1,26 @@
+[
+  {
+    "issuer": "https://op.example.com",
+    "scope": "openid info profile email address phone",
+    "redirect_uris": [
+      "https://192.168.0.150/static"
+    ],
+    "client_id": "demo_rp",
+    "response_types": [
+      "id_token",
+      "id_token token"
+    ]
+  },
+  {
+    "issuer": "https://op2.example.com/",
+    "scope": "openid info profile email address phone",
+    "redirect_uris": [
+      "https://192.168.0.150/static2"
+    ],
+    "client_id": "demo_rp2",
+    "response_types": [
+      "id_token",
+      "id_token token"
+    ]
+  }
+]
\ No newline at end of file

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


More information about the commits mailing list