[java-idp-plugin-oidc-rp] branch main updated: Cleanup request object encryption support. Add tests
Phil Smart
philip.smart at jisc.ac.uk
Fri Jul 22 13:58:28 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=d03e77f129f455fb8b92c42dfd7daeb6ad43db02
The following commit(s) were added to refs/heads/main by this push:
new d03e77f Cleanup request object encryption support. Add tests
d03e77f is described below
commit d03e77f129f455fb8b92c42dfd7daeb6ad43db02
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Fri Jul 22 14:58:22 2022 +0100
Cleanup request object encryption support. Add tests
---
...questObjectEncryptionMethodsLookupFunction.java | 44 ++++
...ObjectKeyTransportAlgorithmsLookupFunction.java | 44 ++++
.../authn/oidc/rp/impl/BuildRequestObject.java | 2 +-
.../rp/impl/PopulateJWTEncryptionParameters.java | 2 +-
...oviderMetadataEncryptionParametersResolver.java | 177 +++++++++++++---
.../authn/oidc/rp/messaging/impl/EncryptJWT.java | 2 -
.../oidc-relying-party-authn-beans.xml | 11 +-
.../plugin/authn/oidc/rp/impl/OIDCRPFlowTest.java | 14 +-
...erMetadataEncryptionParametersResolverTest.java | 233 +++++++++++++++++++++
.../plugin/authn/oidc/rp/impl/TestJsonHelper.java | 55 +++++
.../flow/AbstractAuthnXmlFlowExecutionTests.java | 21 +-
...st-provider-resolver-remote-jwkset-response.jwk | 66 ++++++
.../src/test/resources/logback-test.xml | 3 +-
.../test-resolver-provider-encryption.json | 89 ++++++++
14 files changed, 698 insertions(+), 65 deletions(-)
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/ProviderRequestObjectEncryptionMethodsLookupFunction.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/ProviderRequestObjectEncryptionMethodsLookupFunction.java
new file mode 100644
index 0000000..a784db9
--- /dev/null
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/ProviderRequestObjectEncryptionMethodsLookupFunction.java
@@ -0,0 +1,44 @@
+/*
+ * 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.Collections;
+import java.util.List;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import com.nimbusds.jose.EncryptionMethod;
+import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
+
+/** Lookup the request_object_encryption_alg_values_supported from the provider metadata.*/
+public class ProviderRequestObjectEncryptionMethodsLookupFunction
+ implements Function<OIDCProviderMetadata, List<EncryptionMethod>> {
+
+ @Override
+ @Nonnull public List<EncryptionMethod> apply(@Nullable final OIDCProviderMetadata metadata) {
+ if (metadata == null) {
+ return Collections.emptyList();
+ }
+ return metadata.getRequestObjectJWEEncs() != null
+ ? metadata.getRequestObjectJWEEncs() : Collections.emptyList();
+
+ }
+
+}
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/ProviderRequestObjectKeyTransportAlgorithmsLookupFunction.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/ProviderRequestObjectKeyTransportAlgorithmsLookupFunction.java
new file mode 100644
index 0000000..426c2a7
--- /dev/null
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/ProviderRequestObjectKeyTransportAlgorithmsLookupFunction.java
@@ -0,0 +1,44 @@
+/*
+ * 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.Collections;
+import java.util.List;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import com.nimbusds.jose.JWEAlgorithm;
+import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
+
+/** Lookup the request_object_encryption_enc_values_supported from the provider metadata.*/
+public class ProviderRequestObjectKeyTransportAlgorithmsLookupFunction
+ implements Function<OIDCProviderMetadata, List<JWEAlgorithm>> {
+
+ @Override
+ @Nonnull public List<JWEAlgorithm> apply(@Nullable final OIDCProviderMetadata metadata) {
+ if (metadata == null) {
+ return Collections.emptyList();
+ }
+ return metadata.getRequestObjectJWEAlgs() != null
+ ? metadata.getRequestObjectJWEAlgs() : Collections.emptyList();
+
+ }
+
+}
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/BuildRequestObject.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/BuildRequestObject.java
index bb77907..45cf1b7 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/BuildRequestObject.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/BuildRequestObject.java
@@ -154,7 +154,7 @@ public class BuildRequestObject extends AbstractOIDCAuthenticationRequestAction
requestObjectClaims.toJSONString());
}
- // Create a plain JWT at first, can be signed and encrypted later
+ // Create the claim first, can be signed and encrypted as a JWT later
authnRequest.setRequestObjectClaimsSet(requestObjectClaims);
}
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 1c78a66..fc8bef0 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
@@ -302,7 +302,7 @@ public class PopulateJWTEncryptionParameters extends AbstractProfileAction {
log.debug("{} OIDCProviderMetadataContext is absent", getLogPrefix());
}
- // Add any static credentials from the RP context
+ // Add any static credentials from the RP context. If any resolver supports it
final RelyingPartyContext rpCtx =
relyingPartyContextLookupStrategy.apply(profileRequestContext);
if (rpCtx != null && rpCtx.getConfiguration() != null &&
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 ddce8f0..0e117fd 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
@@ -1,9 +1,28 @@
+/*
+ * 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.impl;
+import java.security.NoSuchAlgorithmException;
import java.time.Duration;
import java.time.Instant;
import java.util.Collections;
import java.util.List;
+import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -32,16 +51,29 @@ import net.shibboleth.oidc.jwk.RemoteJwkSetCache;
import net.shibboleth.oidc.security.credential.BasicJWKCredential;
import net.shibboleth.oidc.security.criterion.ProviderMetadataCriterion;
import net.shibboleth.oidc.security.criterion.StaticCredentialCriterion;
+import net.shibboleth.oidc.security.impl.OIDCDecryptionParameters;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
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.logic.PredicateSupport;
import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
-//TODO so far, this is only pulling out request object algs. Use a strategy to make it generic
+/**
+ *
+ * <p>Does not support Direct Encryption.</p>
+ */
public class ProviderMetadataEncryptionParametersResolver extends BasicEncryptionParametersResolver {
/** Logger. */
private final Logger log = LoggerFactory.getLogger(ProviderMetadataEncryptionParametersResolver.class);
+ /** A strategy to locate the encryption methods ('enc') appropriate for the JWT to be encrypted.*/
+ @Nonnull private Function<OIDCProviderMetadata, List<EncryptionMethod>> providerEncryptionMethodsLookupStrategy;
+
+ /** A strategy to locate the algorithms ('alg') appropriate for the JWT to be encrypted.*/
+ @Nonnull private Function<OIDCProviderMetadata, List<JWEAlgorithm>> providerKeyTransportAlgorithmsLookupStrategy;
+
/** The cache for remote JWK key sets. */
@Nullable private RemoteJwkSetCache remoteJwkSetCache;
@@ -52,8 +84,35 @@ public class ProviderMetadataEncryptionParametersResolver extends BasicEncryptio
/** Constructor.*/
public ProviderMetadataEncryptionParametersResolver() {
super();
+ providerEncryptionMethodsLookupStrategy = FunctionSupport.constant(Collections.emptyList());
+ providerKeyTransportAlgorithmsLookupStrategy = FunctionSupport.constant(Collections.emptyList());
}
+ /**
+ * Set the strategy used to locate the algorothms ('alg') from the OpenID Provider metadata
+ * appropriate for the JWT to be encrypted.
+ *
+ * @param strategy the strategy
+ */
+ public void setProviderKeyTransportAlgorithmsLookupStrategy(
+ @Nonnull final Function<OIDCProviderMetadata, List<JWEAlgorithm>> strategy) {
+
+ providerKeyTransportAlgorithmsLookupStrategy = Constraint.isNotNull(strategy,
+ "ProviderAlgorithmsLookupStrategy can not be null");
+ }
+
+ /**
+ * Set the strategy used to locate the encryption methods ('enc') from the OpenID Provider metadata
+ * appropriate for the JWT to be encrypted.
+ *
+ * @param strategy the strategy
+ */
+ public void setProviderEncryptionMethodsLookupStrategy(
+ @Nonnull final Function<OIDCProviderMetadata, List<EncryptionMethod>> strategy) {
+
+ providerEncryptionMethodsLookupStrategy = Constraint.isNotNull(strategy,
+ "ProviderEncryptionMethodsLookupStrategy can not be null");
+ }
/**
* Set the cache for remote JWK key sets.
@@ -91,19 +150,17 @@ public class ProviderMetadataEncryptionParametersResolver extends BasicEncryptio
final OIDCProviderMetadata metadata = criteria.get(ProviderMetadataCriterion.class).getMetadata();
// We populate the parameters for the algorithm the provider has registered
- final List<JWEAlgorithm> keyTransportAlgorithms = metadata.getRequestObjectJWEAlgs() !=null
- ? metadata.getRequestObjectJWEAlgs(): Collections.emptyList();
+ final List<JWEAlgorithm> keyTransportAlgorithms =
+ 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");
super.resolveAndPopulateCredentialsAndAlgorithms(params, criteria, includeExcludePredicate);
return;
- }
-
- //TODO use strategy to pull these out
- final List<EncryptionMethod> dataEncryptionMethods = metadata.getRequestObjectJWEEncs() != null ?
- metadata.getRequestObjectJWEEncs() : Collections.emptyList();
+ }
+ final List<EncryptionMethod> dataEncryptionMethods =
+ providerEncryptionMethodsLookupStrategy.apply(metadata);
log.trace("Resolved effective data encryption algorithms from provider metadata: {}", dataEncryptionMethods);
final List<String> keyTransportAlgorithmSupported =
@@ -129,36 +186,67 @@ public class ProviderMetadataEncryptionParametersResolver extends BasicEncryptio
log.debug("Supported and configured data encryption algorithms: {}",
supportedAndConfiguredDataEncryptionAlgorithms);
+ if (supportedAndConfiguredKeyTransportAlgorithms.isEmpty()) {
+ log.warn("No supported key transport algorithm");
+ super.resolveAndPopulateCredentialsAndAlgorithms(params, criteria, includeExcludePredicate);
+ return;
+ }
+ if (supportedAndConfiguredDataEncryptionAlgorithms.isEmpty()) {
+ log.warn("No supported data encryption method");
+ super.resolveAndPopulateCredentialsAndAlgorithms(params, criteria, includeExcludePredicate);
+ 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;
+ }
+
+ //Check if all supported and configured 'alg's are key wrapping algorithms. If so, use
+ //Key wrapping, otherwise chose a key encryption/agreement algorithm.
+ if (allKeyWrappingAlgorithms(supportedJWEKeyTransportAlgorithms)) {
+ //Do key wrapping
+ log.debug("All configured and supported algorithms are for the key wrapping mode, generating"
+ + " key wrapping credential");
+ // Choose the first algorithm
+ final JWEAlgorithm algorithm = supportedJWEKeyTransportAlgorithms.get(0);
+ // Pull out the shared secret from the config?
+ //TODO check this logic
+ if (criteria.contains(StaticCredentialCriterion.class)) {
+ final Credential sharedSecret = criteria.get(StaticCredentialCriterion.class).getCredential();
+ //Do more here.
+ params.setKeyTransportEncryptionCredential(sharedSecret);
+ params.setKeyTransportEncryptionAlgorithm(algorithm.getName());
+ params.setDataEncryptionAlgorithm(encryptionMethod.getName());
+ return;
+ } else {
+ log.warn("No shared secret criterion found, can not generate key wrapping credential");
+ super.resolveAndPopulateCredentialsAndAlgorithms(params, criteria, includeExcludePredicate);
+ return;
+ }
+
+ }
+ // Find and process key encryption or key agreement modes
JWKSet providerKeySet = getProviderKeys(metadata);
if (providerKeySet == null) {
providerKeySet = new JWKSet();
}
log.trace("Has '{}' keys from provider's JWKSet", providerKeySet.getKeys().size());
-
- // Add any static credentials from the criteria. Add as a data encryption credential e.g for Direct Encryption.
- //TODO we need to consider this for the 'dir' alg.
- if (criteria.contains(StaticCredentialCriterion.class)) {
- final Credential staticCred = criteria.get(StaticCredentialCriterion.class).getCredential();
- log.trace("Signing credential found in criterion '{}'", staticCred.getKeyNames());
- if (staticCred.getSecretKey() != null) {
- //dataEncryptionCredentials.add(staticCred);
- }
- }
-
- final List<JWEAlgorithm> supportedJWEKeyTransportAlgorithms =
- convertSupportAlgorithmsToJwkAlgorithms(supportedAndConfiguredKeyTransportAlgorithms);
-
- // Default encEnc value
- // TODO we need to 'chose' this.
- final EncryptionMethod encryptionMethod = EncryptionMethod.A128CBC_HS256;
- // Keys in the remote keys file are keytransport algorithms?
+ // Keys in the remote keys file are key encryption and agreement algorithms?
for (final JWK key : providerKeySet.getKeys()) {
if (KeyUse.SIGNATURE.equals(key.getKeyUse())) {
continue;
}
- final JWEAlgorithm keyTransportAlgorithm = findSupportedAlgorithm(key, supportedJWEKeyTransportAlgorithms);
+ final JWEAlgorithm keyTransportAlgorithm =
+ findSupportedKeyTransportAlgorithm(key, supportedJWEKeyTransportAlgorithms);
if (keyTransportAlgorithm != null) {
final BasicJWKCredential jwkCredential = new BasicJWKCredential();
jwkCredential.setAlgorithm(keyTransportAlgorithm);
@@ -186,6 +274,32 @@ public class ProviderMetadataEncryptionParametersResolver extends BasicEncryptio
}
+ /**
+ * If all the supported algorithms are symmetric key wrapping algorithms, return true. Return false otherwise.
+ *
+ * @param algorithms the alogorithms to check
+ *
+ * @return true if all algorithms are symmetric key wrapping algorithms, false otherwise.
+ */
+ private boolean allKeyWrappingAlgorithms(@Nonnull @NotEmpty final List<JWEAlgorithm> algorithms) {
+ return algorithms.stream().allMatch(
+ PredicateSupport.or(JWEAlgorithm.Family.AES_GCM_KW::contains, JWEAlgorithm.Family.AES_KW::contains));
+ }
+
+ /**
+ * 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.
*
@@ -193,20 +307,21 @@ public class ProviderMetadataEncryptionParametersResolver extends BasicEncryptio
*
* @return the converted algorithms
*/
- @Nonnull private List<JWEAlgorithm> convertSupportAlgorithmsToJwkAlgorithms(@Nonnull final List<String> algos) {
+ @Nonnull private List<JWEAlgorithm> convertStringAlgorithmURIsToJwkAlgorithms(@Nonnull final List<String> algos) {
return algos.stream().map(JWEAlgorithm::parse).collect(Collectors.toList());
}
/**
- * Does the key support any one of the given algorithms.
+ * Does the key support any one of the given algorithms. The key has to be either an RSA, or EC type.
*
* @param key the key to check
* @param algorithms the algorithms to check against
*
* @return the supported algorithm, or null if none are supported
*/
- @Nullable private JWEAlgorithm findSupportedAlgorithm(@Nonnull final JWK key,
- @Nonnull final List<JWEAlgorithm> algorithms) {
+ @Nullable private JWEAlgorithm findSupportedKeyTransportAlgorithm(@Nonnull final JWK key,
+ @Nonnull final List<JWEAlgorithm> algorithms) {
+
final JWEAlgorithm algorithm =
algorithms.stream().filter(alg -> alg.equals(key.getAlgorithm())).findFirst().orElse(null);
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 e27fd36..60616a4 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
@@ -29,11 +29,9 @@ import javax.annotation.Nullable;
import org.opensaml.messaging.context.MessageContext;
import org.opensaml.messaging.context.navigate.ChildContextLookup;
-import org.opensaml.messaging.context.navigate.RecursiveTypedParentContextLookup;
import org.opensaml.messaging.handler.AbstractMessageHandler;
import org.opensaml.messaging.handler.MessageHandler;
import org.opensaml.messaging.handler.MessageHandlerException;
-import org.opensaml.profile.context.ProfileRequestContext;
import org.opensaml.security.credential.Credential;
import org.opensaml.xmlsec.EncryptionParameters;
import org.opensaml.xmlsec.context.SecurityParametersContext;
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 e82f0e6..29e010f 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
@@ -217,8 +217,15 @@
<bean id="shibboleth.authn.oidc.rp.EncryptionParametersResolver"
class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.ProviderMetadataEncryptionParametersResolver"
- p:remoteJwkSetCache-ref="shibboleth.authn.oidc.rp.RemoteJwkSetCache"/>
-
+ p:remoteJwkSetCache-ref="shibboleth.authn.oidc.rp.RemoteJwkSetCache">
+ <property name="providerEncryptionMethodsLookupStrategy">
+ <bean class="net.shibboleth.idp.plugin.authn.oidc.rp.config.navigate.ProviderRequestObjectEncryptionMethodsLookupFunction"/>
+ </property>
+ <property name="providerKeyTransportAlgorithmsLookupStrategy">
+ <bean class="net.shibboleth.idp.plugin.authn.oidc.rp.config.navigate.ProviderRequestObjectKeyTransportAlgorithmsLookupFunction"/>
+ </property>
+ </bean>
+
<bean id="BuildRequestObject" class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.BuildRequestObject"
scope="prototype" p:profileContextLookupStrategy-ref="shibboleth.ChildLookup.ProxyProfileRequestContext"
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 f7e75b3..e0d794f 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
@@ -362,7 +362,7 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
private OIDCPeerEntityContext createPeerContext() throws ParseException {
final OIDCPeerEntityContext peerCtx = new OIDCPeerEntityContext();
final OIDCProviderMetadata providerMetadata =
- OIDCProviderMetadata.parse(readJsonFromFile(GOOD_PROVIDER_CONFIGURATION_INFO));
+ OIDCProviderMetadata.parse(TestJsonHelper.readJsonFromFile(GOOD_PROVIDER_CONFIGURATION_INFO));
final OIDCProviderMetadataContext providerMetadataCtx = new OIDCProviderMetadataContext();
providerMetadataCtx.setProviderInformation(providerMetadata);
peerCtx.addSubcontext(providerMetadataCtx);
@@ -430,7 +430,7 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
// First is metadata exchange
mockOPServer.enqueue(new MockResponse().setResponseCode(200)
.setHeader("content-type", "application/json")
- .setBody(readJsonFromFile(GOOD_PROVIDER_CONFIGURATION_INFO)));
+ .setBody(TestJsonHelper.readJsonFromFile(GOOD_PROVIDER_CONFIGURATION_INFO)));
mockOPServer.start(9918);
@@ -468,7 +468,7 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
// First is metadata exchange
mockOPServer.enqueue(new MockResponse().setResponseCode(200)
.setHeader("content-type", "application/json")
- .setBody(readJsonFromFile(GOOD_PROVIDER_CONFIGURATION_INFO_USE_REQUEST_OBJECT)));
+ .setBody(TestJsonHelper.readJsonFromFile(GOOD_PROVIDER_CONFIGURATION_INFO_USE_REQUEST_OBJECT)));
mockOPServer.start(9919);
@@ -507,12 +507,12 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
// First is metadata exchange
mockOPServer.enqueue(new MockResponse().setResponseCode(200)
.setHeader("content-type", "application/json")
- .setBody(readJsonFromFile(GOOD_PROVIDER_CONFIGURATION_INFO_USE_REQUEST_OBJECT_ENCRYPT)));
+ .setBody(TestJsonHelper.readJsonFromFile(GOOD_PROVIDER_CONFIGURATION_INFO_USE_REQUEST_OBJECT_ENCRYPT)));
// Second is JWKSet lookup
mockOPServer.enqueue(new MockResponse().setResponseCode(200)
.setHeader("content-type", "application/json")
- .setBody(readJsonFromFile(REMOTE_JWKSET_RESPONSE)));
+ .setBody(TestJsonHelper.readJsonFromFile(REMOTE_JWKSET_RESPONSE)));
mockOPServer.start(9921);
@@ -550,7 +550,7 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
// First is metadata exchange
mockOPServer.enqueue(new MockResponse().setResponseCode(200)
.setHeader("content-type", "application/json")
- .setBody(readJsonFromFile(GOOD_PROVIDER_CONFIGURATION_INFO_USE_REQUEST_OBJECT_RSA256_SIG)));
+ .setBody(TestJsonHelper.readJsonFromFile(GOOD_PROVIDER_CONFIGURATION_INFO_USE_REQUEST_OBJECT_RSA256_SIG)));
mockOPServer.start(9920);
@@ -583,7 +583,7 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
// First is metadata exchange
mockOPServer.enqueue(new MockResponse().setResponseCode(200)
.setHeader("content-type", "application/json")
- .setBody(readJsonFromFile(GOOD_PROVIDER_CONFIGURATION_INFO)));
+ .setBody(TestJsonHelper.readJsonFromFile(GOOD_PROVIDER_CONFIGURATION_INFO)));
mockOPServer.start(9918);
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
new file mode 100644
index 0000000..21a653f
--- /dev/null
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ProviderMetadataEncryptionParametersResolverTest.java
@@ -0,0 +1,233 @@
+/*
+ * 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.impl;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.protocol.HttpContext;
+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.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.criterion.ProviderMetadataCriterion;
+import net.shibboleth.oidc.security.criterion.StaticCredentialCriterion;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+
+/** Tests for the {@link ProviderMetadataEncryptionParametersResolver}.*/
+public class ProviderMetadataEncryptionParametersResolverTest {
+
+ /**
+ * Example of good provider metadata that supports request_object_encryption.
+ */
+ private static final ClassPathResource GOOD_PROVIDER_CONFIGURATION_INFO =
+ new ClassPathResource("/metadata/test-resolver-provider-encryption.json");
+
+ /** A remote JWKSet.*/
+ private static final ClassPathResource REMOTE_JWKSET =
+ new ClassPathResource("/conf/credentials/test-provider-resolver-remote-jwkset-response.jwk");
+
+ /** The client_secret.*/
+ private static final String CLIENT_SECRET = "Xp2s5v8y/B?E(H+MbQeThWmYq3t6w9z$";
+
+ /** The resolver to test.*/
+ private ProviderMetadataEncryptionParametersResolver resolver;
+
+ /** The basic config.*/
+ private BasicEncryptionConfiguration config;
+
+
+ @BeforeMethod
+ public void setup() throws ComponentInitializationException, ClientProtocolException, IOException {
+ resolver = new ProviderMetadataEncryptionParametersResolver();
+ resolver.setProviderEncryptionMethodsLookupStrategy(OIDCProviderMetadata::getRequestObjectJWEEncs);
+ resolver.setProviderKeyTransportAlgorithmsLookupStrategy(OIDCProviderMetadata::getRequestObjectJWEAlgs);
+ final RemoteJwkSetCache cache = new RemoteJwkSetCache();
+ cache.setStorage(buildStorageService());
+ cache.setHttpClient(createMockHttpClient(TestJsonHelper.readJsonFromFile(REMOTE_JWKSET)));
+ resolver.setRemoteJwkSetCache(cache);
+ }
+
+ protected HttpClient createMockHttpClient(final String output) throws ClientProtocolException, IOException {
+ final HttpClient httpClient = Mockito.mock(HttpClient.class);
+ final HttpResponse httpResponse = Mockito.mock(HttpResponse.class);
+ Mockito.when(httpResponse.getEntity()).thenReturn(new StringEntity(output));
+ Mockito.when(httpClient.execute((HttpUriRequest) Mockito.any(),
+ (HttpContext) Mockito.any())).thenReturn(httpResponse);
+ return httpClient;
+ }
+
+ private StorageService buildStorageService() throws ComponentInitializationException {
+ final MemoryStorageService storageService = new MemoryStorageService();
+ storageService.setId("mockId");
+ storageService.initialize();
+ 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();
+ }
+
+ config = new BasicEncryptionConfiguration();
+ 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)));
+ criteria.add(new ProviderMetadataCriterion(
+ OIDCProviderMetadata.parse(TestJsonHelper.readJsonFromFile(GOOD_PROVIDER_CONFIGURATION_INFO))));
+ criteria.add(
+ new StaticCredentialCriterion(TestCredentialHelper.createClientSecretCredential(CLIENT_SECRET)));
+ return criteria;
+ }
+
+ @Test
+ public void testSuccessfulResolution() throws Exception {
+ final Iterable<EncryptionParameters> params = resolver.resolve(buildBasicCriteriaSet());
+ assertNotNull(params);
+ assertTrue(params.iterator().hasNext());
+ final EncryptionParameters param = params.iterator().next();
+ assertNotNull(param.getDataEncryptionAlgorithm());
+ assertNotNull(param.getKeyTransportEncryptionAlgorithm());
+ assertNotNull(param.getKeyTransportEncryptionCredential());
+ assertNotNull(param.getKeyTransportEncryptionCredential().getPublicKey());
+ }
+
+ /* Algorithms are know because they are limited by config.*/
+ @Test
+ public void testSuccessfulResolution_WithKnownAlgorithms() throws Exception {
+ final CriteriaSet criteria = buildBasicCriteriaSet();
+ 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);
+ assertNotNull(params);
+ assertTrue(params.iterator().hasNext());
+ final EncryptionParameters param = params.iterator().next();
+ assertNotNull(param.getDataEncryptionAlgorithm());
+ assertNotNull(param.getKeyTransportEncryptionAlgorithm());
+ assertEquals(param.getDataEncryptionAlgorithm(),EncryptionConstants.ALGO_ID_ENC_ALG_A256CBC_HS512);
+ assertEquals(param.getKeyTransportEncryptionAlgorithm(),KeyManagementConstants.ALGO_ID_ALG_RSA_OAEP);
+ assertNotNull(param.getKeyTransportEncryptionCredential());
+ assertNotNull(param.getKeyTransportEncryptionCredential().getPublicKey());
+ }
+
+ @Test
+ public void testSuccessfulResolution_ForKeyWrap() throws Exception {
+ final CriteriaSet criteria = buildBasicCriteriaSet();
+ 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);
+ assertNotNull(params);
+ assertTrue(params.iterator().hasNext());
+ final EncryptionParameters 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_AES_256_KW);
+ assertNotNull(param.getKeyTransportEncryptionCredential());
+ assertNotNull(param.getKeyTransportEncryptionCredential().getSecretKey());
+ }
+
+ /*
+ * Can not test ECDH-ES as the net.shibboleth.oidc.jwa.algorithm.descriptors.KeyAgreementECDHES is not
+ * supported by the runtime!
+ */
+ @Test(enabled = false)
+ public void testSuccessfulResolution_ForKeyAgreement() throws Exception {
+ final CriteriaSet criteria = buildBasicCriteriaSet();
+ 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);
+ assertNotNull(params);
+ assertTrue(params.iterator().hasNext());
+ final EncryptionParameters 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_ECDH_ES);
+ assertNotNull(param.getDataEncryptionCredential());
+ assertNotNull(param.getDataEncryptionCredential().getPublicKey());
+ }
+
+ @Test
+ public void testUnSuccessfulResolution_NoSupportedKeyTransportAlgorithm() throws Exception {
+ final CriteriaSet criteria = buildBasicCriteriaSet();
+ config.setKeyTransportEncryptionAlgorithms(List.of("NOT-SUPPORTED"));
+
+ final Iterable<EncryptionParameters> params = resolver.resolve(criteria);
+ assertNotNull(params);
+ assertFalse(params.iterator().hasNext());
+ }
+
+ @Test
+ public void testUnSuccessfulResolution_OnlyConfigCriterion() throws Exception {
+ buildBasicCriteriaSet();
+ final CriteriaSet criteria = new CriteriaSet(new EncryptionConfigurationCriterion(List.of(config)));
+
+ final Iterable<EncryptionParameters> params = resolver.resolve(criteria);
+ assertNotNull(params);
+ assertFalse(params.iterator().hasNext());
+ }
+
+ @Test
+ public void testUnSuccessfulResolution_NoSupportedDataEncryptionMethod() throws Exception {
+ final CriteriaSet criteria = buildBasicCriteriaSet();
+ config.setDataEncryptionAlgorithms(List.of("NOT-SUPPORTED"));
+
+ final Iterable<EncryptionParameters> 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/TestJsonHelper.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/TestJsonHelper.java
new file mode 100644
index 0000000..157250a
--- /dev/null
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/TestJsonHelper.java
@@ -0,0 +1,55 @@
+/*
+ * 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.impl;
+
+import static org.testng.Assert.fail;
+
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.StandardCharsets;
+
+import javax.annotation.Nonnull;
+
+import org.springframework.core.io.Resource;
+import org.springframework.util.FileCopyUtils;
+
+/** Helper methods for dealing with JSON.*/
+public final class TestJsonHelper {
+
+ private TestJsonHelper() {
+
+ }
+
+ /**
+ * Read a file into a string.
+ *
+ * @param location the location of the file to read
+ *
+ * @return the file as a string
+ */
+ public static String readJsonFromFile(@Nonnull final Resource location) {
+ try (Reader reader = new InputStreamReader(location.getInputStream(), StandardCharsets.UTF_8)) {
+ return FileCopyUtils.copyToString(reader);
+ } catch (final Exception ex) {
+ fail();
+ return null;
+ }
+ }
+
+}
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/test/flow/AbstractAuthnXmlFlowExecutionTests.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/test/flow/AbstractAuthnXmlFlowExecutionTests.java
index 75cbf1b..f894e65 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/test/flow/AbstractAuthnXmlFlowExecutionTests.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/test/flow/AbstractAuthnXmlFlowExecutionTests.java
@@ -17,9 +17,6 @@
package net.shibboleth.idp.plugin.authn.test.flow;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Base64;
import java.util.Collections;
@@ -55,7 +52,6 @@ import org.springframework.mock.env.MockPropertySource;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.ContextConfiguration;
-import org.springframework.util.FileCopyUtils;
import org.springframework.webflow.config.FlowDefinitionResource;
import org.springframework.webflow.config.FlowDefinitionResourceFactory;
import org.springframework.webflow.engine.Flow;
@@ -588,22 +584,7 @@ public abstract class AbstractAuthnXmlFlowExecutionTests extends CustomAbstractX
return prc;
}
- /**
- * Read a file into a string.
- *
- * @param location the location of the file to read
- *
- * @return the file as a string
- */
- protected String readJsonFromFile(@Nonnull final Resource location) {
- try (Reader reader = new InputStreamReader(location.getInputStream(), StandardCharsets.UTF_8)) {
- return FileCopyUtils.copyToString(reader);
- } catch (final Exception ex) {
- log.error("Error reading file",ex);
- fail();
- return null;
- }
- }
+
diff --git a/idp-oidc-rp-impl/src/test/resources/conf/credentials/test-provider-resolver-remote-jwkset-response.jwk b/idp-oidc-rp-impl/src/test/resources/conf/credentials/test-provider-resolver-remote-jwkset-response.jwk
new file mode 100644
index 0000000..5473bee
--- /dev/null
+++ b/idp-oidc-rp-impl/src/test/resources/conf/credentials/test-provider-resolver-remote-jwkset-response.jwk
@@ -0,0 +1,66 @@
+{
+"keys": [
+{
+"kty": "RSA",
+"e": "AQAB",
+"use": "sig",
+"kid": "7da9fea4-7a38-4398-aaef-8226b26776a2",
+"n": "kk-3jeBmUPbpMk0fEdIn-APAdNOoOckA0e-SiALLxy5dWfG-GyF51g31zuM_iNiSiMSsmG2ZAVi48iItFpd-JW9IIT40TC147I6aKrel0Rf39Mwp-1tCzME6VYEgOmgI9qDg2e4edt1cvjQfiw3IZlXakwgYQn2BuoknoCBVjETVLHrnsvEqXhPffzML9O5Ze_nBOX6-pCAzVsimr-ljoln2GQz-ID5fGzlflXJV78v7QzlyyAAQovYQMxiEBgecHu44S0Iu_esLEOOobQkZyHc-OgcwEazfJUEUhKEnevVTJFlQF3Odxp1I6W9zd-zLUceqIMKF5Xs10AfmkPhboQ"
+},
+{
+"kty": "RSA",
+"e": "AQAB",
+"use": "sig",
+"kid": "9ae4e77c-a0c7-4c52-982f-b8e5e6b62ab8",
+"n": "lBh4Ujl1k_H9CAfJe-SD-ngZnllWh5lShhv2FF_OlSlDEwr5wbf4WimeQhqLtfeT-dJXALpLSncaG_5y8pHHh0Pflnx_pZfCoOOc4Fba7wZgpHzfSQePwIDH8ygmzMLNzLaECa5m1LxnDD0oVHsABOab-_6_Uvuvam5xo2pKfJHoxkVsEDxQ2R0T_GfqC2bmCNJCdadeqw43yF_ILBRX-9sosA_7GPwyBWKAyiHX-DTUKwWrpR2bwCGE2Bxfgj3cDa97prSX8Vwpj_DEPOH8hbMAjO-N4EBcvcJZ0O0CD3X3IrquC__wqc9aOMEh2xbRxnTHdrNNG1KqzS8-L2yS0w"
+},
+{
+"kty": "EC",
+"use": "sig",
+"crv": "P-256",
+"kid": "7b1a7c28-df25-4d54-b111-11903db56d52",
+"x": "XRlwH72XaSlYjybpA6q4DTHsOphTuSWNPULNKwQ38wo",
+"y": "xWIoYZAyQxZM7RJCL-k14PdIHkCPo4m2tKRiCWyXU9w"
+},
+{
+"kty": "EC",
+"use": "sig",
+"crv": "P-256",
+"kid": "00cfe876-ed35-4052-8045-be1088c3212f",
+"x": "SwSHs_Df-Qxl83Mibu_lWzxn0mBn9hGts9gougQlrqs",
+"y": "kKQfhy4jDV_cxpC3iptQTFODkgENp-HC4XK7NIDqt5s"
+},
+{
+"kty": "EC",
+"use": "sig",
+"crv": "secp256k1",
+"kid": "4d1d9b37-3acc-46b9-9426-ee209db8541f",
+"x": "cZb41D8qgFxbpxnqOcp-kc78M8EdtSYqotje0IhWk_o",
+"y": "viJ95PgOZdYFPHRqdO4NOhRQgkejVDv8RmDprbLE31g"
+},
+{
+"kty": "OKP",
+"use": "sig",
+"crv": "Ed25519",
+"kid": "0c54869d-7d20-4faf-b607-3b040d1e1f27",
+"x": "gi3CalT0xmz8V52rgfdvYyM-rUwKnf8gUUUqB87Gycw"
+},
+{
+"kty": "RSA",
+"e": "AQAB",
+"use": "enc",
+"kid": "87ff206d-15f9-4b8c-ba88-a8c17014da13",
+"alg": "RSA-OAEP",
+"n": "uAVnVD3cMEbrAsDg1c3n6GfzR3sSg9C9pbjTw39_jgWk5YQCHPPOt4zYyZZL2JCnm9TFjnndCCW5ZPWHPJjumiNB2r-vC0CmI-T66JSRX3YYw0h2Odiusr_74FNe_mYyEuClFa4hwo-RMgrp8L1sbrAWcgGOc84rD6-fZXVrWFMkOb0jg6tqF1EwBSxZFG1cfvUmatNuBXs6njPHvvqhd7Bz6adK4YkpzCUbD-jSjpvAvU-Q4TZT_bXq4WRFOPqXv2NX4ch7ErjEm5tJEk7BIqOh7Byg0pWB4WAwsMcZKnHlp7JjtB2T1s_45_iqD2xipxpF-NxoHUlz67qHt7-W4Q"
+},
+{
+"kty": "EC",
+"use": "enc",
+"crv": "P-256",
+"kid": "c689ce91-8d82-45f2-b671-38ee38e7599f",
+"x": "redOUw802EuKJRoS8kQx6_RjuCypx0dcMBhv4IAALvQ",
+"y": "oaypduaS_wPLGCDQfJ0SKtQu0urJzhr4ZRn5wYMhiyk",
+"alg": "ECDH-ES"
+}
+]
+}
\ No newline at end of file
diff --git a/idp-oidc-rp-impl/src/test/resources/logback-test.xml b/idp-oidc-rp-impl/src/test/resources/logback-test.xml
index cabbb3c..2e54ae8 100644
--- a/idp-oidc-rp-impl/src/test/resources/logback-test.xml
+++ b/idp-oidc-rp-impl/src/test/resources/logback-test.xml
@@ -5,7 +5,8 @@
<logger name="org.opensaml.xmlsec.impl" level="DEBUG"/>
<logger name="net.shibboleth.idp.plugin.authn" level="TRACE"/>
<logger name="org.springframework" level="INFO"/>
-
+ <logger name="org.opensaml.xmlsec.config.GlobalAlgorithmRegistryInitializer" level="DEBUG"/>
+ <logger name="org.opensaml.xmlsec.algorithm" level="DEBUG"/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%level [%logger:%line] - %msg%n</pattern>
diff --git a/idp-oidc-rp-impl/src/test/resources/metadata/test-resolver-provider-encryption.json b/idp-oidc-rp-impl/src/test/resources/metadata/test-resolver-provider-encryption.json
new file mode 100644
index 0000000..02633d9
--- /dev/null
+++ b/idp-oidc-rp-impl/src/test/resources/metadata/test-resolver-provider-encryption.json
@@ -0,0 +1,89 @@
+{
+ "issuer":"https://localhost:9921",
+ "authorization_endpoint":"https://localhost:9921/o/oauth2/v2/auth",
+ "device_authorization_endpoint":"https://localhost:9921/device/code",
+ "token_endpoint":"https://localhost:9921/token",
+ "userinfo_endpoint":"https://localhost:9921/v1/userinfo",
+ "revocation_endpoint":"https://localhost:9921/revoke",
+ "jwks_uri":"https://localhost:9921/oauth2/v3/certs",
+ "claims_parameter_supported":true,
+ "request_parameter_supported":true,
+ "response_types_supported":[
+ "code",
+ "token",
+ "id_token",
+ "code token",
+ "code id_token",
+ "token id_token",
+ "code token id_token",
+ "none"
+ ],
+ "subject_types_supported":[
+ "public"
+ ],
+ "id_token_signing_alg_values_supported":[
+ "RS256"
+ ],
+ "request_object_signing_alg_values_supported":[
+ "HS256"
+ ],
+ "request_object_encryption_alg_values_supported":[
+ "RSA1_5",
+ "RSA-OAEP",
+ "RSA-OAEP-256",
+ "RSA-OAEP-384",
+ "RSA-OAEP-512",
+ "ECDH-ES",
+ "ECDH-ES+A128KW",
+ "ECDH-ES+A192KW",
+ "ECDH-ES+A256KW",
+ "A128KW",
+ "A192KW",
+ "A256KW",
+ "A128GCMKW",
+ "A192GCMKW",
+ "A256GCMKW",
+ "dir"
+ ],
+ "request_object_encryption_enc_values_supported":[
+ "A128CBC-HS256",
+ "A192CBC-HS384",
+ "A256CBC-HS512",
+ "A128GCM",
+ "A192GCM",
+ "A256GCM"
+ ],
+ "scopes_supported":[
+ "openid",
+ "email",
+ "profile"
+ ],
+ "token_endpoint_auth_methods_supported":[
+ "client_secret_post",
+ "client_secret_basic"
+ ],
+ "claims_supported":[
+ "aud",
+ "email",
+ "email_verified",
+ "exp",
+ "family_name",
+ "given_name",
+ "iat",
+ "iss",
+ "locale",
+ "name",
+ "picture",
+ "sub"
+ ],
+ "code_challenge_methods_supported":[
+ "plain",
+ "S256"
+ ],
+ "grant_types_supported":[
+ "authorization_code",
+ "refresh_token",
+ "urn:ietf:params:oauth:grant-type:device_code",
+ "urn:ietf:params:oauth:grant-type:jwt-bearer"
+ ]
+}
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list