[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