[java-idp-plugin-oidc-rp] branch main updated: Add UserInfo token signature check

Phil Smart philip.smart at jisc.ac.uk
Tue Jun 7 15:33:07 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=17d82b7b3586f2a59b127a28faff21d685f1540e

The following commit(s) were added to refs/heads/main by this push:
     new 17d82b7  Add UserInfo token signature check
17d82b7 is described below

commit 17d82b7b3586f2a59b127a28faff21d685f1540e
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Tue Jun 7 16:33:01 2022 +0100

    Add UserInfo token signature check
---
 ...atureValidationConfigurationLookupFunction.java | 94 ++++++++++++++++++++++
 .../impl/OIDCProviderMetadataLookupHandler.java    |  4 +-
 .../oidc-relying-party-authn-beans.xml             | 77 ++++++++++++++----
 .../oidc-relying-party-authn-flow.xml              | 18 +++--
 .../plugin/authn/oidc/rp/impl/OIDCRPFlowTest.java  | 67 +++++++++++----
 5 files changed, 222 insertions(+), 38 deletions(-)

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
new file mode 100644
index 0000000..19ac0c0
--- /dev/null
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/UserInfoTokenSignatureValidationConfigurationLookupFunction.java
@@ -0,0 +1,94 @@
+/*
+ * 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 com.nimbusds.jwt.SignedJWT;
+
+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.SignatureValidationConfiguration;
+
+/**
+ * A function that returns a {@link SignatureValidationConfiguration} 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<SignatureValidationConfiguration<SignedJWT>>> {
+
+    /** 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<SignatureValidationConfiguration<SignedJWT>> apply(@Nullable final ProfileRequestContext input) {
+
+        final List<SignatureValidationConfiguration<SignedJWT>> 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))
+                            .getUserInfoTokenJwtSignatureValidationConfig() != null) {
+                configs.add(((OIDCSecurityConfiguration) pc.getSecurityConfiguration(input))
+                        .getUserInfoTokenJwtSignatureValidationConfig());
+            }
+        }
+
+        // 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)
+                    .getUserInfoTokenJwtSignatureValidationConfig() != null) {
+                configs.add(
+                        ((OIDCSecurityConfiguration) defaultConfig).getUserInfoTokenJwtSignatureValidationConfig());
+            }
+        }
+        // TODO: Support for Global Default configuration?
+        return configs;
+    }
+}
+
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 3ecae14..5a161bb 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
@@ -141,7 +141,9 @@ public class OIDCProviderMetadataLookupHandler extends AbstractMessageHandler {
         final OIDCProviderMetadataContext existingMetadataCtx = resolveExisting(messageContext,
                 entityCtx.getIdentifier());
         if (existingMetadataCtx != null) {
-            log.info("{} Resolved existing provider metadata context, re-using it", getLogPrefix());
+            log.info("{} Resolved existing provider metadata context, removing existing "
+                    + "and re-using it", getLogPrefix());
+            entityCtx.removeSubcontext(OIDCProviderMetadataContext.class);
             entityCtx.addSubcontext(existingMetadataCtx);
             return;
         }
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 bcc7a5f..7c95664 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
@@ -262,14 +262,14 @@
     </bean>
 
     <bean id="JWTDecryptionParametersResolver"
-        class="net.shibboleth.oidc.security.impl.DefaultJWTDecryptionParametersResolver"/>
+        class="net.shibboleth.oidc.security.impl.DefaultJWTDecryptionParametersResolver" />
 
     <bean id="IDTokenDecryptionConfigurationLookup" lazy-init="true"
         class="net.shibboleth.idp.plugin.authn.oidc.rp.config.navigate.IDTokenDecryptionConfigurationLookupFunction"
         p:relyingPartyConfigurationResolver-ref="shibboleth.RelyingPartyConfigurationResolver" />
 
-    <bean id="IDTokenInAccessTokenUpdateStrategy" 
-        class="net.shibboleth.idp.plugin.authn.oidc.rp.config.navigate.IDTokenInAccessTokenUpdateStrategy"/>
+    <bean id="IDTokenInAccessTokenUpdateStrategy"
+        class="net.shibboleth.idp.plugin.authn.oidc.rp.config.navigate.IDTokenInAccessTokenUpdateStrategy" />
 
     <bean id="DecryptJWT" parent="NestedWebFlowProfileActionAdaptor" scope="prototype">
         <constructor-arg>
@@ -281,7 +281,7 @@
                         c:expression="#input.getInboundMessageContext().getSubcontext(T(net.shibboleth.idp.plugin.authn.oidc.rp.context.AccessTokenResponseContext)).getIdToken()" />
                 </property>
                 <property name="jwtUpdateStrategy">
-                    <ref bean="IDTokenInAccessTokenUpdateStrategy"/>
+                    <ref bean="IDTokenInAccessTokenUpdateStrategy" />
                 </property>
             </bean>
         </constructor-arg>
@@ -501,10 +501,11 @@
 
     <bean id="shibboleth.authn.oidc.rp.DefaultUserInfoRequestEncoder" scope="prototype"
         class="net.shibboleth.idp.plugin.authn.oidc.rp.encoding.impl.DefaultUserInfoRequestEncoder" />
-        
+
     <!-- UserInfo decryption and signature check if JWT type -->
-    
-        <!-- FIXME: (might not be an issue) Will populate the same security params context as the id_token, but overright the decryption config -->
+
+    <!-- FIXME: (might not be an issue) Will populate the same security params context as the id_token, but overright the 
+        decryption config -->
     <bean id="PopulateUserInfoDecryptionParameters" parent="NestedWebFlowProfileActionAdaptor" scope="prototype">
         <constructor-arg>
             <bean class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.PopulateJWTDecryptionParameters"
@@ -517,8 +518,8 @@
         class="net.shibboleth.idp.plugin.authn.oidc.rp.config.navigate.UserInfoDecryptionConfigurationLookupFunction"
         p:relyingPartyConfigurationResolver-ref="shibboleth.RelyingPartyConfigurationResolver" />
 
-    <bean id="UserInfoInUserInfoResponseContextUpdateStrategy" 
-        class="net.shibboleth.idp.plugin.authn.oidc.rp.config.navigate.UserInfoInUserInfoResponseContextUpdateStrategy"/>
+    <bean id="UserInfoInUserInfoResponseContextUpdateStrategy"
+        class="net.shibboleth.idp.plugin.authn.oidc.rp.config.navigate.UserInfoInUserInfoResponseContextUpdateStrategy" />
 
     <bean id="DecryptUserInfoJWT" parent="NestedWebFlowProfileActionAdaptor" scope="prototype">
         <constructor-arg>
@@ -530,13 +531,61 @@
                         c:expression="#input.getInboundMessageContext().getSubcontext(T(net.shibboleth.idp.plugin.authn.oidc.rp.context.UserInfoResponseContext)).getUserInfo().getResponseJwt()" />
                 </property>
                 <property name="jwtUpdateStrategy">
-                    <ref bean="UserInfoInUserInfoResponseContextUpdateStrategy"/>
+                    <ref bean="UserInfoInUserInfoResponseContextUpdateStrategy" />
                 </property>
             </bean>
         </constructor-arg>
     </bean>
-    
-    <!-- Done UserInfo decryption -->
+
+    <bean id="PopulateUserInfoTokenSignatureValidationParameters" parent="NestedWebFlowProfileActionAdaptor"
+        scope="prototype">
+        <constructor-arg>
+            <bean class="net.shibboleth.oidc.security.impl.PopulateJWTSignatureValidationParameters"
+                p:configurationLookupStrategy-ref="UserInfoTokenSignatureValidationConfigurationLookup"
+                p:signatureValidationParametersResolver-ref="UserInfoTokenJwtSignatureValidationParametersResolver" />
+        </constructor-arg>
+    </bean>
+
+    <bean id="UserInfoTokenJwtSignatureValidationParametersResolver"
+        class="net.shibboleth.oidc.security.impl.OIDCProviderConfigurationSignatureValidationParametersResolver" />
+
+    <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"
+        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
+                            class="net.shibboleth.idp.plugin.authn.oidc.rp.metadata.impl.OIDCProviderMetadataLookupHandler"
+                            scope="prototype" p:copyContextStrategy-ref="OutboundOIDCMetadataContextLookup"
+                            p:providerMetadataResolver-ref="shibboleth.oidc.rp.ProviderMetadataResolver" />
+                        <bean class="net.shibboleth.oidc.security.impl.JWTMessageSignatureSecurityHandler"
+                            scope="prototype">
+                            <property name="jwtTokenLookupStrategy">
+                                <bean
+                                    class="net.shibboleth.idp.profile.context.navigate.SpringExpressionContextLookupFunction"
+                                    c:_0="#{ T(org.opensaml.messaging.context.MessageContext) }"
+                                    c:outputType="#{T(com.nimbusds.jwt.SignedJWT)}"
+                                    c:expression="#input.getSubcontext(T(net.shibboleth.idp.plugin.authn.oidc.rp.context.UserInfoResponseContext)).getUserInfo().getResponseJwt()" />
+                            </property>
+                            <property name="providerMetadataLookupStrategy">
+                                <ref bean="shibboleth.ChildLookup.OIDCProviderMetadataFromPeerEntityContext" />
+                            </property>
+                        </bean>
+                        <!-- TODO WE NEED TO CHECK JWT CLAIMS HERE see spec-->
+                    </list>
+                </property>
+            </bean>
+        </constructor-arg>
+    </bean>
+
+
+    <!-- UserInfo Decryption and Signature Validation Done -->
 
 
     <bean id="ValidateUserInfoClaims" parent="NestedWebFlowProfileActionAdaptor" scope="prototype"
@@ -549,8 +598,8 @@
         p:authenticationContextLookupStrategy-ref="ParentAuthenticiationContextLookup" />
 
 
-    <bean id="CheckUserInfoPlainResponseTypeCondition" 
-        class="net.shibboleth.idp.plugin.authn.oidc.rp.messaging.context.logic.UserInfoPlainResponseTypeCondition"/>
+    <bean id="CheckUserInfoPlainResponseTypeCondition"
+        class="net.shibboleth.idp.plugin.authn.oidc.rp.messaging.context.logic.UserInfoPlainResponseTypeCondition" />
 
     <!-- UserInfo response JWT validation -->
 
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 75638c2..911b391 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,8 +118,7 @@
         <transition on="proceed" to="CheckUserInfoClaimsRequired" />
     </action-state>
 
-    <decision-state id="CheckUserInfoClaimsRequired">
-        <if
+    <decision-state id="CheckUserInfoClaimsRequired">        <if
             test="CheckUserInfoRequiredCondition.test(opensamlProfileRequestContext.getSubcontext('net.shibboleth.idp.authn.context.AuthenticationContext').getSubcontext('org.opensaml.profile.context.ProfileRequestContext'))"
             then="UserInfoRequest" else="FinalizeResponse" />
         <!-- if else here, we need to set id_token claims into EndUserClaimsContext -->
@@ -133,21 +132,26 @@
     </action-state>
 
     <!-- A plain JWT will skip token validation and go straight to claims validation -->
-    <decision-state id="CheckUserInfoResponseType">
-        <if
+    <decision-state id="CheckUserInfoResponseType">        <if
             test="CheckUserInfoPlainResponseTypeCondition.test(opensamlProfileRequestContext.getSubcontext('net.shibboleth.idp.authn.context.AuthenticationContext').getSubcontext('org.opensaml.profile.context.ProfileRequestContext'))"
             then="ValidateUserInfoClaimsSet" else="ValidateUserInfoJWT"/>
     </decision-state>
     
+    <!-- Actions to perform if the UserInfo response is a JWT type -->
     <action-state id="ValidateUserInfoJWT">
         <evaluate expression="PopulateUserInfoDecryptionParameters" />
         <evaluate expression="DecryptUserInfoJWT"/>
-       <!--  <evaluate expression="PopulateUserInfoSignatureValidationParameters" />
-        <evaluate expression="HandleUserInfoTokenValidation" /> -->
+        <evaluate expression="PopulateUserInfoTokenSignatureValidationParameters" />
+        <evaluate expression="HandleUserInfoTokenValidation" />    
+        <evaluate expression="'proceed'" />
+        <transition on="proceed" to="ValidateUserInfoClaimsSet" />    
+    </action-state>
+    
+    <!-- Plain UserInfo response types will skip straight to this stage -->
+    <action-state id="ValidateUserInfoClaimsSet">
         <evaluate expression="ValidateUserInfoClaims" />
         <evaluate expression="'proceed'" />
         <transition on="proceed" to="FinalizeResponse" />
-    
     </action-state>
 
     <action-state id="FinalizeResponse">
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
index 5589143..346fdc8 100644
--- 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
@@ -67,6 +67,7 @@ import com.nimbusds.jose.crypto.ECDSASigner;
 import com.nimbusds.jose.crypto.MACSigner;
 import com.nimbusds.jose.crypto.RSAEncrypter;
 import com.nimbusds.jose.jwk.Curve;
+import com.nimbusds.jose.jwk.ECKey;
 import com.nimbusds.jose.jwk.KeyUse;
 import com.nimbusds.jose.jwk.RSAKey;
 import com.nimbusds.jose.jwk.gen.ECKeyGenerator;
@@ -450,7 +451,8 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
      * @return the signed JWT
      * @throws JOSEException on error
      */
-    private SignedJWT createSignedUserInfoJWTResponseJSON(final String issuer, final String audience) 
+    private Pair<ECKey, SignedJWT> createAsymetricSignedUserInfoJWTResponseJSON(
+            final String issuer, final String audience) 
             throws JOSEException {
         
         final var key = new ECKeyGenerator(Curve.P_256).keyID("123").generate();
@@ -469,7 +471,7 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
         
         final var signedJWT = new SignedJWT(header, payload);
         signedJWT.sign(new ECDSASigner(key.toECPrivateKey()));
-        return signedJWT;
+        return new Pair(key,signedJWT);
     }
     
     /**
@@ -496,14 +498,16 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
     }
     
     /**
-     * Create a signed and encrypted UserInfo response JWT.
+     * Create an asymetrically signed and encrypted UserInfo response JWT. Return both signature and encryption
+     * keys alongside the EncryptedJWT in the response.
      * 
      * @param issuer the issuer
      * @param audience the audience
-     * @return the signed JWT
+     * @return the signed JWT alongside the pair of signature and encryption keys
+     * 
      * @throws JOSEException on error
      */
-    private Pair<RSAKey, EncryptedJWT> createSignedAndAssymetricEncryptedUserInfoJWTResponse(
+    private Pair<Pair<ECKey, RSAKey>, EncryptedJWT> createAsymetricSignedAndAssymetricEncryptedUserInfoJWTResponse(
             final String issuer, final String audience) throws Exception {
         
         final RSAKey keyRecipient = new RSAKeyGenerator(2048)
@@ -511,13 +515,16 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
                 .keyUse(KeyUse.ENCRYPTION)
                 .generate();
         
+        final var keySignedJWTPair = createAsymetricSignedUserInfoJWTResponseJSON(issuer, audience);
+        
         final JWEObject jweObject = 
                 new JWEObject(new JWEHeader.Builder(JWEAlgorithm.RSA_OAEP_256, EncryptionMethod.A256GCM)
                 .contentType("JWT")
                 .build(),
-                new Payload(createSignedUserInfoJWTResponseJSON(issuer, audience)));
+                new Payload(keySignedJWTPair.getSecond()));
         jweObject.encrypt(new RSAEncrypter(keyRecipient.toPublicJWK()));
-        return new Pair<RSAKey, EncryptedJWT>(keyRecipient, EncryptedJWT.parse(jweObject.serialize()));
+        return new Pair<Pair<ECKey, RSAKey>, EncryptedJWT>(
+                new Pair(keySignedJWTPair.getFirst(),keyRecipient), EncryptedJWT.parse(jweObject.serialize()));
     }
     
     /**
@@ -812,7 +819,7 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
         // Second is userInfo
         mockOPServer.enqueue(new MockResponse().setResponseCode(200)
                 .setHeader("content-type", "application/jwt")
-                .setBody(createSignedUserInfoJWTResponseJSON(OP_ISSUER_ID,CLIENT_ID).serialize()));
+                .setBody(createAsymetricSignedUserInfoJWTResponseJSON(OP_ISSUER_ID,CLIENT_ID).serialize()));
         mockOPServer.start(9918);
         
 
@@ -877,7 +884,7 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
     }
     
     @Test 
-    public void testAuthnFlowFromAuthorizationCallback_Using_SignedAndEncrypted_JWTIDTokenAndUserInfoResponse() 
+    public void testAuthnFlowFromAuthorizationCallback_Using_AsymetricSignedAnEncrypted_IDTokenAndUserInfoResponse() 
             throws Exception {
         
         setFlowPath(FLOW);
@@ -898,7 +905,8 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
                 .setHeader("content-type", "application/json")
                 .setBody(createAccessTokenResponseJSONSignedAndEncrypted()));
         // Second is userInfo
-        final var userInfoTokenAndKey = createSignedAndAssymetricEncryptedUserInfoJWTResponse(OP_ISSUER_ID,CLIENT_ID);
+        final var userInfoTokenAndKey = 
+                createAsymetricSignedAndAssymetricEncryptedUserInfoJWTResponse(OP_ISSUER_ID,CLIENT_ID);
         mockOPServer.enqueue(new MockResponse().setResponseCode(200)
                 .setHeader("content-type", "application/jwt")
                 .setBody(userInfoTokenAndKey.getSecond().serialize()));
@@ -943,10 +951,10 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
             public Credential resolveSingle(final CriteriaSet criteria) throws ResolverException {
                 final BasicJWKCredential jwkCredential = new BasicJWKCredential();
                 jwkCredential.setAlgorithm(JWEAlgorithm.RSA_OAEP_256);
-                jwkCredential.setKid(userInfoTokenAndKey.getFirst().getKeyID());                
+                jwkCredential.setKid(userInfoTokenAndKey.getFirst().getSecond().getKeyID());                
                 try {
-                    jwkCredential.setPrivateKey(userInfoTokenAndKey.getFirst().toPrivateKey());
-                    jwkCredential.setPublicKey(userInfoTokenAndKey.getFirst().toPublicKey());
+                    jwkCredential.setPrivateKey(userInfoTokenAndKey.getFirst().getSecond().toPrivateKey());
+                    jwkCredential.setPublicKey(userInfoTokenAndKey.getFirst().getSecond().toPublicKey());
                 } catch (final JOSEException e) {
                     fail();
                 }                
@@ -956,10 +964,37 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
             public Iterable<Credential> resolve(final CriteriaSet criteria) throws ResolverException {
                 return List.of(resolveSingle(criteria));
             }
-        });
-        
+        });      
         secConfig.setIdTokenJwtDecryptionConfig(idTokenDecryptConfig);    
         secConfig.setUserInfoJwtDecryptionConfig(userInfoDecryptConfig);
+        
+        //Signature config for userinfo token
+        final BasicSignatureValidationConfiguration<SignedJWT> sigValidationUserInfo = 
+                new BasicSignatureValidationConfiguration<>();
+        sigValidationUserInfo.setSignatureTrustEngine(new ExplicitKeySignedJWTTrustEngine(
+                new CredentialResolver() {
+                    
+                    @Override
+                    public Credential resolveSingle(final CriteriaSet criteria) throws ResolverException {
+                        final BasicJWKCredential jwkCredential = new BasicJWKCredential();
+                        jwkCredential.setAlgorithm(JWEAlgorithm.RSA_OAEP_256);
+                        jwkCredential.setKid(userInfoTokenAndKey.getFirst().getFirst().getKeyID());                
+                        try {
+                            jwkCredential.setPrivateKey(userInfoTokenAndKey.getFirst().getFirst().toPrivateKey());
+                            jwkCredential.setPublicKey(userInfoTokenAndKey.getFirst().getFirst().toPublicKey());
+                        } catch (final JOSEException e) {
+                            fail();
+                        }                
+                        return jwkCredential;
+                    }            
+                    @Override
+                    public Iterable<Credential> resolve(final CriteriaSet criteria) throws ResolverException {
+                        return List.of(resolveSingle(criteria));
+                    }
+                }, new BasicJOSEObjectCredentialResolver()));
+        
+        secConfig.setUserInfoTokenJwtSignatureValidationConfig(sigValidationUserInfo);  
+        
         partyConfig.setSecurityConfiguration(secConfig);
         
                 
@@ -1012,7 +1047,7 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
      * @throws Exception on error.
      */
     @Test 
-    public void testAuthnFlowFromAuthorizationCallback_Using_SignedAndAsymetricEncryptedIDToken() 
+    public void testAuthnFlowFromAuthorizationCallback_Using_SymetricSigned_And_AsymetricEncryptedIDToken() 
             throws Exception {
         
         setFlowPath(FLOW);

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


More information about the commits mailing list