[java-idp-oidc] branch main updated: Add hook for source of allowed Scope.

Scott Cantor cantor.2 at osu.edu
Fri Feb 4 19:22:41 UTC 2022


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

scantor pushed a commit to branch main
in repository java-idp-oidc.

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

The following commit(s) were added to refs/heads/main by this push:
     new 8b3ed3ab Add hook for source of allowed Scope.
8b3ed3ab is described below

commit 8b3ed3abb99dfbcc0703f227c91f7b24eca3be8a
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Fri Feb 4 14:22:36 2022 -0500

    Add hook for source of allowed Scope.
---
 .../navigate/ClientInfoScopeLookupFunction.java    | 41 ++++++++++++++
 .../plugin/oidc/op/profile/impl/ValidateScope.java | 63 +++++++++++++++++-----
 .../META-INF/net.shibboleth.idp/postconfig.xml     | 13 +++++
 .../idp/flows/oidc/authorize/authorize-beans.xml   |  3 +-
 .../idp/flows/oidc/userinfo/userinfo-beans.xml     |  3 +-
 5 files changed, 107 insertions(+), 16 deletions(-)

diff --git a/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/context/navigate/ClientInfoScopeLookupFunction.java b/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/context/navigate/ClientInfoScopeLookupFunction.java
new file mode 100644
index 00000000..ff5451f9
--- /dev/null
+++ b/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/context/navigate/ClientInfoScopeLookupFunction.java
@@ -0,0 +1,41 @@
+/*
+ * 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.oidc.op.profile.context.navigate;
+
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.navigate.ContextDataLookupFunction;
+
+import com.nimbusds.oauth2.sdk.Scope;
+
+import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCMetadataContext;
+
+/** A function that returns {@link OIDCMetadataContext}. */
+public class ClientInfoScopeLookupFunction implements ContextDataLookupFunction<OIDCMetadataContext,Scope> {
+
+    /** {@inheritDoc} */
+    @Nullable
+    public Scope apply(@Nullable final OIDCMetadataContext input) {
+        if (input == null || input.getClientInformation() == null) {
+            return null;
+        }
+    
+        return input.getClientInformation().getMetadata().getScope();
+    }
+
+}
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/ValidateScope.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/ValidateScope.java
index 931efe44..a048ca54 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/ValidateScope.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/ValidateScope.java
@@ -33,9 +33,12 @@ import com.nimbusds.oauth2.sdk.Scope;
 import com.nimbusds.openid.connect.sdk.OIDCScopeValue;
 
 import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCAuthenticationResponseTokenClaimsContext;
+import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.ClientInfoScopeLookupFunction;
+import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.DefaultOIDCMetadataContextLookupFunction;
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.DefaultRequestResponseTypeLookupFunction;
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.DefaultRequestedScopeLookupFunction;
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.OIDCAuthenticationResponseContextLookupFunction;
+import net.shibboleth.idp.profile.context.navigate.RelyingPartyIdLookupFunction;
 import net.shibboleth.utilities.java.support.component.ComponentSupport;
 import net.shibboleth.utilities.java.support.logic.Constraint;
 
@@ -62,35 +65,66 @@ public class ValidateScope extends AbstractOIDCAuthenticationResponseAction {
     /** Class logger. */
     @Nonnull private Logger log = LoggerFactory.getLogger(ValidateScope.class);
 
+    /** Strategy used to obtain the relying party ID. */
+    @Nonnull private Function<ProfileRequestContext,String> relyingPartyIdLookupStrategy;
+    
     /** Strategy used to obtain the requested scope value. */
     @Nullable private Function<ProfileRequestContext,Scope> requestedScopesLookupStrategy;
 
+    /** Strategy used to obtain the scope allowed for the client. */
+    @Nonnull private Function<ProfileRequestContext,Scope> allowedScopesLookupStrategy;
+
     /** Strategy used to locate the {@link OIDCAuthenticationResponseTokenClaimsContext}. */
     @Nonnull
     private Function<ProfileRequestContext,OIDCAuthenticationResponseTokenClaimsContext>
     tokenClaimsContextLookupStrategy;
     
-    /**
-     * Constructor.
-     */
+    /** Constructor. */
     public ValidateScope() {
         requestedScopesLookupStrategy = new DefaultRequestedScopeLookupFunction();
-        
+        relyingPartyIdLookupStrategy = new RelyingPartyIdLookupFunction();
+        allowedScopesLookupStrategy = new ClientInfoScopeLookupFunction().compose(
+                new DefaultOIDCMetadataContextLookupFunction());
         tokenClaimsContextLookupStrategy =
                 new ChildContextLookup<>(OIDCAuthenticationResponseTokenClaimsContext.class).compose(
                         new OIDCAuthenticationResponseContextLookupFunction());
     }
 
+    /**
+     * Set the strategy used to obtain the relying party ID.
+     * 
+     * @param strategy lookup strategy
+     */
+    public void setRelyingPartyIdLookupStrategy(@Nonnull final Function<ProfileRequestContext,String> strategy) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        
+        relyingPartyIdLookupStrategy = Constraint.isNotNull(strategy,
+                "Relying party ID lookup strategy cannot be null");
+    }
+    
     /**
      * Set the strategy used to locate the requested scope to validate.
      * 
      * @param strategy lookup strategy
      */
-    public void setRequestedScopesLookupStrategy(@Nullable final Function<ProfileRequestContext, Scope> strategy) {
+    public void setRequestedScopesLookupStrategy(@Nullable final Function<ProfileRequestContext,Scope> strategy) {
         ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
         
         requestedScopesLookupStrategy = strategy;
     }
+
+
+    /**
+     * Set the strategy used to locate the allowed scope for the client.
+     * 
+     * @param strategy lookup strategy
+     */
+    public void setAllowedScopesLookupStrategy(@Nonnull final Function<ProfileRequestContext,Scope> strategy) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        
+        allowedScopesLookupStrategy = Constraint.isNotNull(strategy,
+                "Allowed scope lookyp strategy cannot be null");
+    }
     
     /**
      * Set the strategy used to locate the {@link OIDCAuthenticationResponseTokenClaimsContext} associated with a given
@@ -112,11 +146,12 @@ public class ValidateScope extends AbstractOIDCAuthenticationResponseAction {
     @Override
     protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
         
-        // These come from client metadata.
-        final Scope registeredScopes = getMetadataContext().getClientInformation().getMetadata().getScope();
-        if (registeredScopes == null || registeredScopes.isEmpty()) {
-            log.debug("{} No registered scopes for client {}, nothing to do", getLogPrefix(),
-                    getMetadataContext().getClientInformation().getID());
+        final String clientId = relyingPartyIdLookupStrategy.apply(profileRequestContext);
+        
+        // These typically come from metadata but may be supplemented or substituted from elsewhere.
+        final Scope allowedScopes = allowedScopesLookupStrategy.apply(profileRequestContext);
+        if (allowedScopes == null || allowedScopes.isEmpty()) {
+            log.debug("{} No allowed scope for client {}, nothing to do", getLogPrefix(), clientId);
             return;
         }
         
@@ -140,13 +175,13 @@ public class ValidateScope extends AbstractOIDCAuthenticationResponseAction {
         
         for (Iterator<Scope.Value> i = requestedScopes.iterator(); i.hasNext();) {
             final Scope.Value scope = i.next();
-            if (!registeredScopes.contains(scope)) {
-                log.warn("{} Removing requested but unregistered scope {} for RP {}", getLogPrefix(),
-                        scope.getValue(), getMetadataContext().getClientInformation().getID());
+            if (!allowedScopes.contains(scope)) {
+                log.warn("{} Removing requested but unregistered scope {} for RP {}", getLogPrefix(), scope.getValue(),
+                        clientId);
                 i.remove();
             } else if (previouslyGrantedScopes != null && !previouslyGrantedScopes.contains(scope)) {
                 log.warn("{} Removing requested but previously ungranted scope {} for RP {}", getLogPrefix(),
-                        scope.getValue(), getMetadataContext().getClientInformation().getID());
+                        scope.getValue(), clientId);
                 i.remove();
                 reducedRequestedScopes = true;
             }
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
index d3c65f34..7990b687 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
@@ -205,4 +205,17 @@
         p:httpClient="#{getObject('shibboleth.oidc.NonBrowser.HttpClient') ?: getObject('shibboleth.InternalHttpClient')}"
         p:httpClientSecurityParameters="#{getObject('shibboleth.oidc.NonBrowser.HttpClientSecurityParameters')}" />
     
+    <!--
+    This is a default souurce of "allowed" scope for access tokens. It's public to allow an overridden
+    source function to pull in the original metadata-registered scope easily.
+    -->
+    <bean id="shibboleth.oidc.DefaultAllowedScopeStrategy" parent="shibboleth.Functions.Compose">
+        <constructor-arg name="g">
+            <bean class="net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.ClientInfoScopeLookupFunction" />
+        </constructor-arg>
+        <constructor-arg name="f">
+            <bean class="net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.DefaultOIDCMetadataContextLookupFunction" />
+        </constructor-arg>
+    </bean>
+    
 </beans>
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/authorize/authorize-beans.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/authorize/authorize-beans.xml
index d6c8c96f..c9f7de9d 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/authorize/authorize-beans.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/authorize/authorize-beans.xml
@@ -171,7 +171,8 @@
     <bean id="ValidateResponseType" class="net.shibboleth.idp.plugin.oidc.op.profile.impl.ValidateResponseType"
         scope="prototype" />
 
-    <bean id="ValidateScope" class="net.shibboleth.idp.plugin.oidc.op.profile.impl.ValidateScope" scope="prototype" />
+    <bean id="ValidateScope" class="net.shibboleth.idp.plugin.oidc.op.profile.impl.ValidateScope" scope="prototype"
+        p:allowedScopesLookupStrategy="#{getObject('shibboleth.oidc.AllowedScopeStrategy') ?: getObject('shibboleth.oidc.DefaultAllowedScopeStrategy')}" />
 
     <bean id="PopulateIDTokenSignatureSigningParameters"
         class="net.shibboleth.idp.plugin.oidc.op.profile.impl.PopulateOIDCSignatureSigningParameters " scope="prototype"
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/userinfo/userinfo-beans.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/userinfo/userinfo-beans.xml
index c997d9f1..fd8dd794 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/userinfo/userinfo-beans.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/userinfo/userinfo-beans.xml
@@ -34,7 +34,8 @@
     <bean id="shibboleth.UserInfoRequestClientIDLookupStrategy"
         class="net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.UserInfoRequestClientIDLookupFunction" />
 
-    <bean id="ValidateScope" class="net.shibboleth.idp.plugin.oidc.op.profile.impl.ValidateScope" scope="prototype">
+    <bean id="ValidateScope" class="net.shibboleth.idp.plugin.oidc.op.profile.impl.ValidateScope" scope="prototype"
+            p:allowedScopesLookupStrategy="#{getObject('shibboleth.oidc.AllowedScopeStrategy') ?: getObject('shibboleth.oidc.DefaultAllowedScopeStrategy')}">
         <property name="requestedScopesLookupStrategy">
             <null/>
         </property>

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


More information about the commits mailing list