[java-plugin-shibd-oidc] branch dev/JSHIBDOIDC-31-cred-resolver updated: WIP: Adding the new credential resolver to the decryption key lookup
Codeberg
noreply at shibboleth.net
Fri Jul 31 12:11:44 UTC 2026
This is an automated email from the git hooks/post-receive script.
codeberg pushed a commit to branch dev/JSHIBDOIDC-31-cred-resolver
in repository java-plugin-shibd-oidc.
View the commit online:
https://codeberg.org/Shibboleth/java-plugin-shibd-oidc/commit/a5dbceb5f5d5fe9db28b3b7a2312bf017e8e3b6f
The following commit(s) were added to refs/heads/dev/JSHIBDOIDC-31-cred-resolver by this push:
new a5dbceb WIP: Adding the new credential resolver to the decryption key lookup
a5dbceb is described below
commit a5dbceb5f5d5fe9db28b3b7a2312bf017e8e3b6f
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Fri Jul 31 13:11:37 2026 +0100
WIP: Adding the new credential resolver to the decryption key lookup
- this works, but the StaticFilteringCriterionCredentialResolver needs
more explaining, and there is criterion filtering happening at a number
of overlapping levels e.g. StaticFilteringCriterionCredentialResolver
and LocalJOSEObjectCredentialResolver which needs to be cleaned up.
---
.../net/shibboleth/sp/oidc/testing/TestHelper.java | 38 ++++++-
.../net/shibboleth/sp/service/agent/postconfig.xml | 41 +++++--
.../flows/AbstractOIDCTokenConsumerFlowTest.java | 7 +-
.../sp/oidc/flows/OIDCTokenConsumerFlowTest.java | 68 +++++++++++-
.../src/test/resources/logback-flow-test.xml | 4 +
.../idp/module/conf/sp/oidc-credentials.xml | 2 +
.../net/shibboleth/sp/oidc-test-beans.xml | 1 +
...StaticFilteringCriterionCredentialResolver.java | 119 +++++++++++++++++++++
8 files changed, 266 insertions(+), 14 deletions(-)
diff --git a/sp-oidc-api/src/test/java/net/shibboleth/sp/oidc/testing/TestHelper.java b/sp-oidc-api/src/test/java/net/shibboleth/sp/oidc/testing/TestHelper.java
index 2cdc89b..28290c8 100644
--- a/sp-oidc-api/src/test/java/net/shibboleth/sp/oidc/testing/TestHelper.java
+++ b/sp-oidc-api/src/test/java/net/shibboleth/sp/oidc/testing/TestHelper.java
@@ -273,6 +273,31 @@ public final class TestHelper {
@Nonnull public static JWT createJWT(@Nonnull final JWTClaimsSet payload, @Nullable final JWSAlgorithm sigAlg,
@Nullable final JWEAlgorithm jweAlg, @Nullable final EncryptionMethod enc,
@Nullable final Credential sigKey, @Nullable final Credential encKey) throws JOSEException, ParseException {
+ return createJWT(payload, sigAlg, jweAlg, enc, sigKey, encKey, null);
+ }
+
+ /**
+ * Create a JWT from the given payload. The JWT can either be plain, or signed and encrypted. If encrypted, it must
+ * be signed.
+ *
+ * @param payload the payload to create the JWT from
+ * @param sigAlg the signature alg to use. {@code Null} if the JWT is not going to be signed and/or encrypted.
+ * @param jweAlg the encryption alg to use. {@code Null} if the JWT is not going to be encrypted. Note, if encrypted
+ * the signature algorithm must also be supplied, otherwise a plain JWT will be returned.
+ * @param enc the content encryption algorithm to use.
+ * @param sigKey the key to use for signing
+ * @param encKey the key to use for encryption
+ * @param encKeyKid the keyID for the encryption key to add to the header.
+ *
+ * @return and plain JWT, JWS, or JWE.
+ *
+ * @throws JOSEException on error.
+ * @throws ParseException on error.
+ */
+ @Nonnull public static JWT createJWT(@Nonnull final JWTClaimsSet payload, @Nullable final JWSAlgorithm sigAlg,
+ @Nullable final JWEAlgorithm jweAlg, @Nullable final EncryptionMethod enc,
+ @Nullable final Credential sigKey, @Nullable final Credential encKey, @Nullable final String encKeyKid)
+ throws JOSEException, ParseException {
// Sign first.
if (sigAlg != null && sigKey != null) {
@@ -290,11 +315,22 @@ public final class TestHelper {
}
if (jweAlg != null && encKey != null) {
- final JWEObject jweObject =
+ JWEObject jweObject = null;
+ if (encKeyKid != null) {
+ jweObject =
+ new JWEObject(new JWEHeader.Builder(jweAlg, enc)
+ .contentType("JWT")
+ .keyID(encKeyKid)
+ .build(),
+ new Payload(signedJWT));
+ }
+ else{
+ jweObject =
new JWEObject(new JWEHeader.Builder(jweAlg, enc)
.contentType("JWT")
.build(),
new Payload(signedJWT));
+ }
if (JWEAlgorithm.Family.RSA.contains(jweAlg)) {
jweObject.encrypt(new RSAEncrypter((RSAPublicKey)encKey.getPublicKey()));
diff --git a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/sp/service/agent/postconfig.xml b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/sp/service/agent/postconfig.xml
index 6f71b8b..3829842 100644
--- a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/sp/service/agent/postconfig.xml
+++ b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/sp/service/agent/postconfig.xml
@@ -256,16 +256,11 @@
</list>
</property>
</bean>
-
- <bean id="shibboleth.sp.oidc.SigningCredentialsFactory"
- class="net.shibboleth.oidc.profile.config.CredentialsListFactory"
- c:_0="#{getObject('shibboleth.oidc.SigningCredentials')}" />
<bean id="defaultOIDCKeyEncryptionCredentialResolver"
class="net.shibboleth.oidc.security.credential.impl.ChainingJOSEObjectCredentialResolver">
<constructor-arg>
<list>
- <!-- Used by the RP -->
<bean id="OIDCProviderMetadataCredentialResolver"
class="net.shibboleth.oidc.security.credential.impl.ProviderMetadataCredentialResolver"
c:remoteJwkSetCache-ref="shibboleth.oidc.RemoteJwkSetCache"
@@ -280,7 +275,6 @@
class="net.shibboleth.oidc.security.credential.impl.ChainingJOSEObjectCredentialResolver">
<constructor-arg>
<list>
- <!-- Used by the RP -->
<bean id="ClientSecretCriterionCredentialResolver"
class="net.shibboleth.oidc.security.credential.impl.ClientSecretCriterionCredentialResolver"/>
</list>
@@ -296,18 +290,44 @@
<!--
A resolver to public/private key encryption keys global to the RP
-->
+
+ <!-- This bridges the bean below that resolves decryption keys into our service while adding needed criteria. -->
+ <bean id="localDecryptionKEKResolver" class="net.shibboleth.sp.jose.config.impl.StaticFilteringCriterionCredentialResolver"
+ c:resolver-ref="shibboleth.sp.CredentialResolverBridge">
+ <constructor-arg name="criteria">
+ <set>
+ <bean class="org.opensaml.security.criteria.UsageCriterion">
+ <constructor-arg>
+ <util:constant static-field="org.opensaml.security.credential.UsageType.ENCRYPTION" />
+ </constructor-arg>
+ </bean>
+ <bean class="org.opensaml.saml.criterion.ProtocolCriterion">
+ <constructor-arg>
+ <util:constant static-field="net.shibboleth.oidc.saml.xmlobject.Constants.OIDC_PROTOCOL_URI" />
+ </constructor-arg>
+ </bean>
+ </set>
+ </constructor-arg>
+ </bean>
+
<bean id="defaultOIDCKeyDecryptionCredentialResolver"
class="net.shibboleth.oidc.security.credential.impl.ChainingJOSEObjectCredentialResolver">
<constructor-arg>
<list>
- <bean class="net.shibboleth.oidc.security.credential.impl.LocalJOSEObjectCredentialResolver">
- <constructor-arg name="localCredentialResolver"><!-- TODO change to the shibboleth.sp.CredentialResolverBridge -->
+ <!--
+ This resolver pulls out keys from JWT headers and matches them to local credentials. In addition,
+ it adds local credentials if none are present in the headers, using the keyId, if present, for
+ credential resolvers to use in matching local keys.
+ -->
+ <bean id="localDecryptionCredentialResolver"
+ class="net.shibboleth.oidc.security.credential.impl.LocalJOSEObjectCredentialResolver"
+ c:localCredentialResolver-ref="localDecryptionKEKResolver">
+ <!-- <constructor-arg name="localCredentialResolver">
<bean
class="net.shibboleth.oidc.security.credential.impl.CollectionJOSEObjectCredentialResolver"
c:credentials-ref="shibboleth.oidc.EncryptionCredentials" />
- </constructor-arg>
+ </constructor-arg> -->
</bean>
- <!-- Used by the RP -->
<bean id="CriterionCredentialResolver"
class="net.shibboleth.oidc.security.credential.impl.ClientSecretCriterionCredentialResolver"/>
</list>
@@ -340,6 +360,7 @@
class="net.shibboleth.oidc.security.credential.impl.BasicJOSEObjectCredentialResolver" />
<!-- A resolver for resolving trusted credentials to match against those resolved from the JWT -->
+ <!-- TODO the client_secret credential should come from the new credential resolver -->
<bean id="defaultSignedJWTTrustedCredentialResolver"
class="net.shibboleth.oidc.security.credential.impl.ChainingJOSEObjectCredentialResolver">
<constructor-arg>
diff --git a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/AbstractOIDCTokenConsumerFlowTest.java b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/AbstractOIDCTokenConsumerFlowTest.java
index 6a75ad2..fd136a5 100644
--- a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/AbstractOIDCTokenConsumerFlowTest.java
+++ b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/AbstractOIDCTokenConsumerFlowTest.java
@@ -200,13 +200,16 @@ public abstract class AbstractOIDCTokenConsumerFlowTest extends AbstractSPFlowTe
* @param expiry expiry time
* @param issuedAt issue time
* @param nonce the nonce
+ * @param additionalClaims any additional claims
+ * @param encKeyId the KeyID of the encryption key to add to the headers
+ *
* @return the tokens
* @throws ParseException
* @throws JOSEException
*/
protected OIDCTokenResponse constructSuccessfulTokenResponseSignedAndEncrypted(
@Nonnull final Instant expiry, @Nonnull final Instant issuedAt, @Nullable final String nonce,
- @Nullable final Map<String, Object> additionalClaims)
+ @Nullable final Map<String, Object> additionalClaims, @Nullable final String encKeyId)
throws JOSEException, ParseException {
final JWTClaimsSet.Builder claimsSetBuilder = new JWTClaimsSet.Builder()
@@ -228,7 +231,7 @@ public abstract class AbstractOIDCTokenConsumerFlowTest extends AbstractSPFlowTe
final JWT encryptedIdToken =
TestHelper.createJWT(claimsSet, JWSAlgorithm.RS256, JWEAlgorithm.RSA_OAEP_256,
- EncryptionMethod.A128CBC_HS256, opSigningCredential, rpEncryptionCredential);
+ EncryptionMethod.A128CBC_HS256, opSigningCredential, rpEncryptionCredential, encKeyId);
final AccessToken accessToken = new BearerAccessToken("fake-access-token-value", 3600, null);
final RefreshToken refreshToken = new RefreshToken("fake-refresh-token-value");
diff --git a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowTest.java b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowTest.java
index d6bb66f..c45892a 100644
--- a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowTest.java
+++ b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowTest.java
@@ -261,7 +261,7 @@ public class OIDCTokenConsumerFlowTest extends AbstractOIDCTokenConsumerFlowTest
public void testSuccess_SignedEncryptedIDToken_PlainUserInfo() throws Exception {
mockOIDCEndpoints(constructSuccessfulTokenResponseSignedAndEncrypted(Instant.now().plusSeconds(3600),
- Instant.now(), null, null), constructJSONUserInfoResponse());
+ Instant.now(), null, null, null), constructJSONUserInfoResponse());
final AuthenticationSuccessResponse response =
TestHelper.buildOIDCAuthorizationCodeResponse(TestConstants.RESPONSE_URL, ResponseMode.QUERY,
@@ -286,6 +286,72 @@ public class OIDCTokenConsumerFlowTest extends AbstractOIDCTokenConsumerFlowTest
TestConstants.RESOURCE_URL);
}
+ /**
+ * Test successful flow with a signed and encrypted id_token and a plain user info response. The kid of the key
+ * used to encrypt the IDToken is in the Headers.
+ *
+ * @throws IOException on error
+ */
+ @Test
+ public void testSuccess_SignedEncryptedIDToken_WithDecryptionKID_PlainUserInfo() throws Exception {
+
+ mockOIDCEndpoints(constructSuccessfulTokenResponseSignedAndEncrypted(Instant.now().plusSeconds(3600),
+ Instant.now(), null, null, rpEncryptionCredential.getKid()), constructJSONUserInfoResponse());
+
+ final AuthenticationSuccessResponse response =
+ TestHelper.buildOIDCAuthorizationCodeResponse(TestConstants.RESPONSE_URL, ResponseMode.QUERY,
+ TestConstants.STATE_TOKEN);
+ final DDF input = buildRemotedQueryStringResponse(response);
+
+ // Add cookies
+ input.addmember("http.headers.Cookie").unsafe_string(TestHelper.buildCookieHeader(
+ TestConstants.STATE_TOKEN,
+ TestConstants.APPLICATION_ID_REQUEST_OBJECT,
+ TestHelper.buildAuthenticationState(null, false, null), true));
+
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
+
+ final FlowExecutionResult result = flowExecutor.launchExecution(TestConstants.FLOW_ID, null, externalContext);
+ assertFlowExecutionResult(result, TestConstants.FLOW_ID);
+ assertFlowExecutionOutcome(result.getOutcome());
+ final DDF output = assertOutputMessageSuccess(result);
+ assert output != null;
+ System.out.println("test output: " + output.toString());
+ validateOutputMessage(result, CollectionSupport.setOf("sub","mail","displayName","eduPersonScopedAffiliation"),
+ TestConstants.RESOURCE_URL);
+ }
+
+ /**
+ * Test failure flow with a signed and encrypted id_token and a plain user info response. The kid of the key
+ * used to encrypt the IDToken is not one that matches to a local key defined.
+ *
+ * @throws IOException on error
+ */
+ @Test
+ public void testFail_SignedEncryptedIDToken_WithDifferentDecryptionKID_PlainUserInfo() throws Exception {
+
+ mockOIDCEndpoints(constructSuccessfulTokenResponseSignedAndEncrypted(Instant.now().plusSeconds(3600),
+ Instant.now(), null, null, "wrong-encryption-keyid"), constructJSONUserInfoResponse());
+
+ final AuthenticationSuccessResponse response =
+ TestHelper.buildOIDCAuthorizationCodeResponse(TestConstants.RESPONSE_URL, ResponseMode.QUERY,
+ TestConstants.STATE_TOKEN);
+ final DDF input = buildRemotedQueryStringResponse(response);
+
+ // Add cookies
+ input.addmember("http.headers.Cookie").unsafe_string(TestHelper.buildCookieHeader(
+ TestConstants.STATE_TOKEN,
+ TestConstants.APPLICATION_ID_REQUEST_OBJECT,
+ TestHelper.buildAuthenticationState(null, false, null), true));
+
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
+
+ final FlowExecutionResult result = flowExecutor.launchExecution(TestConstants.FLOW_ID, null, externalContext);
+ assertFlowExecutionResult(result, TestConstants.FLOW_ID);
+ assertFlowExecutionOutcome(result.getOutcome());
+ assertOutputMessageEvent(result, EventIds.MESSAGE_PROC_ERROR);
+ }
+
/**
* Test successful flow with a signed id_token and a JWT user info response.
*
diff --git a/sp-oidc-conf-impl/src/test/resources/logback-flow-test.xml b/sp-oidc-conf-impl/src/test/resources/logback-flow-test.xml
index a89c91c..fedae41 100644
--- a/sp-oidc-conf-impl/src/test/resources/logback-flow-test.xml
+++ b/sp-oidc-conf-impl/src/test/resources/logback-flow-test.xml
@@ -18,6 +18,10 @@
<appender-ref ref="STDOUT" />
</logger>
+ <logger name="org.opensaml.security" level="DEBUG" additivity="false">
+ <appender-ref ref="STDOUT" />
+ </logger>
+
<logger name="net.shibboleth.idp" level="DEBUG" additivity="false">
<appender-ref ref="STDOUT" />
</logger>
diff --git a/sp-oidc-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/oidc-credentials.xml b/sp-oidc-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/oidc-credentials.xml
index 4a26085..955a893 100644
--- a/sp-oidc-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/oidc-credentials.xml
+++ b/sp-oidc-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/oidc-credentials.xml
@@ -11,6 +11,8 @@
default-init-method="initialize"
default-destroy-method="destroy">
+
+ <!-- TODO: with changes to credential resolver, remove this!! -->
<!--
This file contains default OIDC signing and encryption credentials. This file should be imported into agents.xml.
diff --git a/sp-oidc-conf-impl/src/test/resources/net/shibboleth/sp/oidc-test-beans.xml b/sp-oidc-conf-impl/src/test/resources/net/shibboleth/sp/oidc-test-beans.xml
index 32ee7bf..084a430 100644
--- a/sp-oidc-conf-impl/src/test/resources/net/shibboleth/sp/oidc-test-beans.xml
+++ b/sp-oidc-conf-impl/src/test/resources/net/shibboleth/sp/oidc-test-beans.xml
@@ -28,6 +28,7 @@
<bean id="shibboleth.oidc.JWKCredential" abstract="true"
class="net.shibboleth.oidc.security.credential.BasicJWKCredentialFactoryBean" />
+ <!-- These need to be the same as those resolvable by the security configuration used -->
<bean id="dummy.op.signing.Credential" parent="shibboleth.oidc.JWKCredential"
p:resource="%{idp.home}/credentials/op/op-signing-rsa.jwk" p:throwIfNull="false" />
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/jose/config/impl/StaticFilteringCriterionCredentialResolver.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/jose/config/impl/StaticFilteringCriterionCredentialResolver.java
new file mode 100644
index 0000000..66d2eb9
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/jose/config/impl/StaticFilteringCriterionCredentialResolver.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed 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.sp.jose.config.impl;
+
+import java.util.Collection;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.security.credential.Credential;
+import org.opensaml.security.credential.CredentialResolver;
+import org.opensaml.security.credential.criteria.impl.EvaluableCredentialCriterion;
+import org.opensaml.security.credential.impl.AbstractCriteriaFilteringCredentialResolver;
+
+import net.shibboleth.oidc.security.credential.JOSEObjectCredentialResolver;
+import net.shibboleth.shared.annotation.ParameterName;
+import net.shibboleth.shared.annotation.constraint.NonnullElements;
+import net.shibboleth.shared.collection.CollectionSupport;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.resolver.CriteriaSet;
+import net.shibboleth.shared.resolver.Criterion;
+import net.shibboleth.shared.resolver.ResolverException;
+
+/**
+ * A filtering resolver that adds statically-defined {@link Criterion} objects to a new {@link CriteriaSet}
+ * fed into a wrapped, delegated, resolver.
+ *
+ * <p>The new criteria set may optionally include the criteria supplied by the caller. The caller's input
+ * {@link CriteriaSet} instance is never passed directly to the wrapped resolver.</p>
+ *
+ * <p>After credential resolution has been performed by the wrapped resolver, the filtering behaviour from
+ * {@link AbstractCriteriaFilteringCredentialResolver} is applied using any {@link EvaluableCredentialCriterion}
+ * instances present in the input criteria set (not including the static criteria, or anything from the underlying
+ * resolver). Technically these filters are added as an additional filter-view layer on top of whatever is produced
+ * by the wrapped resolver.</p>
+ *
+ * <p>Restated, the statically-defined criteria (and, optionally, the caller-supplied criteria) are passed to the
+ * wrapped credential resolver, which may use them as it sees fit during credential resolution. Once the wrapped
+ * resolver has finished its resolution, this resolver adds another filter layer to the resulting credential iterable
+ * using only those {@link EvaluableCredentialCriterion} instances present in the input criteria set.</p>
+ *
+ * <p>It exports the additional {@link JOSEObjectCredentialResolver} interface so it can be used for JOSE credential
+ * resolution. Effectively bridging between JOSE credential use cases, and an underlying, generic,
+ * CredentialResolver.</p>
+ *
+ */
+public class StaticFilteringCriterionCredentialResolver extends AbstractCriteriaFilteringCredentialResolver
+ implements JOSEObjectCredentialResolver {
+
+ /** List of credentials held by this resolver. */
+ @Nonnull private final CredentialResolver credentialResolver;
+
+ /** Static criteria to add. */
+ @Nonnull private final Collection<Criterion> staticCriteria;
+
+ /**
+ * If the {@link CriteriaSet} from the caller should be copied into the {@link CriteriaSet} passed into the
+ * credential resolver. Defaults to false if not set, where only the staticCriteria are passed through.
+ */
+ private final boolean enableCriteriaPassthrough;
+
+ /**
+ * Constructor.
+ *
+ * @param resolver underlying resolver
+ * @param criteria static criteria to add to all resolutions
+ * @param passthrough If the {@link CriteriaSet} from the caller should be copied into the
+ * {@link CriteriaSet} passed into the credential resolver
+ */
+ public StaticFilteringCriterionCredentialResolver(
+ @Nonnull @ParameterName(name="resolver") final CredentialResolver resolver,
+ @Nullable @ParameterName(name="criteria") final Collection<Criterion> criteria,
+ @ParameterName(name="criteriaPassthrough") final boolean passthrough) {
+ credentialResolver = Constraint.isNotNull(resolver, "CredentialResolver cannot be null");
+ if (criteria != null) {
+ staticCriteria = CollectionSupport.copyToSet(criteria);
+ } else {
+ staticCriteria = CollectionSupport.emptySet();
+ }
+ enableCriteriaPassthrough = passthrough;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param resolver underlying resolver
+ * @param criteria static criteria to add to all resolutions
+ */
+ public StaticFilteringCriterionCredentialResolver(
+ @Nonnull @ParameterName(name="resolver") final CredentialResolver resolver,
+ @Nullable @ParameterName(name="criteria") final Collection<Criterion> criteria) {
+ this(resolver, criteria, false);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull @NonnullElements public Iterable<Credential> resolveFromSource(
+ @Nullable final CriteriaSet criteriaSet) throws ResolverException {
+ final CriteriaSet finalCriteria = new CriteriaSet();
+ if (enableCriteriaPassthrough && criteriaSet != null) {
+ finalCriteria.addAll(criteriaSet);
+ }
+ finalCriteria.addAll(staticCriteria);
+ return credentialResolver.resolve(finalCriteria);
+ }
+
+}
\ 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