[java-idp-plugin-oidc-rp] branch main updated: Allow TLS server verification only for signed id_token

Phil Smart philip.smart at jisc.ac.uk
Wed Nov 30 12:25:50 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=8ab8b42c8e94123ce14b593e8b479c9f7e2ce321

The following commit(s) were added to refs/heads/main by this push:
     new 8ab8b42  Allow TLS server verification only for signed id_token
8ab8b42 is described below

commit 8ab8b42c8e94123ce14b593e8b479c9f7e2ce321
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Wed Nov 30 12:25:47 2022 +0000

    Allow TLS server verification only for signed id_token
    
     -  TLS server validation MAY be used to validate the issuer in place of
    checking the token signature
---
 .../RequiresSignatureVerificationPredicate.java    | 92 +++++++++++++++++++++
 ...tureValidationConfigurationLookupFunction.java} | 25 +++---
 ...atureValidationConfigurationLookupFunction.java | 93 ----------------------
 ...RequiresSignatureVerificationPredicateTest.java | 59 ++++++++++++++
 .../idp/plugin/authn/oidc/rp/impl/DecryptJWT.java  |  2 +-
 .../META-INF/net.shibboleth.idp/postconfig.xml     |  9 ++-
 .../oidc-relying-party-authn-beans.xml             | 80 +++++++++----------
 .../oidc-relying-party-authn-flow.xml              |  9 +--
 .../authn/oidc/rp/conf/authn/oidc-rp.properties    |  3 +
 9 files changed, 220 insertions(+), 152 deletions(-)

diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/logic/RequiresSignatureVerificationPredicate.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/logic/RequiresSignatureVerificationPredicate.java
new file mode 100644
index 0000000..226b666
--- /dev/null
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/logic/RequiresSignatureVerificationPredicate.java
@@ -0,0 +1,92 @@
+/*
+ * 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.config.logic;
+
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.shibboleth.idp.plugin.authn.oidc.rp.context.AbstractAuthenticatableOIDCContext;
+import net.shibboleth.utilities.java.support.annotation.ParameterName;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+/**
+ * Is successful TLS credential verficiation enough to validate the JWT in question? Defaults to true — 
+ * signature verification is required.
+ */
+public class RequiresSignatureVerificationPredicate implements Predicate<MessageContext> {
+    
+    /** Class logger. */
+    @Nonnull private final Logger log = LoggerFactory.getLogger(RequiresSignatureVerificationPredicate.class);
+    
+    /** 
+     * If true and the {@link AbstractAuthenticatableOIDCContext} is authenticated, the predicate 
+     * returns false (no additional signature verification required).
+     */
+    private boolean tlsServerValidationOnly;
+    
+    /** Strategy used to lookup the {@link AbstractAuthenticatableOIDCContext} to test. */
+    @Nonnull 
+    private final Function<MessageContext, AbstractAuthenticatableOIDCContext> authenticatableOIDCContextLookupStrategy;
+
+    
+    /**
+     * 
+     * Constructor.
+     *
+     * @param strategy the strategy used to locate the {@link AbstractAuthenticatableOIDCContext} to test
+     */
+    public RequiresSignatureVerificationPredicate(@Nonnull @ParameterName(name="authenticatableOIDCContextLookupStrategy") 
+            final Function<MessageContext, AbstractAuthenticatableOIDCContext> strategy) {
+        super();
+        authenticatableOIDCContextLookupStrategy = Constraint.isNotNull(strategy,
+                "authenticatableOIDCContextLookupStrategy can not be null");
+    }
+    
+    /**
+     * Set whether TLS server validation is sufficient (true), or if JWT signature verification should 
+     * still occur (false).
+     * 
+     * @param flag the flag
+     */
+    public void setTlsServerValidationOnly(final boolean flag) {
+        tlsServerValidationOnly = flag;
+    }
+
+    @Override
+    public boolean test(@Nonnull final MessageContext msgContext) {
+       
+        final AbstractAuthenticatableOIDCContext authContext = 
+                authenticatableOIDCContextLookupStrategy.apply(msgContext);
+        
+        if (tlsServerValidationOnly && authContext.isAuthenticated()) {
+            // No further validation required.
+            log.debug("TLS server validation was successful and sufficient, no further signature processing performed");
+            return false;
+        }       
+        
+        return true;
+        
+    }
+
+}
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/IDTokenSignatureValidationConfigurationLookupFunction.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/JWTSignatureValidationConfigurationLookupFunction.java
similarity index 78%
rename from idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/IDTokenSignatureValidationConfigurationLookupFunction.java
rename to idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/JWTSignatureValidationConfigurationLookupFunction.java
index 7853405..79076f7 100644
--- a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/IDTokenSignatureValidationConfigurationLookupFunction.java
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/JWTSignatureValidationConfigurationLookupFunction.java
@@ -22,25 +22,25 @@ import java.util.List;
 
 import javax.annotation.Nullable;
 
-import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.messaging.context.MessageContext;
 
 import net.shibboleth.idp.profile.config.ProfileConfiguration;
 import net.shibboleth.idp.profile.config.SecurityConfiguration;
 import net.shibboleth.idp.profile.context.RelyingPartyContext;
-import net.shibboleth.idp.profile.context.navigate.AbstractRelyingPartyLookupFunction;
+import net.shibboleth.idp.profile.context.navigate.messaging.AbstractRelyingPartyLookupFunction;
 import net.shibboleth.idp.relyingparty.RelyingPartyConfigurationResolver;
 import net.shibboleth.oidc.profile.config.OIDCSecurityConfiguration;
 import net.shibboleth.oidc.security.JWTSignatureValidationConfiguration;
 
 /**
- * A function that returns a {@link JWTSignatureValidationConfiguration} list for id_token signature validation by way
+ * A function that returns a {@link JWTSignatureValidationConfiguration} list for JWS validation by way
  * of various lookup strategies. 
  * 
  * <p>
  * If a specific setting is unavailable, a null value is returned.
  * </p>
  */
-public class IDTokenSignatureValidationConfigurationLookupFunction 
+public class JWTSignatureValidationConfigurationLookupFunction 
             extends AbstractRelyingPartyLookupFunction<List<JWTSignatureValidationConfiguration>> {
 
     /** A resolver for default security configurations. */
@@ -59,17 +59,21 @@ public class IDTokenSignatureValidationConfigurationLookupFunction
     /** {@inheritDoc} */
     @Override
     @Nullable
-    public List<JWTSignatureValidationConfiguration> apply(@Nullable final ProfileRequestContext input) {
+    public List<JWTSignatureValidationConfiguration> apply(@Nullable final MessageContext input) {
 
         final List<JWTSignatureValidationConfiguration> configs = new ArrayList<>();
 
         final RelyingPartyContext rpc = getRelyingPartyContextLookupStrategy().apply(input);
         if (rpc != null) {
             final ProfileConfiguration pc = rpc.getProfileConfig();
-            if (pc != null && pc.getSecurityConfiguration(input) instanceof OIDCSecurityConfiguration
-                    && ((OIDCSecurityConfiguration) pc.getSecurityConfiguration(input))
-                            .getJwtSignatureValidationConfiguration() != null) {
-                configs.add(((OIDCSecurityConfiguration) pc.getSecurityConfiguration(input))
+            if (pc != null && 
+                    pc.getSecurityConfiguration(getProfileRequestContextLookupStrategy().apply(input)) 
+                        instanceof OIDCSecurityConfiguration
+                    && ((OIDCSecurityConfiguration) pc.getSecurityConfiguration(
+                            getProfileRequestContextLookupStrategy().apply(input)))
+                    .getJwtSignatureValidationConfiguration() != null) {
+                configs.add(((OIDCSecurityConfiguration) pc.getSecurityConfiguration(
+                        getProfileRequestContextLookupStrategy().apply(input)))
                         .getJwtSignatureValidationConfiguration());
             }
         }
@@ -77,7 +81,8 @@ public class IDTokenSignatureValidationConfigurationLookupFunction
         // Check for a per-profile default (relying party independent) config.
         if (input != null && rpResolver != null) {
             final SecurityConfiguration defaultConfig =
-                    rpResolver.getDefaultSecurityConfiguration(input.getProfileId());
+                    rpResolver.getDefaultSecurityConfiguration(
+                            getProfileRequestContextLookupStrategy().apply(input).getProfileId());
             if (defaultConfig instanceof OIDCSecurityConfiguration
                     && ((OIDCSecurityConfiguration) defaultConfig)
                     .getJwtSignatureValidationConfiguration() != null) {
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/UserInfoTokenSignatureValidationConfigurationLookupFunction.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/UserInfoTokenSignatureValidationConfigurationLookupFunction.java
deleted file mode 100644
index be202e4..0000000
--- a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/UserInfoTokenSignatureValidationConfigurationLookupFunction.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.config.navigate;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.annotation.Nullable;
-
-import org.opensaml.profile.context.ProfileRequestContext;
-
-import net.shibboleth.idp.profile.config.ProfileConfiguration;
-import net.shibboleth.idp.profile.config.SecurityConfiguration;
-import net.shibboleth.idp.profile.context.RelyingPartyContext;
-import net.shibboleth.idp.profile.context.navigate.AbstractRelyingPartyLookupFunction;
-import net.shibboleth.idp.relyingparty.RelyingPartyConfigurationResolver;
-import net.shibboleth.oidc.profile.config.OIDCSecurityConfiguration;
-import net.shibboleth.oidc.security.JWTSignatureValidationConfiguration;
-
-/**
- * A function that returns a {@link JWTSignatureValidationConfiguration} list for UserInfo token signature validation 
- * by way of various lookup strategies. 
- * 
- * <p>
- * If a specific setting is unavailable, a null value is returned.
- * </p>
- */
-public class UserInfoTokenSignatureValidationConfigurationLookupFunction 
-            extends AbstractRelyingPartyLookupFunction<List<JWTSignatureValidationConfiguration>> {
-
-    /** A resolver for default security configurations. */
-    @Nullable
-    private RelyingPartyConfigurationResolver rpResolver;
-
-    /**
-     * Set the resolver for default security configurations.
-     * 
-     * @param resolver the resolver to use
-     */
-    public void setRelyingPartyConfigurationResolver(@Nullable final RelyingPartyConfigurationResolver resolver) {
-        rpResolver = resolver;
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    @Nullable
-    public List<JWTSignatureValidationConfiguration> apply(@Nullable final ProfileRequestContext input) {
-
-        final List<JWTSignatureValidationConfiguration> configs = new ArrayList<>();
-
-        final RelyingPartyContext rpc = getRelyingPartyContextLookupStrategy().apply(input);
-        if (rpc != null) {
-            final ProfileConfiguration pc = rpc.getProfileConfig();
-            if (pc != null && pc.getSecurityConfiguration(input) instanceof OIDCSecurityConfiguration
-                    && ((OIDCSecurityConfiguration) pc.getSecurityConfiguration(input))
-                            .getJwtSignatureValidationConfiguration() != null) {
-                configs.add(((OIDCSecurityConfiguration) pc.getSecurityConfiguration(input))
-                        .getJwtSignatureValidationConfiguration());
-            }
-        }
-
-        // Check for a per-profile default (relying party independent) config.
-        if (input != null && rpResolver != null) {
-            final SecurityConfiguration defaultConfig =
-                    rpResolver.getDefaultSecurityConfiguration(input.getProfileId());
-            if (defaultConfig instanceof OIDCSecurityConfiguration
-                    && ((OIDCSecurityConfiguration) defaultConfig)
-                    .getJwtSignatureValidationConfiguration() != null) {
-                configs.add(
-                        ((OIDCSecurityConfiguration) defaultConfig)
-                        .getJwtSignatureValidationConfiguration());
-            }
-        }
-        // TODO: Support for Global Default configuration?
-        return configs;
-    }
-}
-
diff --git a/idp-oidc-rp-api/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/logic/RequiresSignatureVerificationPredicateTest.java b/idp-oidc-rp-api/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/logic/RequiresSignatureVerificationPredicateTest.java
new file mode 100644
index 0000000..7776f73
--- /dev/null
+++ b/idp-oidc-rp-api/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/logic/RequiresSignatureVerificationPredicateTest.java
@@ -0,0 +1,59 @@
+
+package net.shibboleth.idp.plugin.authn.oidc.rp.config.logic;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.testng.annotations.Test;
+
+import net.shibboleth.idp.plugin.authn.oidc.rp.context.AbstractAuthenticatableOIDCContext;
+
+public class RequiresSignatureVerificationPredicateTest {
+    
+    /** The predicate to test*/
+    private RequiresSignatureVerificationPredicate predicate;
+    
+    
+    
+    @Test
+    public void testSignatureVerificationRequired_TLSOnlyDisabled() {
+        predicate = new RequiresSignatureVerificationPredicate(msg -> new MockAuthenticatableContext(true));
+        predicate.setTlsServerValidationOnly(false);
+        
+        assertTrue(predicate.test(new MessageContext()));
+    }
+    
+    @Test
+    public void testSignatureVerificationRequired_TLSOnlyDisabled_ContextNotAuthenticated() {
+        predicate = new RequiresSignatureVerificationPredicate(msg -> new MockAuthenticatableContext(false));
+        predicate.setTlsServerValidationOnly(false);
+        
+        assertTrue(predicate.test(new MessageContext()));
+    }
+    
+    @Test
+    public void testSignatureVerificationRequired_TLSOnlyEnabled_ContextNotAuthenticated() {
+        predicate = new RequiresSignatureVerificationPredicate(msg -> new MockAuthenticatableContext(false));
+        predicate.setTlsServerValidationOnly(true);
+        
+        assertTrue(predicate.test(new MessageContext()));
+    }
+    
+    @Test
+    public void testSignatureVerificationNotRequired_TLSOnlyEnabled() {
+        predicate = new RequiresSignatureVerificationPredicate(msg -> new MockAuthenticatableContext(true));
+        predicate.setTlsServerValidationOnly(true);
+        
+        assertFalse(predicate.test(new MessageContext()));
+    }
+    
+    /** Mock Authenticatable context.*/
+    private static class MockAuthenticatableContext extends AbstractAuthenticatableOIDCContext {
+                
+        private MockAuthenticatableContext(final boolean authn) {
+            super.setAuthenticated(authn);
+        }
+    }
+
+}
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/DecryptJWT.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/DecryptJWT.java
index 982e706..226c998 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/DecryptJWT.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/DecryptJWT.java
@@ -144,7 +144,7 @@ public class DecryptJWT extends AbstractProfileAction {
         
         encryptedJwt = jwtTokenLookupStrategy.apply(profileRequestContext);
         if (encryptedJwt == null) {
-            log.debug("{} JWT was not an Encrypted, nothing to decrypt",
+            log.debug("{} JWT was not encrypted, nothing to decrypt",
                     getLogPrefix());
             return false;
         }
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 0b6cc94..3e7dff0 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
@@ -41,7 +41,11 @@
     <bean id="shibboleth.ChildLookup.OIDCPeerEntityContext"
         class="org.opensaml.messaging.context.navigate.ChildContextLookup"
         c:type="#{ T(net.shibboleth.idp.plugin.authn.oidc.rp.context.OIDCPeerEntityContext) }" />
-
+        
+    <bean id="shibboleth.ChildLookup.AccessTokenResponseContext"
+        class="org.opensaml.messaging.context.navigate.ChildContextLookup"
+        c:type="#{ T(net.shibboleth.idp.plugin.authn.oidc.rp.context.AccessTokenResponseContext) }" />
+        
     <bean id="shibboleth.ChildLookup.OIDCProviderMetadataContextFromOutbound" parent="shibboleth.Functions.Compose">
         <constructor-arg name="g">
             <ref bean="shibboleth.ChildLookup.OIDCProviderMetadataContext" />
@@ -134,6 +138,9 @@
     <bean id="shibboleth.MessageLookup.oidc.rp.AuthenticationResponse"
         class="org.opensaml.messaging.context.navigate.MessageLookup"
         c:type="#{ T(com.nimbusds.openid.connect.sdk.AuthenticationResponse) }" />
+        
+    <bean id="shibboleth.ChildLookup.AccessTokenResponseFromInbound" parent="shibboleth.Functions.Compose"
+        c:g-ref="shibboleth.ChildLookup.AccessTokenResponseContext" c:f-ref="shibboleth.MessageContextLookup.Inbound" />
     
     <!-- Aliases to use in the flow config -->
     <alias name="shibboleth.ChildLookup.Proxy.MessageContextLookup.Inbound" alias="InboundMessageContextFromRootPRC"/>
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 21a8916..9c21aae 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
@@ -462,34 +462,29 @@
 
     <!-- ID TOKEN Signature Validation -->
 
-    <bean id="PopulateIDTokenSignatureValidationParameters" parent="NestedWebFlowProfileActionAdaptor"
-        scope="prototype">
-        <constructor-arg>
-            <bean class="net.shibboleth.oidc.profile.impl.PopulateJWTSignatureValidationParameters"
-                c:strategy-ref="shibboleth.MessageContextLookup.Inbound"
-                p:configurationLookupStrategy-ref="shibboleth.authn.oidc.rp.IDTokenSignatureValidationConfigurationLookup"
-                p:signatureValidationParametersResolver-ref="shibboleth.authn.oidc.rp.IDTokenJwtSignatureValidationParametersResolver" />
-        </constructor-arg>
-    </bean>
-
-    <bean id="shibboleth.authn.oidc.rp.IDTokenJwtSignatureValidationParametersResolver"
-        class="net.shibboleth.oidc.security.impl.BasicJWTSignatureValidationParametersResolver" />
-
-    <bean id="shibboleth.authn.oidc.rp.IDTokenSignatureValidationConfigurationLookup"
-        class="net.shibboleth.idp.plugin.authn.oidc.rp.config.navigate.IDTokenSignatureValidationConfigurationLookupFunction"
-        p:relyingPartyConfigurationResolver-ref="shibboleth.RelyingPartyConfigurationResolver" />
-
-    <!-- TODO should we handle claims validation here as well? -->
-    <bean id="HandleIDTokenValidation" parent="NestedWebFlowMessageHandlerAdaptor" scope="prototype"
+    <bean id="IDTokenSignatureValidation" parent="NestedWebFlowMessageHandlerAdaptor" scope="prototype"
         c:executionDirection="INBOUND">
         <constructor-arg>
-            <bean class="org.opensaml.messaging.handler.impl.BasicMessageHandlerChain">
+            <bean class="org.opensaml.messaging.handler.impl.BasicMessageHandlerChain"
+                p:activationCondition-ref="IDTokenRequiresSignatureVerificationCondition">
                 <property name="handlers">
                     <list>
+                    
+                        <bean scope="prototype" class="net.shibboleth.oidc.profile.impl.PopulateJWTSignatureValidationParametersHandler">
+                            <property name="signatureValidationParametersResolver">
+                                <bean class="net.shibboleth.oidc.security.impl.BasicJWTSignatureValidationParametersResolver" />
+                            </property>
+                            <property name="configurationLookupStrategy">
+                                <bean class="net.shibboleth.idp.plugin.authn.oidc.rp.config.navigate.JWTSignatureValidationConfigurationLookupFunction"
+                                    p:relyingPartyConfigurationResolver-ref="shibboleth.RelyingPartyConfigurationResolver" />
+                            </property>                            
+                        </bean>                        
+                        
                         <bean
                             class="net.shibboleth.idp.plugin.authn.oidc.rp.metadata.impl.OIDCProviderMetadataLookupHandler"
                             scope="prototype" p:copyContextStrategy-ref="OutboundOIDCMetadataContextLookup"
                             p:providerMetadataResolver-ref="shibboleth.authn.oidc.rp.ProviderMetadataResolver" />
+                            
                         <bean class="net.shibboleth.oidc.security.impl.JWTMessageSignatureSecurityHandler"
                             scope="prototype">
                             <property name="jwtTokenLookupStrategy">
@@ -503,13 +498,17 @@
                                 <ref bean="shibboleth.ChildLookup.OIDCProviderMetadataFromPeerEntityContext" />
                             </property>
                         </bean>
+                        
                     </list>
                 </property>
             </bean>
         </constructor-arg>
     </bean>
-
-
+    
+    <bean id="IDTokenRequiresSignatureVerificationCondition" scope="prototype" 
+        class="net.shibboleth.idp.plugin.authn.oidc.rp.config.logic.RequiresSignatureVerificationPredicate"
+        p:tlsServerValidationOnly="%{idp.authn.oidc.rp.client.idtoken.tlsServerValidationOnly:false}"
+        c:authenticatableOIDCContextLookupStrategy-ref="shibboleth.ChildLookup.AccessTokenResponseContext"/>
 
     <bean id="OutboundOIDCMetadataContextLookup" parent="shibboleth.Functions.Compose">
         <constructor-arg name="g">
@@ -723,34 +722,33 @@
         </property>
     </bean>
 
-    <bean id="PopulateUserInfoTokenSignatureValidationParameters" parent="NestedWebFlowProfileActionAdaptor"
-        scope="prototype">
-        <constructor-arg>
-            <bean class="net.shibboleth.oidc.profile.impl.PopulateJWTSignatureValidationParameters"
-                c:strategy-ref="shibboleth.MessageContextLookup.Inbound"
-                p:configurationLookupStrategy-ref="UserInfoTokenSignatureValidationConfigurationLookup"
-                p:signatureValidationParametersResolver-ref="UserInfoTokenJwtSignatureValidationParametersResolver" />
-        </constructor-arg>
-    </bean>
-
-    <bean id="UserInfoTokenJwtSignatureValidationParametersResolver"
-        class="net.shibboleth.oidc.security.impl.BasicJWTSignatureValidationParametersResolver" />
-
-    <bean id="UserInfoTokenSignatureValidationConfigurationLookup"
-        class="net.shibboleth.idp.plugin.authn.oidc.rp.config.navigate.UserInfoTokenSignatureValidationConfigurationLookupFunction"
-        p:relyingPartyConfigurationResolver-ref="shibboleth.RelyingPartyConfigurationResolver" />
-
-    <bean id="HandleUserInfoTokenValidation" parent="NestedWebFlowMessageHandlerAdaptor" scope="prototype"
+    <!-- 
+    Note, this is identical in setup to the id_token signature validation flow as they both use the same config and trust engine.
+    the only difference is the location of the JWT to validate. Maybe they could be merged. Also, the populate steps may or may not
+    have already been performed in the id_token validation depending on the activation condition, so maybe those could be consolidated.
+    -->
+    <bean id="UserInfoTokenSignatureValidation" parent="NestedWebFlowMessageHandlerAdaptor" scope="prototype"
         c:executionDirection="INBOUND">
         <constructor-arg>
             <bean class="org.opensaml.messaging.handler.impl.BasicMessageHandlerChain">
                 <property name="handlers">
                     <list>
-                        <!-- FIXME Do we need to copy this again, it was in the id_token sig validation -->
+                        <bean scope="prototype" class="net.shibboleth.oidc.profile.impl.PopulateJWTSignatureValidationParametersHandler">
+                            <property name="signatureValidationParametersResolver">
+                                <bean class="net.shibboleth.oidc.security.impl.BasicJWTSignatureValidationParametersResolver" />
+                            </property>
+                            <property name="configurationLookupStrategy">
+                                <bean class="net.shibboleth.idp.plugin.authn.oidc.rp.config.navigate.JWTSignatureValidationConfigurationLookupFunction"
+							        p:relyingPartyConfigurationResolver-ref="shibboleth.RelyingPartyConfigurationResolver" />
+                            </property>                            
+                        </bean>  
+                        
                         <bean
                             class="net.shibboleth.idp.plugin.authn.oidc.rp.metadata.impl.OIDCProviderMetadataLookupHandler"
                             scope="prototype" p:copyContextStrategy-ref="OutboundOIDCMetadataContextLookup"
                             p:providerMetadataResolver-ref="shibboleth.authn.oidc.rp.ProviderMetadataResolver" />
+                            
+                            
                         <bean class="net.shibboleth.oidc.security.impl.JWTMessageSignatureSecurityHandler"
                             scope="prototype">
                             <property name="jwtTokenLookupStrategy">
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 b0d551a..d8ac1d0 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
@@ -118,9 +118,8 @@
         <evaluate expression="ExtractIDTokenFromTokenResponse" />
         <evaluate expression="PopulateIDTokenDecryptionParameters" />
         <evaluate expression="DecryptJWT" />
-        <evaluate expression="PopulateIDTokenSignatureValidationParameters" />
-        <!-- TODO Not sure if HandleIDTokenValidation needs to be a message chain? -->
-        <evaluate expression="HandleIDTokenValidation" />
+        <!--Validation of the JWT signature is optional if TLS server validation was performed -->
+        <evaluate expression="IDTokenSignatureValidation" />
         <evaluate expression="ValidateIDTokenClaims" />
         <evaluate expression="TokenResponsePopulateAuditContext" />
         <evaluate expression="'proceed'" />
@@ -135,7 +134,6 @@
 
     <action-state id="UserInfoRequest">
         <evaluate expression="UserInfoEndpointLookup" />
-        <!-- Something needs to check TLS server certificate? Not sure, performed by HTTP Client -->
         <evaluate expression="'proceed'" />
         <transition on="proceed" to="CheckUserInfoResponseType" />
     </action-state>
@@ -150,8 +148,7 @@
     <action-state id="ValidateUserInfoJWT">
         <evaluate expression="PopulateUserInfoDecryptionParameters" />
         <evaluate expression="DecryptUserInfoJWT" />
-        <evaluate expression="PopulateUserInfoTokenSignatureValidationParameters" />
-        <evaluate expression="HandleUserInfoTokenValidation" />
+        <evaluate expression="UserInfoTokenSignatureValidation" />
         <evaluate expression="ValidateUserInfoTokenClaims" />
         <evaluate expression="PostJWTUserInfoResponsePopulateAuditContext" />
         <evaluate expression="'proceed'" />
diff --git a/idp-oidc-rp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/oidc/rp/conf/authn/oidc-rp.properties b/idp-oidc-rp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/oidc/rp/conf/authn/oidc-rp.properties
index 3b769db..188f1b7 100644
--- a/idp-oidc-rp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/oidc/rp/conf/authn/oidc-rp.properties
+++ b/idp-oidc-rp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/oidc/rp/conf/authn/oidc-rp.properties
@@ -16,6 +16,9 @@ idp.authn.oidc.rp.client.redirecturl.allowedOrigins = https://localhost:8443
 #idp.authn.oidc.rp.client.requestobject.encrypted = false
 #idp.authn.oidc.rp.client.requestobject.signed = true
 
+## If true and the token was retrieved using TLS with server validation, JWS signature checking will be skipped.
+#idp.authn.oidc.rp.client.idtoken.tlsServerValidationOnly = false
+
 #idp.authn.oidc.rp.client.userinfo.enabled = true
 #idp.authn.oidc.rp.client.userinfo.requireJWTResponse = false
 

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


More information about the commits mailing list