[java-idp-plugin-oidc-rp] branch main updated: Changes to support new JWT encryption config and param classes
Phil Smart
philip.smart at jisc.ac.uk
Thu Aug 18 14:46:56 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=eb3843470c62a669d93f2ce866ae7660e7240928
The following commit(s) were added to refs/heads/main by this push:
new eb38434 Changes to support new JWT encryption config and param classes
eb38434 is described below
commit eb3843470c62a669d93f2ce866ae7660e7240928
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Thu Aug 18 15:46:50 2022 +0100
Changes to support new JWT encryption config and param classes
Minor cleanup
Javadoc
---
...TokenDecryptionConfigurationLookupFunction.java | 10 +-
...bjectEncryptionConfigurationLookupFunction.java | 19 +-
...rInfoDecryptionConfigurationLookupFunction.java | 10 +-
.../rp/impl/PopulateJWTDecryptionParameters.java | 16 +-
.../rp/impl/PopulateJWTEncryptionParameters.java | 45 ++--
...oviderMetadataEncryptionParametersResolver.java | 246 ++++++++-------------
...RelyingPartyProxySigningParametersResolver.java | 29 +--
.../authn/oidc/rp/messaging/impl/EncryptJWT.java | 10 +-
.../oidc/rp/messaging/impl/SignRequestObject.java | 5 +-
.../idp/service/relying-party/postconfig.xml | 54 ++++-
.../oidc/rp/impl/AuthorizationControllerTest.java | 8 +-
.../plugin/authn/oidc/rp/impl/EncryptJWTTest.java | 47 +++-
...erMetadataEncryptionParametersResolverTest.java | 131 ++++++++---
...ingPartyProxySigningParametersResolverTest.java | 16 +-
.../authn/oidc/rp/impl/TestCredentialHelper.java | 6 +-
.../rp/messaging/impl/SignRequestObjectTest.java | 10 +-
.../test/resources/conf/authn/rp-credentials.xml | 7 +-
17 files changed, 365 insertions(+), 304 deletions(-)
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/IDTokenDecryptionConfigurationLookupFunction.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/IDTokenDecryptionConfigurationLookupFunction.java
index 4157f5f..bbb601f 100644
--- a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/IDTokenDecryptionConfigurationLookupFunction.java
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/IDTokenDecryptionConfigurationLookupFunction.java
@@ -30,10 +30,10 @@ 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.DecryptionConfiguration;
+import net.shibboleth.oidc.security.JWTDecryptionConfiguration;
/**
- * A function that returns a {@link DecryptionConfiguration} list for JWE decryption by way
+ * A function that returns a {@link JWTDecryptionConfiguration} list for JWE decryption by way
* of various lookup strategies.
*
* <p>
@@ -41,7 +41,7 @@ import net.shibboleth.oidc.security.DecryptionConfiguration;
* </p>
*/
public class IDTokenDecryptionConfigurationLookupFunction
- extends AbstractRelyingPartyLookupFunction<List<DecryptionConfiguration>> {
+ extends AbstractRelyingPartyLookupFunction<List<JWTDecryptionConfiguration>> {
/** A resolver for default security configurations. */
@Nullable
@@ -59,9 +59,9 @@ public class IDTokenDecryptionConfigurationLookupFunction
/** {@inheritDoc} */
@Override
@Nullable
- public List<DecryptionConfiguration> apply(@Nullable final ProfileRequestContext input) {
+ public List<JWTDecryptionConfiguration> apply(@Nullable final ProfileRequestContext input) {
- final List<DecryptionConfiguration> configs = new ArrayList<>();
+ final List<JWTDecryptionConfiguration> configs = new ArrayList<>();
final RelyingPartyContext rpc = getRelyingPartyContextLookupStrategy().apply(input);
if (rpc != null) {
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/RequestObjectEncryptionConfigurationLookupFunction.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/RequestObjectEncryptionConfigurationLookupFunction.java
index 2c78b5c..b0ebd76 100644
--- a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/RequestObjectEncryptionConfigurationLookupFunction.java
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/RequestObjectEncryptionConfigurationLookupFunction.java
@@ -24,9 +24,6 @@ import javax.annotation.Nullable;
import org.opensaml.profile.context.ProfileRequestContext;
import org.opensaml.xmlsec.EncryptionConfiguration;
-import org.opensaml.xmlsec.SignatureSigningConfiguration;
-
-import com.nimbusds.jwt.SignedJWT;
import net.shibboleth.idp.profile.config.ProfileConfiguration;
import net.shibboleth.idp.profile.config.SecurityConfiguration;
@@ -34,7 +31,7 @@ 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;
+import net.shibboleth.oidc.security.JWTEncryptionConfiguration;
/**
* A function that returns an {@link EncryptionConfiguration} list for request object encryption by way
@@ -45,7 +42,7 @@ import net.shibboleth.oidc.security.SignatureValidationConfiguration;
* </p>
*/
public class RequestObjectEncryptionConfigurationLookupFunction
- extends AbstractRelyingPartyLookupFunction<List<EncryptionConfiguration>> {
+ extends AbstractRelyingPartyLookupFunction<List<JWTEncryptionConfiguration>> {
/** A resolver for default security configurations. */
@Nullable
@@ -63,18 +60,18 @@ public class RequestObjectEncryptionConfigurationLookupFunction
/** {@inheritDoc} */
@Override
@Nullable
- public List<EncryptionConfiguration> apply(@Nullable final ProfileRequestContext input) {
+ public List<JWTEncryptionConfiguration> apply(@Nullable final ProfileRequestContext input) {
- final List<EncryptionConfiguration> configs = new ArrayList<>();
+ final List<JWTEncryptionConfiguration> 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))
- .getEncryptionConfiguration() != null) {
+ .getRequestObjectEncryptionConfig() != null) {
configs.add(((OIDCSecurityConfiguration) pc.getSecurityConfiguration(input))
- .getEncryptionConfiguration());
+ .getRequestObjectEncryptionConfig());
}
}
@@ -84,9 +81,9 @@ public class RequestObjectEncryptionConfigurationLookupFunction
rpResolver.getDefaultSecurityConfiguration(input.getProfileId());
if (defaultConfig instanceof OIDCSecurityConfiguration
&& ((OIDCSecurityConfiguration) defaultConfig)
- .getEncryptionConfiguration() != null) {
+ .getRequestObjectEncryptionConfig() != null) {
configs.add(
- ((OIDCSecurityConfiguration) defaultConfig).getEncryptionConfiguration());
+ ((OIDCSecurityConfiguration) defaultConfig).getRequestObjectEncryptionConfig());
}
}
// TODO: Support for Global Default configuration?
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/UserInfoDecryptionConfigurationLookupFunction.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/UserInfoDecryptionConfigurationLookupFunction.java
index 9bc34f7..908c65b 100644
--- a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/UserInfoDecryptionConfigurationLookupFunction.java
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/UserInfoDecryptionConfigurationLookupFunction.java
@@ -30,10 +30,10 @@ 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.DecryptionConfiguration;
+import net.shibboleth.oidc.security.JWTDecryptionConfiguration;
/**
- * A function that returns a {@link DecryptionConfiguration} list for JWE decryption by way
+ * A function that returns a {@link JWTDecryptionConfiguration} list for JWE decryption by way
* of various lookup strategies.
*
* <p>
@@ -41,7 +41,7 @@ import net.shibboleth.oidc.security.DecryptionConfiguration;
* </p>
*/
public class UserInfoDecryptionConfigurationLookupFunction
- extends AbstractRelyingPartyLookupFunction<List<DecryptionConfiguration>> {
+ extends AbstractRelyingPartyLookupFunction<List<JWTDecryptionConfiguration>> {
/** A resolver for default security configurations. */
@Nullable
@@ -59,9 +59,9 @@ public class UserInfoDecryptionConfigurationLookupFunction
/** {@inheritDoc} */
@Override
@Nullable
- public List<DecryptionConfiguration> apply(@Nullable final ProfileRequestContext input) {
+ public List<JWTDecryptionConfiguration> apply(@Nullable final ProfileRequestContext input) {
- final List<DecryptionConfiguration> configs = new ArrayList<>();
+ final List<JWTDecryptionConfiguration> configs = new ArrayList<>();
final RelyingPartyContext rpc = getRelyingPartyContextLookupStrategy().apply(input);
if (rpc != null) {
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateJWTDecryptionParameters.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateJWTDecryptionParameters.java
index 822b6be..6c0fd3e 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateJWTDecryptionParameters.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateJWTDecryptionParameters.java
@@ -34,7 +34,7 @@ import org.slf4j.LoggerFactory;
import net.shibboleth.idp.profile.AbstractProfileAction;
import net.shibboleth.idp.profile.context.RelyingPartyContext;
import net.shibboleth.oidc.profile.config.OIDCAuthorizationConfiguration;
-import net.shibboleth.oidc.security.DecryptionConfiguration;
+import net.shibboleth.oidc.security.JWTDecryptionConfiguration;
import net.shibboleth.oidc.security.JWTDecryptionParameters;
import net.shibboleth.oidc.security.JWTDecryptionParametersResolver;
import net.shibboleth.oidc.security.context.JWTSecurityParametersContext;
@@ -56,8 +56,8 @@ public class PopulateJWTDecryptionParameters extends AbstractProfileAction {
@Nonnull
private Function<ProfileRequestContext,JWTSecurityParametersContext> securityParametersContextLookupStrategy;
- /** Strategy used to lookup a per-request {@link DecryptionConfiguration} list. */
- @NonnullAfterInit private Function<ProfileRequestContext,List<DecryptionConfiguration>> configurationLookupStrategy;
+ /** Strategy used to lookup a per-request {@link JWTDecryptionConfiguration} list. */
+ @NonnullAfterInit private Function<ProfileRequestContext,List<JWTDecryptionConfiguration>> configurationLookupStrategy;
/** Lookup function for relying party context. */
@Nonnull private Function<ProfileRequestContext,RelyingPartyContext> relyingPartyContextLookupStrategy;
@@ -101,12 +101,12 @@ public class PopulateJWTDecryptionParameters extends AbstractProfileAction {
}
/**
- * Set the strategy used to look up a per-request {@link DecryptionConfiguration} list.
+ * Set the strategy used to look up a per-request {@link JWTDecryptionConfiguration} list.
*
* @param strategy lookup strategy
*/
public void setConfigurationLookupStrategy(
- @Nonnull final Function<ProfileRequestContext, List<DecryptionConfiguration>> strategy) {
+ @Nonnull final Function<ProfileRequestContext, List<JWTDecryptionConfiguration>> strategy) {
ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
configurationLookupStrategy = Constraint.isNotNull(strategy,
@@ -144,7 +144,7 @@ public class PopulateJWTDecryptionParameters extends AbstractProfileAction {
log.debug("{} Resolving JWT DecryptionParameters for request", getLogPrefix());
- final List<DecryptionConfiguration> configs = configurationLookupStrategy.apply(profileRequestContext);
+ final List<JWTDecryptionConfiguration> configs = configurationLookupStrategy.apply(profileRequestContext);
if (configs == null || configs.isEmpty()) {
log.error("{} No DecryptionConfigurations returned by lookup strategy", getLogPrefix());
ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_SEC_CFG);
@@ -177,13 +177,13 @@ public class PopulateJWTDecryptionParameters extends AbstractProfileAction {
* Build the criteria used as input to the {@link JWTDecryptionParametersResolver}.
*
* @param profileRequestContext current profile request context
- * @param configs a list of {@link DecryptionConfiguration}s to add to the criteria set.
+ * @param configs a list of {@link JWTDecryptionConfiguration}s to add to the criteria set.
*
* @return the criteria set to use
*/
@Nonnull
private CriteriaSet buildCriteriaSet(@Nonnull final ProfileRequestContext profileRequestContext,
- final List<DecryptionConfiguration> configs) {
+ final List<JWTDecryptionConfiguration> configs) {
final CriteriaSet criteria = new CriteriaSet();
criteria.add(new DecryptionConfigurationCriterion(configs));
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateJWTEncryptionParameters.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateJWTEncryptionParameters.java
index 93c3dd7..63313a1 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateJWTEncryptionParameters.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateJWTEncryptionParameters.java
@@ -17,7 +17,6 @@
package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
-import java.util.Collections;
import java.util.List;
import java.util.function.Function;
@@ -29,11 +28,6 @@ import org.opensaml.profile.action.ActionSupport;
import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
import org.opensaml.profile.context.navigate.OutboundMessageContextLookup;
-import org.opensaml.xmlsec.EncryptionConfiguration;
-import org.opensaml.xmlsec.EncryptionParameters;
-import org.opensaml.xmlsec.EncryptionParametersResolver;
-import org.opensaml.xmlsec.SecurityConfigurationSupport;
-import org.opensaml.xmlsec.criterion.EncryptionConfigurationCriterion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -42,8 +36,12 @@ import net.shibboleth.idp.profile.context.RelyingPartyContext;
import net.shibboleth.oidc.metadata.context.OIDCMetadataContext;
import net.shibboleth.oidc.metadata.context.OIDCProviderMetadataContext;
import net.shibboleth.oidc.profile.config.OIDCAuthorizationConfiguration;
+import net.shibboleth.oidc.security.JWTEncryptionConfiguration;
+import net.shibboleth.oidc.security.JWTEncryptionParameters;
+import net.shibboleth.oidc.security.JWTEncryptionParametersResolver;
import net.shibboleth.oidc.security.context.JWTSecurityParametersContext;
import net.shibboleth.oidc.security.criterion.ClientInformationCriterion;
+import net.shibboleth.oidc.security.criterion.JWTEncryptionConfigurationCriterion;
import net.shibboleth.oidc.security.criterion.ProviderMetadataCriterion;
import net.shibboleth.oidc.security.criterion.StaticCredentialCriterion;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
@@ -56,12 +54,12 @@ import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
import net.shibboleth.utilities.java.support.resolver.ResolverException;
/**
- * Action that resolves and populates {@link EncryptionParameters} on an {@link JWTSecurityParametersContext}
+ * Action that resolves and populates {@link JWTEncryptionParameters} on an {@link JWTSecurityParametersContext}
* created/accessed via a lookup function, by default on a child of the outbound message context.
*
* <p>The resolution process is contingent on the active profile configuration requesting encryption.</p>
*
- * <p>The default, per-RelyingParty, and default per-profile {@link EncryptionConfiguration}
+ * <p>The default, per-RelyingParty, and default per-profile {@link JWTEncryptionConfiguration}
* objects are input to the resolution process, along with the relying party's client metadata, any static
* credentials configured on the relying party, and the OpenID Provider metadata (which in most cases
* will be the source of the eventual encryption key)</p>
@@ -85,14 +83,15 @@ public class PopulateJWTEncryptionParameters extends AbstractProfileAction {
@Nonnull
private Function<ProfileRequestContext,JWTSecurityParametersContext> securityParametersContextLookupStrategy;
- /** Strategy used to look up a per-request {@link EncryptionConfiguration} list. */
- @NonnullAfterInit private Function<ProfileRequestContext,List<EncryptionConfiguration>> configurationLookupStrategy;
+ /** Strategy used to look up a per-request {@link JWTEncryptionConfiguration} list. */
+ @NonnullAfterInit
+ private Function<ProfileRequestContext,List<JWTEncryptionConfiguration>> configurationLookupStrategy;
/** Resolver for parameters to store into context. */
- @NonnullAfterInit private EncryptionParametersResolver encParamsresolver;
+ @NonnullAfterInit private JWTEncryptionParametersResolver encParamsresolver;
/** Active configurations to feed into resolver. */
- @Nullable @NonnullElements private List<EncryptionConfiguration> encryptionConfigurations;
+ @Nullable @NonnullElements private List<JWTEncryptionConfiguration> encryptionConfigurations;
/** Strategy used to look up a OIDC client metadata context. */
@Nullable private Function<ProfileRequestContext, OIDCMetadataContext> oidcClientMetadataContextLookupStrategy;
@@ -182,12 +181,12 @@ public class PopulateJWTEncryptionParameters extends AbstractProfileAction {
}
/**
- * Set the strategy used to look up a per-request {@link EncryptionConfiguration} list.
+ * Set the strategy used to look up a per-request {@link JWTEncryptionConfiguration} list.
*
* @param strategy lookup strategy
*/
public void setConfigurationLookupStrategy(
- @Nonnull final Function<ProfileRequestContext, List<EncryptionConfiguration>> strategy) {
+ @Nonnull final Function<ProfileRequestContext, List<JWTEncryptionConfiguration>> strategy) {
ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
@@ -200,7 +199,7 @@ public class PopulateJWTEncryptionParameters extends AbstractProfileAction {
*
* @param newResolver encParamsresolver to use
*/
- public void setEncryptionParametersResolver(@Nonnull final EncryptionParametersResolver newResolver) {
+ public void setEncryptionParametersResolver(@Nonnull final JWTEncryptionParametersResolver newResolver) {
ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
encParamsresolver = Constraint.isNotNull(newResolver, "EncryptionParametersResolver cannot be null");
@@ -212,14 +211,7 @@ public class PopulateJWTEncryptionParameters extends AbstractProfileAction {
if (encParamsresolver == null) {
throw new ComponentInitializationException("EncryptionParametersResolver cannot be null");
- } else if (configurationLookupStrategy == null) {
- configurationLookupStrategy = new Function<ProfileRequestContext, List<EncryptionConfiguration>>() {
- @Override
- public List<EncryptionConfiguration> apply(final ProfileRequestContext input) {
- return Collections.singletonList(SecurityConfigurationSupport.getGlobalEncryptionConfiguration());
- }
- };
- }
+ }
}
@Override
@@ -251,7 +243,7 @@ public class PopulateJWTEncryptionParameters extends AbstractProfileAction {
throw new ResolverException("No EncryptionConfigurations returned by lookup strategy");
}
final CriteriaSet criteria = buildCriteriaSet(profileRequestContext);
- final EncryptionParameters params = encParamsresolver.resolveSingle(criteria);
+ final JWTEncryptionParameters params = encParamsresolver.resolveSingle(criteria);
if (params != null) {
log.debug("{} Resolved EncryptionParameters for {}", getLogPrefix(),forFriendlyName);
@@ -268,7 +260,7 @@ public class PopulateJWTEncryptionParameters extends AbstractProfileAction {
// Checkstyle: CyclomaticComplexity ON
/**
- * Build the criteria used as input to the {@link EncryptionParametersResolver}.
+ * Build the criteria used as input to the {@link JWTEncryptionParametersResolver}.
*
* @param profileRequestContext current profile request context
*
@@ -277,7 +269,8 @@ public class PopulateJWTEncryptionParameters extends AbstractProfileAction {
@Nonnull
private CriteriaSet buildCriteriaSet(@Nonnull final ProfileRequestContext profileRequestContext) {
- final CriteriaSet criteria = new CriteriaSet(new EncryptionConfigurationCriterion(encryptionConfigurations));
+ final CriteriaSet criteria = new CriteriaSet(
+ new JWTEncryptionConfigurationCriterion(encryptionConfigurations));
// Add client metadata criterion
final OIDCMetadataContext oidcMetadataCtx =
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ProviderMetadataEncryptionParametersResolver.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ProviderMetadataEncryptionParametersResolver.java
index 87d7bd7..a0ba872 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ProviderMetadataEncryptionParametersResolver.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ProviderMetadataEncryptionParametersResolver.java
@@ -21,6 +21,7 @@ import java.time.Duration;
import java.time.Instant;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -28,15 +29,9 @@ import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import org.opensaml.security.credential.Credential;
-import org.opensaml.xmlsec.EncryptionConfiguration;
-import org.opensaml.xmlsec.EncryptionParameters;
-import org.opensaml.xmlsec.criterion.EncryptionConfigurationCriterion;
-import org.opensaml.xmlsec.impl.BasicEncryptionParametersResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.nimbusds.jose.Algorithm;
import com.nimbusds.jose.EncryptionMethod;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWEAlgorithm;
@@ -49,33 +44,43 @@ import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
import net.shibboleth.oidc.jwk.RemoteJwkSetCache;
+import net.shibboleth.oidc.security.JWTEncryptionConfiguration;
+import net.shibboleth.oidc.security.JWTEncryptionParameters;
import net.shibboleth.oidc.security.credential.BasicJWKCredential;
-import net.shibboleth.oidc.security.credential.JWKCredential;
+import net.shibboleth.oidc.security.criterion.JWKSetCriterion;
+import net.shibboleth.oidc.security.criterion.JWTEncryptionConfigurationCriterion;
import net.shibboleth.oidc.security.criterion.ProviderMetadataCriterion;
-import net.shibboleth.oidc.security.impl.CredentialConversionUtil;
+import net.shibboleth.oidc.security.impl.BasicJWTEncryptionParametersResolver;
import net.shibboleth.utilities.java.support.annotation.constraint.Positive;
import net.shibboleth.utilities.java.support.logic.Constraint;
import net.shibboleth.utilities.java.support.logic.FunctionSupport;
import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
/**
- * A specialization of {@link BasicEncryptionParametersResolver} which resolves encryption credentials from
- * various sources based on what is supported by both the IdP and the downstream OpenID Provider.
- * Broadly, this supports the following credentials:
+ * An extension of {@link BasicJWTEncryptionParametersResolver} to support parameter resolution from an
+ * OpenID Provider's metadata (remote keyset), in addition to those resolved from local configuration by the
+ * base class.
+ *
+ * <p>The set of supported and configured key transport ('alg') and encryption methods ('enc') are derived
+ * from the intersection of those supported by local configuration, and those supported by the downstream
+ * OpenID Provider. The order of those algorithms in the local configuration are preserved, and affect which
+ * credential is chosen. As algorithm 'alg' and 'enc' support is optional in provider metadata, failure to
+ * locate them will result in the default behaviour of the parent class being applied (resolve from local
+ * configuration). If they are present, but are not compatible with the set configured in the encryption
+ * configuration, no parameters are returned (a failure). </p>
+ *
+ * <p>Generally, the following logic applies:</p>
* <ul>
- * <li>Private KeyWrapping credentials found in the {@link EncryptionConfiguration}.</li>
- * <li>Public KeyEncryption or KeyAgreement credentials found in the Providers remote keyset. The Provider's metadata
- * must be contained inside a ProviderMetadataCriterion.</li>
- * </ul>
- * Failure to resolve credentials from the above sources delegates resolution back to the
- * {@link BasicEncryptionParametersResolver}.
- * It does not support:
- * <ul>
- * <li>Direct encryption credentials</li>
+ * <li>Private KeyWrapping and direct encryption credentials are found in the local
+ * {@link JWTEncryptionConfiguration}.</li>
+ * <li>Public KeyEncryption or KeyAgreement credentials are found in the OpenID Provider's KeySet.
+ * The Provider's metadata must be contained inside a ProviderMetadataCriterion, otherwise only local
+ * credentials can be resolved.</li>
* </ul>
+ *
+ *
*/
-//TODO check key length for algorithm e.g AES key wrap credential size?
-public class ProviderMetadataEncryptionParametersResolver extends BasicEncryptionParametersResolver {
+public class ProviderMetadataEncryptionParametersResolver extends BasicJWTEncryptionParametersResolver {
/** Logger. */
private final Logger log = LoggerFactory.getLogger(ProviderMetadataEncryptionParametersResolver.class);
@@ -146,16 +151,18 @@ public class ProviderMetadataEncryptionParametersResolver extends BasicEncryptio
}
@Override
- protected void resolveAndPopulateCredentialsAndAlgorithms(@Nonnull final EncryptionParameters params,
+ protected void resolveAndPopulateCredentialsAndAlgorithms(@Nonnull final JWTEncryptionParameters params,
@Nonnull final CriteriaSet criteria, @Nonnull final Predicate<String> includeExcludePredicate) {
if (remoteJwkSetCache == null) {
- log.error("OIDC Provider metadata encryption parameters resolver does not have a remote JWKSet cache set");
+ log.debug("OIDC Provider metadata encryption parameters resolver does not have a remote JWKSet cache set,"
+ + "falling back to default local configuration");
+ super.resolveAndPopulateCredentialsAndAlgorithms(params, criteria, includeExcludePredicate);
+ return;
}
- if (!criteria.contains(EncryptionConfigurationCriterion.class)) {
- log.debug("No encryption configuration criterion, falling back to default configuration");
- super.resolveAndPopulateCredentialsAndAlgorithms(params, criteria, includeExcludePredicate);
+ if (!criteria.contains(JWTEncryptionConfigurationCriterion.class)) {
+ log.debug("No encryption configuration criterion, encryption parameters can not be resolved");
return;
}
@@ -166,11 +173,10 @@ public class ProviderMetadataEncryptionParametersResolver extends BasicEncryptio
}
final OIDCProviderMetadata metadata = criteria.get(ProviderMetadataCriterion.class).getMetadata();
- final List<EncryptionConfiguration> encryptionConfigurations =
- criteria.get(EncryptionConfigurationCriterion.class).getConfigurations();
- if (encryptionConfigurations == null || encryptionConfigurations.isEmpty()) {
- log.debug("No encryption configuration, falling back to default configuration");
- super.resolveAndPopulateCredentialsAndAlgorithms(params, criteria, includeExcludePredicate);
+ final List<JWTEncryptionConfiguration> encryptionConfigurations =
+ criteria.get(JWTEncryptionConfigurationCriterion.class).getConfigurations();
+ if (encryptionConfigurations.isEmpty()) {
+ log.debug("No encryption configuration, encryption parameters can not be resolved");
return;
}
@@ -179,7 +185,8 @@ public class ProviderMetadataEncryptionParametersResolver extends BasicEncryptio
providerKeyTransportAlgorithmsLookupStrategy.apply(metadata);
log.trace("Resolved effective key transport algorithms from provider metadata: {}", keyTransportAlgorithms);
if (keyTransportAlgorithms.isEmpty()) {
- log.debug("No algorithm information in provider metadata, falling back to default configuration");
+ log.debug("No algorithm ('alg') information in provider metadata, "
+ + "falling back to default local configuration");
super.resolveAndPopulateCredentialsAndAlgorithms(params, criteria, includeExcludePredicate);
return;
}
@@ -212,142 +219,85 @@ public class ProviderMetadataEncryptionParametersResolver extends BasicEncryptio
supportedAndConfiguredDataEncryptionAlgorithms);
if (supportedAndConfiguredKeyTransportAlgorithms.isEmpty()) {
- log.warn("No supported key transport algorithm");
- super.resolveAndPopulateCredentialsAndAlgorithms(params, criteria, includeExcludePredicate);
+ log.warn("No supported key transport algorithm. Provider metadata and configuration are not compatible");
return;
}
if (supportedAndConfiguredDataEncryptionAlgorithms.isEmpty()) {
- log.warn("No supported data encryption method");
- super.resolveAndPopulateCredentialsAndAlgorithms(params, criteria, includeExcludePredicate);
+ log.warn("No supported data encryption method. Provider metadata and configuration are not compatible");
return;
}
- final List<JWEAlgorithm> supportedJWEKeyTransportAlgorithms =
- convertStringAlgorithmURIsToJwkAlgorithms(supportedAndConfiguredKeyTransportAlgorithms);
-
- final EncryptionMethod encryptionMethod =
- resolveEncryptionMethod(supportedAndConfiguredDataEncryptionAlgorithms);
- if (encryptionMethod == null) {
- log.warn("No supported encryption method");
- super.resolveAndPopulateCredentialsAndAlgorithms(params, criteria, includeExcludePredicate);
- return;
- }
-
- resolveCredentialForSupportedAlgorithm(metadata, supportedJWEKeyTransportAlgorithms,
- encryptionConfigurations.stream()
- .flatMap(config -> config.getKeyTransportEncryptionCredentials().stream())
- .collect(Collectors.toList()), params, encryptionMethod);
-
- if (params.getKeyTransportEncryptionCredential() == null) {
- log.debug("Not able to locate encryption credentials based on provider metadata or encryption "
- + "configuration");
- super.resolveAndPopulateCredentialsAndAlgorithms(params, criteria, includeExcludePredicate);
- }
+ // Add JWKSet criterion so the callback methods can pull out the OP's JWK set.
+ criteria.add(new JWKSetCriterion(getProviderKeys(metadata)));
-
+ // Now we have resolved the set of supported 'alg' and 'enc' algorithms, delegate back to the base
+ // class to check locally configured credentials, and call back to this class to resolve from
+ // the providers key set.
+ super.resolveCredentialForSupportedAlgorithm(criteria,
+ convertStringAlgorithmURIsToJwkAlgorithms(supportedAndConfiguredKeyTransportAlgorithms),
+ convertStringEncryptionMethodURIsToEncryptionMethods(supportedAndConfiguredDataEncryptionAlgorithms),
+ getEffectiveKeyTransportCredentials(criteria),
+ getEffectiveDataEncryptionCredentials(criteria),
+ params);
+
+ if (params.getKeyTransportEncryptionCredential() == null && params.getDataEncryptionCredential() == null) {
+ log.debug("Unable to resolve either key transport or data encryption credential");
+ }
}
/**
- * Resolve a credential compatible with a supported algorithm. Algorithms are tried in the order
- * they appear in the list of keyTransportAlgorithms.
- *
- * <p>Key wrapping credentials come from locally configured keys.</p>
- * <p>
- * Key encryption or key agreement credentials are fetched from the OP's remote key set.
- * </p>
- * <p>The first key that is compatible with the algorithm is returned. That is, if two or more keys
- * support the same algorithm, the first key in the local credentials list or provider metadata keys set
- * will be returned. There is no guarantee which key that is.</p>
- *
- * @param metadata the OpenID Provider's metadata
- * @param keyTransportAlgorithms the set of supported key transport algorithms
- * @param localCredentials the list of local credentials that might represent a private/secret key
- * @param params the encryption parameters to add the credential to
- * @param encryptionMethod the encryption method to use
+ * {@inheritDoc}
+ * <p>Resolves key transport credentials compatible with the given algorithm from those defined in the
+ * OP's JWKSet (stored in the criteria).</p>
*/
- //TODO what happens if a 'dir' alg is used and that matches a local cred?
- private void resolveCredentialForSupportedAlgorithm(@Nonnull final OIDCProviderMetadata metadata,
- @Nonnull final List<JWEAlgorithm> keyTransportAlgorithms,
- @Nonnull final List<Credential> localCredentials,
- @Nonnull final EncryptionParameters params, @Nonnull final EncryptionMethod encryptionMethod) {
+ @Override
+ protected void resolveKeyTransportCredentialForSupportedAlgorithmFromAdditionalSource(
+ @Nonnull final JWEAlgorithm algorithm, @Nonnull final EncryptionMethod encryptionMethod,
+ @Nonnull final CriteriaSet criteria, @Nonnull final JWTEncryptionParameters params) {
+
+ final JWKSetCriterion jwkSetCriterion = criteria.get(JWKSetCriterion.class);
+ if (jwkSetCriterion == null) {
+ log.debug("Unable to find JWKSet criterion, can not resolver provider keys");
+ return;
+ }
+ final JWKSet providerKeySet = jwkSetCriterion.getJWKSet();
+ if (providerKeySet == null) {
+ log.debug("Unable to find keys in JWKSet criterion, can not resolver provider keys");
+ return;
+ }
- for (final JWEAlgorithm algorithm : keyTransportAlgorithms) {
- // First match against local secret keys
- final JWKCredential localCred = localCredentials.stream()
- .filter(JWKCredential.class::isInstance)
- .map(JWKCredential.class::cast)
- .filter(c -> algorithm.equals(c.getAlgorithm()))
+ // All keys in provider metadata should be key transport, not direct data/content encryption, as that
+ // is a public document.
+ final JWK key =
+ providerKeySet.getKeys().stream()
+ .filter(Objects::nonNull)
+ .filter(k -> KeyUse.ENCRYPTION == k.getKeyUse())
+ .filter(k -> k.getAlgorithm().equals(algorithm))
.findFirst().orElse(null);
-
- if (localCred != null) {
- if (log.isDebugEnabled()) {
- log.debug("Selected key '{}' for alg {} and enc {}",
- CredentialConversionUtil.resolveKid(localCred),
- algorithm.getName(), encryptionMethod.getName());
+
+ if (key != null) {
+ final BasicJWKCredential jwkCredential = new BasicJWKCredential();
+ jwkCredential.setAlgorithm(algorithm);
+ jwkCredential.setKid(key.getKeyID());
+ try {
+ if (key.getKeyType().equals(KeyType.RSA)) {
+ jwkCredential.setPublicKey(((RSAKey) key).toPublicKey());
+ } else if (key.getKeyType().equals(KeyType.EC)){
+ jwkCredential.setPublicKey(((ECKey) key).toPublicKey());
}
- params.setKeyTransportEncryptionCredential(localCred);
- params.setKeyTransportEncryptionAlgorithm(algorithm.getName());
- params.setDataEncryptionAlgorithm(encryptionMethod.getName());
+ } catch (final JOSEException e) {
+ log.warn("Unable to parse keyset", e);
return;
- }
-
- // Now match key encryption/agreement key from OP's keyset
- final JWKSet providerKeySet = getProviderKeys(metadata);
-
- final JWK key =
- providerKeySet.getKeys().stream()
- .filter(k -> KeyUse.ENCRYPTION == k.getKeyUse())
- .filter(k -> k.getAlgorithm().equals(algorithm))
- .findFirst().orElse(null);
-
- if (key != null) {
- final BasicJWKCredential jwkCredential = new BasicJWKCredential();
- jwkCredential.setAlgorithm(algorithm);
- jwkCredential.setKid(key.getKeyID());
- try {
- if (key.getKeyType().equals(KeyType.RSA)) {
- jwkCredential.setPublicKey(((RSAKey) key).toPublicKey());
- } else if (key.getKeyType().equals(KeyType.EC)){
- jwkCredential.setPublicKey(((ECKey) key).toPublicKey());
- }
- } catch (final JOSEException e) {
- log.warn("Unable to parse keyset", e);
- continue;
- }
+ }
+ if (checkKeyAlgorithmAndLength(jwkCredential, algorithm.getName())) {
log.debug("Selected key '{}' for alg {} and enc {}", key.getKeyID(),
algorithm.getName(), encryptionMethod.getName());
params.setKeyTransportEncryptionCredential(jwkCredential);
params.setKeyTransportEncryptionAlgorithm(algorithm.getName());
- params.setDataEncryptionAlgorithm(encryptionMethod.getName());
- return;
+ params.setDataEncryptionAlgorithm(encryptionMethod.getName());
}
}
- }
-
- /**
- * Return the first encryption method in the supported list, or null otherwise.
- *
- * @param dataEncryptionAlgorithms the supported data encryption method
- *
- * @return the first supported encryption method, or {@literal null}.
- */
- @Nullable private EncryptionMethod resolveEncryptionMethod(@Nonnull final List<String> dataEncryptionAlgorithms) {
- if (!dataEncryptionAlgorithms.isEmpty()) {
- return EncryptionMethod.parse(dataEncryptionAlgorithms.get(0));
- }
- return null;
- }
-
- /**
- * Convert the algorithms represented as strings, into Nimbus {@link Algorithm}s for later comparison.
- * This will preserve the order of the original list ({@link List} is ordered).
- *
- * @param algos the algorithms to convert
- *
- * @return the converted algorithms
- */
- @Nonnull private List<JWEAlgorithm> convertStringAlgorithmURIsToJwkAlgorithms(@Nonnull final List<String> algos) {
- return algos.stream().map(JWEAlgorithm::parse).collect(Collectors.toList());
+
}
/**
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/RelyingPartyProxySigningParametersResolver.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/RelyingPartyProxySigningParametersResolver.java
index 5f32b18..6069267 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/RelyingPartyProxySigningParametersResolver.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/RelyingPartyProxySigningParametersResolver.java
@@ -39,8 +39,10 @@ import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.jwk.Curve;
import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
+import net.shibboleth.oidc.security.JWTSignatureSigningParameters;
import net.shibboleth.oidc.security.criterion.ProviderMetadataCriterion;
import net.shibboleth.oidc.security.criterion.StaticCredentialCriterion;
+import net.shibboleth.oidc.security.impl.BasicJWTSignatureSigningParametersResolver;
import net.shibboleth.oidc.security.impl.CredentialConversionUtil;
import net.shibboleth.utilities.java.support.logic.Constraint;
import net.shibboleth.utilities.java.support.logic.FunctionSupport;
@@ -63,7 +65,7 @@ import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
* <li>{@link ProviderMetadataCriterion} - required</li>
* </ul>
*/
-public class RelyingPartyProxySigningParametersResolver extends BasicSignatureSigningParametersResolver {
+public class RelyingPartyProxySigningParametersResolver extends BasicJWTSignatureSigningParametersResolver {
/** Logger. */
@Nonnull
@@ -94,9 +96,9 @@ public class RelyingPartyProxySigningParametersResolver extends BasicSignatureSi
}
// Checkstyle: CyclomaticComplexity|ReturnCount OFF
- /** {@inheritDoc} */
@Override
- protected void resolveAndPopulateCredentialAndSignatureAlgorithm(@Nonnull final SignatureSigningParameters params,
+ protected void resolveAndPopulateCredentialAndSignatureAlgorithm(
+ @Nonnull final JWTSignatureSigningParameters params,
@Nonnull final CriteriaSet criteria, @Nonnull final Predicate<String> includeExcludePredicate) {
final List<Credential> allCredentials = new ArrayList<>();
@@ -135,26 +137,7 @@ public class RelyingPartyProxySigningParametersResolver extends BasicSignatureSi
log.trace("Credential failed eval against Signing Algorithm");
}
- }
-
-
- /** {@inheritDoc}
- *
- * <p>Does not include validation of the SignatureCanonicalizationAlgorithm or the
- * SignatureReferenceDigestMethod. These will be null in the JWT case.</p>
- */
- @Override
- protected boolean validate(@Nonnull final SignatureSigningParameters params) {
- if (params.getSigningCredential() == null) {
- log.debug("Validation failure: Unable to resolve signing credential");
- return false;
- }
- if (params.getSignatureAlgorithm() == null) {
- log.debug("Validation failure: Unable to resolve signing algorithm URI");
- return false;
- }
- return true;
- }
+ }
/**
* Convert the algorithms represented as strings, into Nimbus {@link Algorithm}s for later comparison.
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/impl/EncryptJWT.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/impl/EncryptJWT.java
index c621158..31cf4b1 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/impl/EncryptJWT.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/impl/EncryptJWT.java
@@ -43,11 +43,13 @@ import com.nimbusds.jose.JWEHeader;
import com.nimbusds.jose.JWEObject;
import com.nimbusds.jose.Payload;
import com.nimbusds.jose.crypto.AESEncrypter;
+import com.nimbusds.jose.crypto.DirectEncrypter;
import com.nimbusds.jose.crypto.ECDHEncrypter;
import com.nimbusds.jose.crypto.RSAEncrypter;
import com.nimbusds.jwt.EncryptedJWT;
import com.nimbusds.jwt.JWT;
+import net.shibboleth.oidc.security.JWTEncryptionParameters;
import net.shibboleth.oidc.security.context.JWTSecurityParametersContext;
import net.shibboleth.oidc.security.impl.CredentialConversionUtil;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
@@ -61,7 +63,6 @@ import net.shibboleth.utilities.java.support.primitive.StringSupport;
* {@link JWTSecurityParametersContext}. The {@link Payload} to encrypt is determined by lookup strategy.
* A consumer takes the {@link EncryptedJWT} and updates the correct object in the {@link MessageContext}.
*/
-//TODO does not support 'dir'?
public class EncryptJWT extends AbstractMessageHandler {
/** Class logger. */
@@ -77,7 +78,7 @@ public class EncryptJWT extends AbstractMessageHandler {
@NonnullAfterInit private BiConsumer<JWT, MessageContext> jwtUpdateConsumer;
/** The signature signing parameters. */
- @Nullable private EncryptionParameters encryptionParameters;
+ @Nullable private JWTEncryptionParameters encryptionParameters;
/** Constructor.*/
@@ -192,8 +193,11 @@ public class EncryptJWT extends AbstractMessageHandler {
jweObject.encrypt(new RSAEncrypter((RSAPublicKey) credential.getPublicKey()));
} else if (JWEAlgorithm.Family.ECDH_ES.contains(encAlg) && credential.getPublicKey() != null) {
jweObject.encrypt(new ECDHEncrypter((ECPublicKey) credential.getPublicKey()));
- } else if (JWEAlgorithm.Family.SYMMETRIC.contains(encAlg) && credential.getSecretKey() != null) {
+ } else if ((JWEAlgorithm.Family.AES_KW.contains(encAlg) || JWEAlgorithm.Family.AES_GCM_KW.contains(encAlg))
+ && credential.getSecretKey() != null) {
jweObject.encrypt(new AESEncrypter(credential.getSecretKey()));
+ } else if (JWEAlgorithm.DIR.equals(encAlg) && credential.getSecretKey() != null){
+ jweObject.encrypt(new DirectEncrypter(credential.getSecretKey()));
} else {
log.error("{} Unsupported algorithm {} or key '{}'", getLogPrefix(), encAlg.getName(),
kid);
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/impl/SignRequestObject.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/impl/SignRequestObject.java
index d15b3c1..26fd3e5 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/impl/SignRequestObject.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/impl/SignRequestObject.java
@@ -29,7 +29,6 @@ import org.opensaml.messaging.context.navigate.ChildContextLookup;
import org.opensaml.messaging.handler.AbstractMessageHandler;
import org.opensaml.messaging.handler.MessageHandlerException;
import org.opensaml.security.credential.Credential;
-import org.opensaml.xmlsec.SignatureSigningParameters;
import org.opensaml.xmlsec.context.SecurityParametersContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -41,7 +40,6 @@ import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.JWSObject.State;
import com.nimbusds.jose.JWSSigner;
-import com.nimbusds.jose.Payload;
import com.nimbusds.jose.crypto.ECDSASigner;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.RSASSASigner;
@@ -49,6 +47,7 @@ import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
+import net.shibboleth.oidc.security.JWTSignatureSigningParameters;
import net.shibboleth.oidc.security.context.JWTSecurityParametersContext;
import net.shibboleth.oidc.security.credential.JWKCredential;
import net.shibboleth.oidc.security.impl.CredentialConversionUtil;
@@ -78,7 +77,7 @@ public class SignRequestObject extends AbstractMessageHandler {
@NonnullAfterInit private Function<MessageContext, JWTClaimsSet> claimsToSignLookupStrategy;
/** The signature signing parameters. */
- @Nullable private SignatureSigningParameters signatureSigningParameters;
+ @Nullable private JWTSignatureSigningParameters signatureSigningParameters;
/** resolved credential. */
@Nullable private Credential credential;
diff --git a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
index c43f38c..fe7479f 100644
--- a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
+++ b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
@@ -63,6 +63,28 @@
<!-- Security Configuration Defaults. These settings establish the default security configurations for signatures and
loads the default credentials used. -->
+
+ <!-- TODO change the signature config over to JWT -->
+ <bean id="shibboleth.authn.oidc.rp.BasicSignatureValidationConfiguration" abstract="true"
+ class="org.opensaml.xmlsec.impl.BasicSignatureValidationConfiguration"
+ p:includedAlgorithms="#{getObject('shibboleth.authn.oidc.rp.IncludedSignatureAlgorithms')}"
+ p:excludedAlgorithms="#{getObject('shibboleth.authn.oidc.rp.ExcludedSignatureAlgorithms')}" />
+
+ <bean id="shibboleth.authn.oidc.rp.BasicSignatureSigningConfiguration" abstract="true"
+ class="org.opensaml.xmlsec.impl.BasicSignatureSigningConfiguration"
+ p:includedAlgorithms="#{getObject('shibboleth.authn.oidc.rp.IncludedSignatureAlgorithms')}"
+ p:excludedAlgorithms="#{getObject('shibboleth.authn.oidc.rp.ExcludedSignatureAlgorithms')}" />
+
+ <bean id="shibboleth.authn.oidc.rp.BasicEncryptionConfiguration" abstract="true"
+ class="net.shibboleth.oidc.security.impl.BasicJWTEncryptionConfiguration"
+ p:includedAlgorithms="#{getObject('shibboleth.authn.oidc.rp.IncludedEncryptionAlgorithms')}"
+ p:excludedAlgorithms="#{getObject('shibboleth.authn.oidc.rp.ExcludedEncryptionAlgorithms')}" />
+
+ <bean id="shibboleth.authn.oidc.rp.BasicDecryptionConfiguration" abstract="true"
+ class="net.shibboleth.oidc.security.impl.BasicJWTDecryptionConfiguration"
+ p:includedAlgorithms="#{getObject('shibboleth.authn.oidc.rp.IncludedEncryptionAlgorithms')}"
+ p:excludedAlgorithms="#{getObject('shibboleth.authn.oidc.rp.ExcludedEncryptionAlgorithms')}" />
+
<bean id="shibboleth.authn.oidc.rp.DefaultSecurityConfiguration"
class="net.shibboleth.oidc.profile.config.OIDCSecurityConfiguration">
@@ -89,17 +111,19 @@
bean="#{'%{idp.authn.oidc.rp.requestobject.signing.config:shibboleth.authn.oidc.rp.DefaultRequestObjectSigningConfiguration}'.trim()}" />
</property>
<!-- For now, Request Object encryption configuration only -->
- <property name="encryptionConfiguration">
+ <property name="requestObjectEncryptionConfig">
<ref
- bean="#{'%{idp.authn.oidc.rp.encryption.config:shibboleth.authn.oidc.rp.EncryptionConfiguration}'.trim()}" />
+ bean="#{'%{idp.authn.oidc.rp.requestobject.encryption.config:shibboleth.authn.oidc.rp.DefaultRequestObjectEncryptionConfiguration}'.trim()}" />
</property>
</bean>
<!-- Configuration for supported algorithms for Request Object encryption. -->
- <bean id="shibboleth.authn.oidc.rp.EncryptionConfiguration" parent="shibboleth.BasicEncryptionConfiguration"
- p:keyTransportEncryptionCredentials="#{getObject('shibboleth.authn.oidc.rp.RequestObjectEncryptionCredentials')}">
+ <bean id="shibboleth.authn.oidc.rp.DefaultRequestObjectEncryptionConfiguration"
+ parent="shibboleth.authn.oidc.rp.BasicEncryptionConfiguration"
+ p:keyTransportEncryptionCredentials-ref="shibboleth.authn.oidc.rp.RequestObjectKeyTransportEncryptionCredentials"
+ p:dataEncryptionCredentials-ref="shibboleth.authn.oidc.rp.RequestObjectDataEncryptionCredentials">
<property name="keyTransportEncryptionAlgorithms">
- <list>
+ <list>
<util:constant
static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_RSA_1_5" />
<util:constant
@@ -118,6 +142,8 @@
static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_AES_192_GCM_KW" />
<util:constant
static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_AES_256_GCM_KW" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_ECDH_ES" />
</list>
</property>
<property name="dataEncryptionAlgorithms">
@@ -142,7 +168,7 @@
from the RP's configuration will be included in the set of usable credentials -->
<bean id="shibboleth.authn.oidc.rp.DefaultRequestObjectSigningConfiguration"
parent="shibboleth.BasicSignatureSigningConfiguration"
- p:signingCredentials="#{getObject('shibboleth.authn.oidc.rp.SigningCredentials')}">
+ p:signingCredentials-ref="shibboleth.authn.oidc.rp.SigningCredentials">
<property name="signatureAlgorithms">
<list>
<util:constant
@@ -163,20 +189,24 @@
<bean id="shibboleth.authn.oidc.rp.SigningCredentials"
class="net.shibboleth.idp.plugin.authn.oidc.rp.config.CredentialsListFactory"
- c:_0-ref="shibboleth.authn.oidc.rp.DefaultSigningCredentials" />
+ c:_0="#{getObject('shibboleth.authn.oidc.rp.DefaultSigningCredentials')}" />
- <bean id="shibboleth.authn.oidc.rp.RequestObjectEncryptionCredentials"
+ <bean id="shibboleth.authn.oidc.rp.RequestObjectKeyTransportEncryptionCredentials"
class="net.shibboleth.idp.plugin.authn.oidc.rp.config.CredentialsListFactory"
- c:_0-ref="shibboleth.authn.oidc.rp.DefaultRequestObjectEncryptionCredentials" />
-
+ c:_0="#{getObject('shibboleth.authn.oidc.rp.DefaultRequestObjectKeyTransportEncryptionCredentials')}" />
+
+ <bean id="shibboleth.authn.oidc.rp.RequestObjectDataEncryptionCredentials"
+ class="net.shibboleth.idp.plugin.authn.oidc.rp.config.CredentialsListFactory"
+ c:_0="#{getObject('shibboleth.authn.oidc.rp.DefaultRequestObjectDataEncryptionCredentials')}" />
<bean id="shibboleth.authn.oidc.rp.DefaultCredential" parent="shibboleth.authn.oidc.rp.ExpiringJWKCredential"
- p:secret="%{idp.authn.oidc.rp.client.clientSecret:#{null}}" p:keyNames="defaultPropertiesClientSecret"
+ p:secret="%{idp.authn.oidc.rp.client.clientSecret:#{null}}"
+ p:keyNames="%{idp.authn.oidc.rp.client.clientSecretKeyName:defaultPropertiesClientSecret}"
p:alg="dir" />
<bean id="shibboleth.authn.oidc.rp.DefaultJWTDecryptionConfiguration"
- class="net.shibboleth.oidc.security.impl.BasicJWTDecryptionConfiguration"
+ parent="shibboleth.authn.oidc.rp.BasicDecryptionConfiguration"
p:KEKCredentialResolver-ref="defaultOIDCRPKeyEncryptionCredentialResolver"
p:contentEncryptionKeyCredentialResolver-ref="defaultOIDCRPContentEncryptionKeyCredentialResolver" />
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AuthorizationControllerTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AuthorizationControllerTest.java
index 8ec7aeb..67986c3 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AuthorizationControllerTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AuthorizationControllerTest.java
@@ -48,8 +48,6 @@ import org.opensaml.profile.action.AbstractProfileAction;
import org.opensaml.profile.action.ActionSupport;
import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.xmlsec.EncryptionParameters;
-import org.opensaml.xmlsec.SignatureSigningParameters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
@@ -104,6 +102,8 @@ import net.shibboleth.oidc.profile.config.OIDCAuthorizationConfiguration.OIDCHtt
import net.shibboleth.oidc.profile.core.OIDCAuthenticationRequest;
import net.shibboleth.oidc.profile.decoding.OIDCMessageDecoder;
import net.shibboleth.oidc.profile.encoder.impl.AbstractOIDCMessageEncoder;
+import net.shibboleth.oidc.security.JWTEncryptionParameters;
+import net.shibboleth.oidc.security.JWTSignatureSigningParameters;
import net.shibboleth.oidc.security.context.JWTSecurityParametersContext;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.net.HttpServletSupport;
@@ -315,12 +315,12 @@ public class AuthorizationControllerTest extends AbstractTestNGSpringContextTest
// Create a sec context under the nested prc outbound msg context
final var secContext = prc.getOutboundMessageContext().getSubcontext(JWTSecurityParametersContext.class, true);
- final var sigParams = new SignatureSigningParameters();
+ final var sigParams = new JWTSignatureSigningParameters();
sigParams.setSignatureAlgorithm("HS256");
sigParams.setSigningCredential(TestCredentialHelper.createClientSecretCredential(CLIENT_SECRET));
secContext.setSignatureSigningParameters(sigParams);
- final var encParams = new EncryptionParameters();
+ final var encParams = new JWTEncryptionParameters();
encParams.setDataEncryptionAlgorithm("A128CBC-HS256");
encParams.setKeyTransportEncryptionAlgorithm("RSA-OAEP-256");
final RSAKey key = new RSAKeyGenerator(2048)
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/EncryptJWTTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/EncryptJWTTest.java
index f8afacf..900eb57 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/EncryptJWTTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/EncryptJWTTest.java
@@ -1,5 +1,20 @@
package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
-
+/*
+ * 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.
+ */
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
@@ -9,7 +24,6 @@ import static org.testng.Assert.fail;
import java.util.Date;
import org.opensaml.messaging.handler.MessageHandlerException;
-import org.opensaml.xmlsec.EncryptionParameters;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@@ -17,12 +31,12 @@ import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWEAlgorithm;
import com.nimbusds.jose.JWEObject.State;
import com.nimbusds.jose.crypto.AESDecrypter;
+import com.nimbusds.jose.crypto.DirectDecrypter;
import com.nimbusds.jose.crypto.ECDHDecrypter;
import com.nimbusds.jose.crypto.RSADecrypter;
import com.nimbusds.jose.jwk.Curve;
import com.nimbusds.jose.jwk.ECKey;
import com.nimbusds.jose.jwk.KeyUse;
-import com.nimbusds.jose.jwk.OctetKeyPair;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.gen.ECKeyGenerator;
import com.nimbusds.jose.jwk.gen.RSAKeyGenerator;
@@ -32,6 +46,7 @@ import com.nimbusds.jwt.JWTClaimsSet;
import net.shibboleth.idp.plugin.authn.oidc.rp.messaging.impl.EncryptJWT;
import net.shibboleth.oidc.jwa.support.EncryptionConstants;
import net.shibboleth.oidc.jwa.support.KeyManagementConstants;
+import net.shibboleth.oidc.security.JWTEncryptionParameters;
import net.shibboleth.oidc.security.context.JWTSecurityParametersContext;
/** Tests for EncryptJWT.*/
@@ -47,7 +62,7 @@ public class EncryptJWTTest extends AbstractOIDCTest {
private JWTSecurityParametersContext secContext;
/** The encryption params to use.*/
- private EncryptionParameters params;
+ private JWTEncryptionParameters params;
@Override
@BeforeMethod
@@ -79,7 +94,7 @@ public class EncryptJWTTest extends AbstractOIDCTest {
secContext =
prc.getOutboundMessageContext().getSubcontext(JWTSecurityParametersContext.class, true);
- params = new EncryptionParameters();
+ params = new JWTEncryptionParameters();
secContext.setEncryptionParameters(params);
}
@@ -180,6 +195,28 @@ public class EncryptJWTTest extends AbstractOIDCTest {
assertEquals(claims.getIssuer(), "https://rp.example.com");
}
+ @Test
+ public void testEncryptWithDirectEncryption() throws Exception {
+
+ params.setKeyTransportEncryptionAlgorithm(KeyManagementConstants.ALGO_ID_ALG_DIR);
+ params.setDataEncryptionAlgorithm(EncryptionConstants.ALGO_ID_ENC_ALG_A256GCM);
+ final var sharedKey = TestCredentialHelper.createClientSecretCredential(CLIENT_SECRET);
+ params.setKeyTransportEncryptionCredential(sharedKey);
+
+ action.initialize();
+ action.invoke(prc.getOutboundMessageContext());
+
+ assertNotNull(prc.getOutboundMessageContext().getMessage());
+ assertTrue(prc.getOutboundMessageContext().getMessage() instanceof EncryptedJWT);
+
+ final EncryptedJWT encryptedJWT = (EncryptedJWT) prc.getOutboundMessageContext().getMessage();
+ final DirectDecrypter decrypter = new DirectDecrypter(sharedKey.getSecretKey());
+ encryptedJWT.decrypt(decrypter);
+ assertTrue(encryptedJWT.getState() == State.DECRYPTED);
+ final JWTClaimsSet claims = encryptedJWT.getJWTClaimsSet();
+ assertEquals(claims.getIssuer(), "https://rp.example.com");
+ }
+
@Test
public void testEncryptWithKeyAgreement() throws Exception {
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ProviderMetadataEncryptionParametersResolverTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ProviderMetadataEncryptionParametersResolverTest.java
index b978f5e..514f8a8 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ProviderMetadataEncryptionParametersResolverTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ProviderMetadataEncryptionParametersResolverTest.java
@@ -17,6 +17,7 @@
package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
+import static org.junit.Assert.assertNull;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
@@ -36,23 +37,26 @@ import org.mockito.Mockito;
import org.opensaml.core.config.InitializationException;
import org.opensaml.storage.StorageService;
import org.opensaml.storage.impl.MemoryStorageService;
-import org.opensaml.xmlsec.EncryptionParameters;
import org.opensaml.xmlsec.config.GlobalAlgorithmRegistryInitializer;
-import org.opensaml.xmlsec.criterion.EncryptionConfigurationCriterion;
-import org.opensaml.xmlsec.impl.BasicEncryptionConfiguration;
import org.springframework.core.io.ClassPathResource;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.nimbusds.jose.JWEAlgorithm;
+import com.nimbusds.jose.jwk.KeyUse;
+import com.nimbusds.jose.jwk.RSAKey;
+import com.nimbusds.jose.jwk.gen.RSAKeyGenerator;
import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
import net.shibboleth.oidc.jwa.support.EncryptionConstants;
import net.shibboleth.oidc.jwa.support.KeyManagementConstants;
import net.shibboleth.oidc.jwk.RemoteJwkSetCache;
+import net.shibboleth.oidc.security.JWTEncryptionParameters;
import net.shibboleth.oidc.security.credential.JWKCredential;
+import net.shibboleth.oidc.security.criterion.JWTEncryptionConfigurationCriterion;
import net.shibboleth.oidc.security.criterion.ProviderMetadataCriterion;
import net.shibboleth.oidc.security.criterion.StaticCredentialCriterion;
+import net.shibboleth.oidc.security.impl.BasicJWTEncryptionConfiguration;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
@@ -82,11 +86,19 @@ public class ProviderMetadataEncryptionParametersResolverTest {
private ProviderMetadataEncryptionParametersResolver resolver;
/** The basic config.*/
- private BasicEncryptionConfiguration config;
+ private BasicJWTEncryptionConfiguration config;
@BeforeMethod
public void setup() throws ComponentInitializationException, ClientProtocolException, IOException {
+ //Create an algorithm registry here, as opensaml init will not take place for these tests
+ try {
+ final GlobalAlgorithmRegistryInitializer gar = new GlobalAlgorithmRegistryInitializer();
+ gar.init();
+ } catch (final InitializationException e) {
+ fail();
+ }
+
resolver = new ProviderMetadataEncryptionParametersResolver();
resolver.setProviderEncryptionMethodsLookupStrategy(OIDCProviderMetadata::getRequestObjectJWEEncs);
resolver.setProviderKeyTransportAlgorithmsLookupStrategy(OIDCProviderMetadata::getRequestObjectJWEAlgs);
@@ -112,24 +124,16 @@ public class ProviderMetadataEncryptionParametersResolverTest {
return storageService;
}
- private CriteriaSet buildBasicCriteriaSet() throws Exception {
-
- //Create an algorithm registry here, as opensaml init will not take place for these tests
- try {
- final GlobalAlgorithmRegistryInitializer gar = new GlobalAlgorithmRegistryInitializer();
- gar.init();
- } catch (final InitializationException e) {
- fail();
- }
+ private CriteriaSet buildBasicCriteriaSet() throws Exception {
- config = new BasicEncryptionConfiguration();
+ config = new BasicJWTEncryptionConfiguration();
config.setKeyTransportEncryptionAlgorithms(
List.of(KeyManagementConstants.ALGO_ID_ALG_AES_128_KW, KeyManagementConstants.ALGO_ID_ALG_RSA_OAEP_256,
KeyManagementConstants.ALGO_ID_ALG_ECDH_ES_AES_192_KW, KeyManagementConstants.ALGO_ID_ALG_RSA_OAEP));
config.setDataEncryptionAlgorithms(
List.of(EncryptionConstants.ALGO_ID_ENC_ALG_A128CBC_HS256,EncryptionConstants.ALGO_ID_ENC_ALG_A128GCM,
EncryptionConstants.ALGO_ID_ENC_ALG_A256CBC_HS512));
- final CriteriaSet criteria = new CriteriaSet(new EncryptionConfigurationCriterion(List.of(config)));
+ final CriteriaSet criteria = new CriteriaSet(new JWTEncryptionConfigurationCriterion(List.of(config)));
criteria.add(new ProviderMetadataCriterion(
OIDCProviderMetadata.parse(TestJsonHelper.readJsonFromFile(GOOD_PROVIDER_CONFIGURATION_INFO))));
criteria.add(
@@ -139,10 +143,10 @@ public class ProviderMetadataEncryptionParametersResolverTest {
@Test
public void testSuccessfulResolution() throws Exception {
- final Iterable<EncryptionParameters> params = resolver.resolve(buildBasicCriteriaSet());
+ final Iterable<JWTEncryptionParameters> params = resolver.resolve(buildBasicCriteriaSet());
assertNotNull(params);
assertTrue(params.iterator().hasNext());
- final EncryptionParameters param = params.iterator().next();
+ final JWTEncryptionParameters param = params.iterator().next();
assertNotNull(param.getDataEncryptionAlgorithm());
assertNotNull(param.getKeyTransportEncryptionAlgorithm());
assertNotNull(param.getKeyTransportEncryptionCredential());
@@ -156,10 +160,10 @@ public class ProviderMetadataEncryptionParametersResolverTest {
config.setKeyTransportEncryptionAlgorithms(List.of(KeyManagementConstants.ALGO_ID_ALG_RSA_OAEP));
config.setDataEncryptionAlgorithms(List.of(EncryptionConstants.ALGO_ID_ENC_ALG_A256CBC_HS512));
- final Iterable<EncryptionParameters> params = resolver.resolve(criteria);
+ final Iterable<JWTEncryptionParameters> params = resolver.resolve(criteria);
assertNotNull(params);
assertTrue(params.iterator().hasNext());
- final EncryptionParameters param = params.iterator().next();
+ final JWTEncryptionParameters param = params.iterator().next();
assertNotNull(param.getDataEncryptionAlgorithm());
assertNotNull(param.getKeyTransportEncryptionAlgorithm());
assertEquals(param.getDataEncryptionAlgorithm(),EncryptionConstants.ALGO_ID_ENC_ALG_A256CBC_HS512);
@@ -177,10 +181,10 @@ public class ProviderMetadataEncryptionParametersResolverTest {
KeyManagementConstants.ALGO_ID_ALG_AES_128_KW));
config.setDataEncryptionAlgorithms(List.of(EncryptionConstants.ALGO_ID_ENC_ALG_A256CBC_HS512));
- final Iterable<EncryptionParameters> params = resolver.resolve(criteria);
+ final Iterable<JWTEncryptionParameters> params = resolver.resolve(criteria);
assertNotNull(params);
assertTrue(params.iterator().hasNext());
- final EncryptionParameters param = params.iterator().next();
+ final JWTEncryptionParameters param = params.iterator().next();
assertNotNull(param.getDataEncryptionAlgorithm());
assertNotNull(param.getKeyTransportEncryptionAlgorithm());
assertEquals(param.getDataEncryptionAlgorithm(),EncryptionConstants.ALGO_ID_ENC_ALG_A256CBC_HS512);
@@ -200,10 +204,10 @@ public class ProviderMetadataEncryptionParametersResolverTest {
List.of(TestCredentialHelper.createClientSecretCredential("mockKey",
SYMMETRIC_KEY, JWEAlgorithm.A256KW)));
- final Iterable<EncryptionParameters> params = resolver.resolve(criteria);
+ final Iterable<JWTEncryptionParameters> params = resolver.resolve(criteria);
assertNotNull(params);
assertTrue(params.iterator().hasNext());
- final EncryptionParameters param = params.iterator().next();
+ final JWTEncryptionParameters param = params.iterator().next();
assertNotNull(param.getDataEncryptionAlgorithm());
assertNotNull(param.getKeyTransportEncryptionAlgorithm());
assertEquals(param.getDataEncryptionAlgorithm(),EncryptionConstants.ALGO_ID_ENC_ALG_A256CBC_HS512);
@@ -221,10 +225,10 @@ public class ProviderMetadataEncryptionParametersResolverTest {
List.of(TestCredentialHelper.createClientSecretCredential("mockKey", SYMMETRIC_KEY,
JWEAlgorithm.A256KW)));
- final Iterable<EncryptionParameters> params = resolver.resolve(criteria);
+ final Iterable<JWTEncryptionParameters> params = resolver.resolve(criteria);
assertNotNull(params);
assertTrue(params.iterator().hasNext());
- final EncryptionParameters param = params.iterator().next();
+ final JWTEncryptionParameters param = params.iterator().next();
assertNotNull(param.getDataEncryptionAlgorithm());
assertNotNull(param.getKeyTransportEncryptionAlgorithm());
assertEquals(param.getDataEncryptionAlgorithm(),EncryptionConstants.ALGO_ID_ENC_ALG_A128GCM);
@@ -233,6 +237,65 @@ public class ProviderMetadataEncryptionParametersResolverTest {
assertNotNull(param.getKeyTransportEncryptionCredential().getSecretKey());
}
+ /* Runtime does not yet support 'dir' key transport, so disabled for now.*/
+ @Test(enabled = false)
+ public void testSuccessfulResolution_ForDirectEncryption() throws Exception {
+ final CriteriaSet criteria = buildBasicCriteriaSet();
+ config.setKeyTransportEncryptionAlgorithms(List.of(KeyManagementConstants.ALGO_ID_ALG_DIR));
+ config.setDataEncryptionAlgorithms(List.of(EncryptionConstants.ALGO_ID_ENC_ALG_A256GCM));
+ config.setDataEncryptionCredentials(
+ List.of(TestCredentialHelper.createClientSecretCredential("mockKey", SYMMETRIC_KEY,
+ JWEAlgorithm.DIR)));
+
+ final Iterable<JWTEncryptionParameters> params = resolver.resolve(criteria);
+ assertNotNull(params);
+ assertTrue(params.iterator().hasNext());
+ final JWTEncryptionParameters param = params.iterator().next();
+ assertNotNull(param.getDataEncryptionAlgorithm());
+ assertNotNull(param.getKeyTransportEncryptionAlgorithm());
+ assertEquals(param.getDataEncryptionAlgorithm(),EncryptionConstants.ALGO_ID_ENC_ALG_A256GCM);
+ assertEquals(param.getKeyTransportEncryptionAlgorithm(),KeyManagementConstants.ALGO_ID_ALG_DIR);
+ assertNull(param.getKeyTransportEncryptionCredential());
+ assertNotNull(param.getDataEncryptionCredential());
+ assertNotNull(param.getDataEncryptionCredential().getSecretKey());
+ assertTrue(param.getDataEncryptionCredential().getKeyNames().contains("mockKey"));
+ }
+
+ /*
+ * The local RSA key should be derived from the local config even if provider metadata is excluded from
+ * the criteria set.
+ */
+ @Test
+ public void testSuccessfulResolution_NoProviderMetadata_FallBackToLocalBehaviour() throws Exception {
+ // Do not add ProviderMetadataCriterion
+ buildBasicCriteriaSet();
+ final CriteriaSet criteria = new CriteriaSet(new JWTEncryptionConfigurationCriterion(List.of(config)));
+
+ config.setKeyTransportEncryptionAlgorithms(List.of(KeyManagementConstants.ALGO_ID_ALG_RSA_OAEP_256));
+ config.setDataEncryptionAlgorithms(List.of(EncryptionConstants.ALGO_ID_ENC_ALG_A128GCM));
+
+ final RSAKey key = new RSAKeyGenerator(2048)
+ .algorithm(JWEAlgorithm.RSA_OAEP_256)
+ .keyUse(KeyUse.ENCRYPTION)
+ .keyID("mock-key")
+ .generate();
+
+ config.setKeyTransportEncryptionCredentials(
+ List.of(TestCredentialHelper.createKeyEncryptionCredential(key)));
+
+ final Iterable<JWTEncryptionParameters> params = resolver.resolve(criteria);
+ assertNotNull(params);
+ assertTrue(params.iterator().hasNext());
+ final JWTEncryptionParameters param = params.iterator().next();
+ assertNotNull(param.getDataEncryptionAlgorithm());
+ assertNotNull(param.getKeyTransportEncryptionAlgorithm());
+ assertEquals(param.getDataEncryptionAlgorithm(),EncryptionConstants.ALGO_ID_ENC_ALG_A128GCM);
+ assertEquals(param.getKeyTransportEncryptionAlgorithm(),KeyManagementConstants.ALGO_ID_ALG_RSA_OAEP_256);
+ assertNotNull(param.getKeyTransportEncryptionCredential());
+ assertTrue(param.getKeyTransportEncryptionCredential().getKeyNames().contains("mock-key"));
+ assertNotNull(param.getKeyTransportEncryptionCredential().getPublicKey());
+ }
+
/* The first mockKey in the list should be resolved.*/
@Test
public void testSuccessfulResolution_ForKeyWrap_MoreThanOneKeyWrapCred() throws Exception {
@@ -245,10 +308,10 @@ public class ProviderMetadataEncryptionParametersResolverTest {
TestCredentialHelper.createClientSecretCredential("mockKeyTwo", SYMMETRIC_KEY_TWO,
JWEAlgorithm.A256KW)));
- final Iterable<EncryptionParameters> params = resolver.resolve(criteria);
+ final Iterable<JWTEncryptionParameters> params = resolver.resolve(criteria);
assertNotNull(params);
assertTrue(params.iterator().hasNext());
- final EncryptionParameters param = params.iterator().next();
+ final JWTEncryptionParameters param = params.iterator().next();
assertNotNull(param.getDataEncryptionAlgorithm());
assertNotNull(param.getKeyTransportEncryptionAlgorithm());
assertEquals(param.getDataEncryptionAlgorithm(),EncryptionConstants.ALGO_ID_ENC_ALG_A128GCM);
@@ -266,7 +329,7 @@ public class ProviderMetadataEncryptionParametersResolverTest {
config.setKeyTransportEncryptionAlgorithms(List.of(KeyManagementConstants.ALGO_ID_ALG_AES_256_KW));
config.setDataEncryptionAlgorithms(List.of(EncryptionConstants.ALGO_ID_ENC_ALG_A128GCM));
- final Iterable<EncryptionParameters> params = resolver.resolve(criteria);
+ final Iterable<JWTEncryptionParameters> params = resolver.resolve(criteria);
assertNotNull(params);
assertFalse(params.iterator().hasNext());
}
@@ -277,10 +340,10 @@ public class ProviderMetadataEncryptionParametersResolverTest {
config.setKeyTransportEncryptionAlgorithms(List.of(KeyManagementConstants.ALGO_ID_ALG_ECDH_ES));
config.setDataEncryptionAlgorithms(List.of(EncryptionConstants.ALGO_ID_ENC_ALG_A128GCM));
- final Iterable<EncryptionParameters> params = resolver.resolve(criteria);
+ final Iterable<JWTEncryptionParameters> params = resolver.resolve(criteria);
assertNotNull(params);
assertTrue(params.iterator().hasNext());
- final EncryptionParameters param = params.iterator().next();
+ final JWTEncryptionParameters param = params.iterator().next();
assertNotNull(param.getDataEncryptionAlgorithm());
assertNotNull(param.getKeyTransportEncryptionAlgorithm());
assertEquals(param.getDataEncryptionAlgorithm(),EncryptionConstants.ALGO_ID_ENC_ALG_A128GCM);
@@ -294,7 +357,7 @@ public class ProviderMetadataEncryptionParametersResolverTest {
final CriteriaSet criteria = buildBasicCriteriaSet();
config.setKeyTransportEncryptionAlgorithms(List.of("NOT-SUPPORTED"));
- final Iterable<EncryptionParameters> params = resolver.resolve(criteria);
+ final Iterable<JWTEncryptionParameters> params = resolver.resolve(criteria);
assertNotNull(params);
assertFalse(params.iterator().hasNext());
}
@@ -302,9 +365,9 @@ public class ProviderMetadataEncryptionParametersResolverTest {
@Test
public void testUnSuccessfulResolution_OnlyConfigCriterion() throws Exception {
buildBasicCriteriaSet();
- final CriteriaSet criteria = new CriteriaSet(new EncryptionConfigurationCriterion(List.of(config)));
+ final CriteriaSet criteria = new CriteriaSet(new JWTEncryptionConfigurationCriterion(List.of(config)));
- final Iterable<EncryptionParameters> params = resolver.resolve(criteria);
+ final Iterable<JWTEncryptionParameters> params = resolver.resolve(criteria);
assertNotNull(params);
assertFalse(params.iterator().hasNext());
}
@@ -314,7 +377,7 @@ public class ProviderMetadataEncryptionParametersResolverTest {
final CriteriaSet criteria = buildBasicCriteriaSet();
config.setDataEncryptionAlgorithms(List.of("NOT-SUPPORTED"));
- final Iterable<EncryptionParameters> params = resolver.resolve(criteria);
+ final Iterable<JWTEncryptionParameters> params = resolver.resolve(criteria);
assertNotNull(params);
assertFalse(params.iterator().hasNext());
}
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/RelyingPartyProxySigningParametersResolverTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/RelyingPartyProxySigningParametersResolverTest.java
index 5bb5338..8cbea30 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/RelyingPartyProxySigningParametersResolverTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/RelyingPartyProxySigningParametersResolverTest.java
@@ -35,7 +35,6 @@ import javax.crypto.spec.SecretKeySpec;
import org.opensaml.core.config.InitializationException;
import org.opensaml.security.credential.UsageType;
-import org.opensaml.xmlsec.SignatureSigningParameters;
import org.opensaml.xmlsec.config.GlobalAlgorithmRegistryInitializer;
import org.opensaml.xmlsec.criterion.SignatureSigningConfigurationCriterion;
import org.opensaml.xmlsec.impl.BasicSignatureSigningConfiguration;
@@ -58,6 +57,7 @@ import net.shibboleth.idp.profile.context.RelyingPartyContext;
import net.shibboleth.idp.relyingparty.RelyingPartyConfiguration;
import net.shibboleth.oidc.jwa.support.SignatureConstants;
import net.shibboleth.oidc.profile.config.OIDCAuthorizationConfiguration;
+import net.shibboleth.oidc.security.JWTSignatureSigningParameters;
import net.shibboleth.oidc.security.credential.BasicExpiringJWKCredential;
import net.shibboleth.oidc.security.credential.JWKCredential;
import net.shibboleth.oidc.security.criterion.ProviderMetadataCriterion;
@@ -105,7 +105,7 @@ public class RelyingPartyProxySigningParametersResolverTest extends AbstractOIDC
public void testResolveSuccess_StaticCredentials() throws ResolverException {
final CriteriaSet criteria = buildCriteria(List.of(SignatureConstants.ALGO_ID_SIGNATURE_HS_256));
criteria.add(new StaticCredentialCriterion(createClientSecretCredential("atestsecret")));
- final Iterable<SignatureSigningParameters> params = resolver.resolve(criteria);
+ final Iterable<JWTSignatureSigningParameters> params = resolver.resolve(criteria);
assertNotNull(params);
assertTrue(params.iterator().hasNext());
assertNotNull(params.iterator().next().getSigningCredential());
@@ -116,7 +116,7 @@ public class RelyingPartyProxySigningParametersResolverTest extends AbstractOIDC
public void testResolveFail_StaticCredentials_UnsupportedMethod() throws ResolverException {
final CriteriaSet criteria = buildCriteria(List.of(SignatureConstants.ALGO_ID_SIGNATURE_RS_256));
criteria.add(new StaticCredentialCriterion(createClientSecretCredential("atestsecret")));
- final Iterable<SignatureSigningParameters> params = resolver.resolve(criteria);
+ final Iterable<JWTSignatureSigningParameters> params = resolver.resolve(criteria);
assertNotNull(params);
assertFalse(params.iterator().hasNext());
}
@@ -126,7 +126,7 @@ public class RelyingPartyProxySigningParametersResolverTest extends AbstractOIDC
final CriteriaSet criteria = buildCriteria(List.of(SignatureConstants.ALGO_ID_SIGNATURE_RS_256,
SignatureConstants.ALGO_ID_SIGNATURE_HS_256));
criteria.add(new StaticCredentialCriterion(createClientSecretCredential("atestsecret")));
- final Iterable<SignatureSigningParameters> params = resolver.resolve(criteria);
+ final Iterable<JWTSignatureSigningParameters> params = resolver.resolve(criteria);
assertNotNull(params);
assertTrue(params.iterator().hasNext());
assertNotNull(params.iterator().next().getSigningCredential());
@@ -145,7 +145,7 @@ public class RelyingPartyProxySigningParametersResolverTest extends AbstractOIDC
metadata.setRequestObjectJWSAlgs(List.of(JWSAlgorithm.HS256));
criteria.add(new ProviderMetadataCriterion(metadata));
- final Iterable<SignatureSigningParameters> params = resolver.resolve(criteria);
+ final Iterable<JWTSignatureSigningParameters> params = resolver.resolve(criteria);
assertNotNull(params);
assertTrue(params.iterator().hasNext());
assertNotNull(params.iterator().next().getSigningCredential());
@@ -164,7 +164,7 @@ public class RelyingPartyProxySigningParametersResolverTest extends AbstractOIDC
metadata.setRequestObjectJWSAlgs(List.of(JWSAlgorithm.EdDSA));
criteria.add(new ProviderMetadataCriterion(metadata));
- final Iterable<SignatureSigningParameters> params = resolver.resolve(criteria);
+ final Iterable<JWTSignatureSigningParameters> params = resolver.resolve(criteria);
assertNotNull(params);
assertFalse(params.iterator().hasNext());
}
@@ -193,7 +193,7 @@ public class RelyingPartyProxySigningParametersResolverTest extends AbstractOIDC
metadata.setRequestObjectJWSAlgs(List.of(JWSAlgorithm.RS256));
criteria.add(new ProviderMetadataCriterion(metadata));
- final Iterable<SignatureSigningParameters> params = resolver.resolve(criteria);
+ final Iterable<JWTSignatureSigningParameters> params = resolver.resolve(criteria);
assertNotNull(params);
assertTrue(params.iterator().hasNext());
assertNotNull(params.iterator().next().getSigningCredential());
@@ -223,7 +223,7 @@ public class RelyingPartyProxySigningParametersResolverTest extends AbstractOIDC
metadata.setRequestObjectJWSAlgs(List.of(JWSAlgorithm.RS256, JWSAlgorithm.ES256));
criteria.add(new ProviderMetadataCriterion(metadata));
- final Iterable<SignatureSigningParameters> params = resolver.resolve(criteria);
+ final Iterable<JWTSignatureSigningParameters> params = resolver.resolve(criteria);
assertNotNull(params);
assertTrue(params.iterator().hasNext());
assertNotNull(params.iterator().next().getSigningCredential());
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/TestCredentialHelper.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/TestCredentialHelper.java
index 2cf3a67..4306123 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/TestCredentialHelper.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/TestCredentialHelper.java
@@ -116,7 +116,7 @@ public final class TestCredentialHelper {
jwkCredential.setUsageType(UsageType.SIGNING);
jwkCredential.setKid(((JWK)key).getKeyID());
- jwkCredential.getKeyNames().add("mockKey");
+ jwkCredential.getKeyNames().add(((JWK)key).getKeyID());
jwkCredential.setAlgorithm(((JWK)key).getAlgorithm());
return jwkCredential;
}
@@ -138,7 +138,7 @@ public final class TestCredentialHelper {
jwkCredential.setUsageType(UsageType.ENCRYPTION);
jwkCredential.setKid(secret.getKeyID());
- jwkCredential.getKeyNames().add("mockKey");
+ jwkCredential.getKeyNames().add(secret.getKeyID());
jwkCredential.setAlgorithm(secret.getAlgorithm());
return jwkCredential;
}
@@ -159,7 +159,7 @@ public final class TestCredentialHelper {
jwkCredential.setUsageType(UsageType.ENCRYPTION);
jwkCredential.setKid(secret.getKeyID());
- jwkCredential.getKeyNames().add("mockKey");
+ jwkCredential.getKeyNames().add(secret.getKeyID());
jwkCredential.setAlgorithm(secret.getAlgorithm());
return jwkCredential;
}
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/impl/SignRequestObjectTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/impl/SignRequestObjectTest.java
index a19fc61..1fde602 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/impl/SignRequestObjectTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/impl/SignRequestObjectTest.java
@@ -24,7 +24,6 @@ import java.util.Date;
import javax.annotation.Nonnull;
-import org.opensaml.xmlsec.SignatureSigningParameters;
import org.testng.AssertJUnit;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@@ -45,6 +44,7 @@ import com.nimbusds.oauth2.sdk.id.ClientID;
import net.shibboleth.idp.plugin.authn.oidc.rp.impl.AbstractOIDCTest;
import net.shibboleth.idp.plugin.authn.oidc.rp.impl.TestCredentialHelper;
import net.shibboleth.oidc.profile.core.OIDCAuthenticationRequest;
+import net.shibboleth.oidc.security.JWTSignatureSigningParameters;
import net.shibboleth.oidc.security.context.JWTSecurityParametersContext;
/**
@@ -98,7 +98,7 @@ public class SignRequestObjectTest extends AbstractOIDCTest {
public void testSignHMAC_Success() throws Exception {
final JWTSecurityParametersContext secParamCtx = new JWTSecurityParametersContext();
- final var params = new SignatureSigningParameters();
+ final var params = new JWTSignatureSigningParameters();
params.setSigningCredential(TestCredentialHelper.createClientSecretCredential(CLIENT_SECRET));
params.setSignatureAlgorithm("HS256");
secParamCtx.setSignatureSigningParameters(params);
@@ -116,7 +116,7 @@ public class SignRequestObjectTest extends AbstractOIDCTest {
public void testSignHMAC_WrongCredentialType() throws Exception {
final JWTSecurityParametersContext secParamCtx = new JWTSecurityParametersContext();
- final var params = new SignatureSigningParameters();
+ final var params = new JWTSignatureSigningParameters();
params.setSigningCredential(TestCredentialHelper.createClientSecretCredential(CLIENT_SECRET));
params.setSignatureAlgorithm("RS256");
secParamCtx.setSignatureSigningParameters(params);
@@ -134,7 +134,7 @@ public class SignRequestObjectTest extends AbstractOIDCTest {
public void testSignRS256_Success() throws Exception {
final JWTSecurityParametersContext secParamCtx = new JWTSecurityParametersContext();
- final var params = new SignatureSigningParameters();
+ final var params = new JWTSignatureSigningParameters();
final RSAKey rsaKey = new RSAKeyGenerator(2048)
.keyID("1")
.keyUse(KeyUse.SIGNATURE)
@@ -156,7 +156,7 @@ public class SignRequestObjectTest extends AbstractOIDCTest {
public void testSignES256_Success() throws Exception {
final JWTSecurityParametersContext secParamCtx = new JWTSecurityParametersContext();
- final var params = new SignatureSigningParameters();
+ final var params = new JWTSignatureSigningParameters();
final ECKey ecKey = new ECKeyGenerator(Curve.P_256)
.keyID("1")
.keyUse(KeyUse.SIGNATURE)
diff --git a/idp-oidc-rp-impl/src/test/resources/conf/authn/rp-credentials.xml b/idp-oidc-rp-impl/src/test/resources/conf/authn/rp-credentials.xml
index e45060a..1d1ab5d 100644
--- a/idp-oidc-rp-impl/src/test/resources/conf/authn/rp-credentials.xml
+++ b/idp-oidc-rp-impl/src/test/resources/conf/authn/rp-credentials.xml
@@ -15,11 +15,16 @@
p:resource="%{idp.authn.oidc.rp.client.enc.key:#{null}}" />
</util:list>
- <util:list id="shibboleth.authn.oidc.rp.DefaultRequestObjectEncryptionCredentials">
+ <util:list id="shibboleth.authn.oidc.rp.DefaultRequestObjectKeyTransportEncryptionCredentials">
<bean parent="shibboleth.authn.oidc.rp.JWKCredential" p:failIfResourceIsNull="false"
p:resource="%{idp.authn.oidc.rp.client.requestobject.enc.key:#{null}}" />
</util:list>
+ <!-- <util:list id="shibboleth.authn.oidc.rp.DefaultRequestObjectDataEncryptionCredentials">
+ <bean parent="shibboleth.authn.oidc.rp.JWKCredential" p:failIfResourceIsNull="false"
+ p:resource="%{idp.authn.oidc.rp.client.requestobject.enc.key:#{null}}" />
+ </util:list> -->
+
<!-- Default signing credentials -->
<util:list id="shibboleth.authn.oidc.rp.DefaultSigningCredentials">
<bean parent="shibboleth.authn.oidc.rp.JWKCredential" p:failIfResourceIsNull="false"
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list