[java-oidc-common] branch main updated: JOIDC-144 - Improve token audience handling with JWT authentication

Henri Mikkonen henri.mikkonen at iki.fi
Fri Apr 14 05:31:34 UTC 2023


This is an automated email from the git hooks/post-receive script.

hjmikkon pushed a commit to branch main
in repository java-oidc-common.

View the commit online:
http://git.shibboleth.net/view/?p=java-oidc-common.git;a=commit;h=a1e3ff5a83c753786f63813efc09981d20052977

The following commit(s) were added to refs/heads/main by this push:
     new a1e3ff5  JOIDC-144 - Improve token audience handling with JWT authentication
a1e3ff5 is described below

commit a1e3ff5a83c753786f63813efc09981d20052977
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Fri Apr 14 08:31:16 2023 +0300

    JOIDC-144 - Improve token audience handling with JWT authentication
    
    https://shibboleth.atlassian.net/browse/JOIDC-144
    
    Refactored the existing AudienceClaimsValidator so that it can be
    extended to deal with multiple accepted audiences. A new validator
    AuthenticationAudienceClaimsValidator extends it and provides means
    to accept issuer value (responder ID) and token endpoint URL in
    addition to the single accepted audience.
---
 .../jwt/claims/impl/AudienceClaimsValidator.java   |  32 ++-
 .../AuthenticationAudienceClaimsValidator.java     | 135 ++++++++++++
 .../AuthenticationAudienceClaimsValidatorTest.java | 237 +++++++++++++++++++++
 3 files changed, 397 insertions(+), 7 deletions(-)

diff --git a/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/jwt/claims/impl/AudienceClaimsValidator.java b/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/jwt/claims/impl/AudienceClaimsValidator.java
index 555d05a..4763c4c 100644
--- a/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/jwt/claims/impl/AudienceClaimsValidator.java
+++ b/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/jwt/claims/impl/AudienceClaimsValidator.java
@@ -33,6 +33,7 @@ import com.nimbusds.jwt.JWTClaimsSet;
 import net.shibboleth.oidc.jwt.claims.AbstractClaimsValidator;
 import net.shibboleth.oidc.jwt.claims.JWTValidationException;
 import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
 import net.shibboleth.utilities.java.support.annotation.constraint.ThreadSafeAfterInit;
 import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
 import net.shibboleth.utilities.java.support.component.ComponentSupport;
@@ -136,14 +137,30 @@ public class AudienceClaimsValidator extends AbstractClaimsValidator{
         extraAudienceValidation = flag;
     }
 
-    @Override
-    protected void doValidate(@Nonnull final JWTClaimsSet claims, @Nonnull final ProfileRequestContext context) 
-               throws JWTValidationException {
-        
+    /**
+     * Resolve the set of accepted audiences. This method is mostly a hook for classes extending this validator: in
+     * this case it simply returns the resolved single accepted audience in the set.
+     * 
+     * @param claims the claims fed for the audience lookup strategy
+     * @param context the profile request context fed for the audience lookup strategy
+     * @return the set containing the accepted audience claim
+     * @throws JWTValidationException if the audience value could not be resolved via lookup strategy
+     */
+    @Nonnull @NotEmpty protected Set<String> resolveAcceptedAudiences(@Nonnull final JWTClaimsSet claims,
+            @Nonnull final ProfileRequestContext context) throws JWTValidationException {
         final String acceptedAudience = audienceLookupStrategy.apply(context,claims);
         if (acceptedAudience == null) {
             throw new JWTValidationException("Audience value not returned by lookup function");
         }
+        return Set.of(acceptedAudience);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void doValidate(@Nonnull final JWTClaimsSet claims, @Nonnull final ProfileRequestContext context) 
+               throws JWTValidationException {
+        
+        final Set<String> acceptedAudiences = resolveAcceptedAudiences(claims, context);
         
         Set<String> additionalAudiences = additionalAudiencesLookupStrategy.apply(context, claims);
         if (additionalAudiences == null) {
@@ -165,10 +182,10 @@ public class AudienceClaimsValidator extends AbstractClaimsValidator{
         // Filter nulls from audList
         final List<String> audListFiltered = audList.stream().filter(Objects::nonNull).collect(Collectors.toList());       
                
-        final boolean acceptedAudienceMatch = audListFiltered.contains(acceptedAudience);
+        final boolean acceptedAudienceMatch = audListFiltered.stream().anyMatch(acceptedAudiences::contains);
 
         if (!acceptedAudienceMatch) {
-            throw new JWTValidationException("JWT audience rejected, accepted audience not found in: " 
+            throw new JWTValidationException("JWT audience rejected, no accepted audiences found in: " 
                     + audListFiltered);
         }
         
@@ -178,7 +195,8 @@ public class AudienceClaimsValidator extends AbstractClaimsValidator{
             
             // Remove the accepted audience
             final List<String> audListFilteredWithoutAcceptedAud = 
-                    audListFiltered.stream().filter(aud -> !aud.equals(acceptedAudience)).collect(Collectors.toList());
+                    audListFiltered.stream().filter(aud -> !acceptedAudiences.contains(aud))
+                    .collect(Collectors.toList());
             
             // Test all additional audiences are known or trusted
             final boolean additionalAudiencesTrusted = 
diff --git a/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/jwt/claims/impl/AuthenticationAudienceClaimsValidator.java b/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/jwt/claims/impl/AuthenticationAudienceClaimsValidator.java
new file mode 100644
index 0000000..f51fb81
--- /dev/null
+++ b/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/jwt/claims/impl/AuthenticationAudienceClaimsValidator.java
@@ -0,0 +1,135 @@
+/*
+ * 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.oidc.security.jwt.claims.impl;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import com.nimbusds.jwt.JWTClaimsSet;
+
+import net.shibboleth.idp.profile.context.navigate.ResponderIdLookupFunction;
+import net.shibboleth.oidc.jwt.claims.JWTValidationException;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.annotation.constraint.ThreadSafeAfterInit;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
+/**
+ * Verifies the Audience (aud) claim contains the appropriate value in JWT authentication. This validator extends the
+ * functionality of {@link AudienceClaimsValidator} with two features. First, it contains a configurable strategy for
+ * resolving responder ID that may be used in the audience claim. Second, it can be configured to replace configurable
+ * substrings from the audience claim into a configurable replacement. This is useful when token endpoint URL is
+ * desired to be accepted in some other endpoints.
+ * 
+ * The {@link AudienceClaimsValidator#resolveAcceptedAudiences(JWTClaimsSet, ProfileRequestContext)} is expected
+ * to return the endpoint URL used in the HTTP request containing the JWT authentication.
+ */
+ at ThreadSafeAfterInit
+public class AuthenticationAudienceClaimsValidator extends AudienceClaimsValidator{
+    
+    /** Lookup function for the responder identifier. */
+    @Nonnull private Function<ProfileRequestContext, String> responderIdLookupStrategy;
+    
+    /** The substrings to replace from resolved endpoint with one configured at {@link #endpointReplacement}. */
+    @Nonnull private List<String> endpointTargets;
+
+    /** The replacement substring for the endpoint containing any ones configured at {@link #endpointTargets}. */
+    @Nullable private String endpointReplacement;
+    
+    /** Constructor. */
+    public AuthenticationAudienceClaimsValidator() {
+        super();
+        responderIdLookupStrategy = new ResponderIdLookupFunction();
+        endpointTargets = Collections.emptyList();
+        endpointReplacement = null;
+    }
+    
+    /**
+     * Set the lookup function for the responder identifier.
+     * 
+     * @param strategy What to set.
+     */
+    public void setResponderIdLookupStrategy(@Nonnull final Function<ProfileRequestContext, String> strategy) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+        responderIdLookupStrategy = Constraint.isNotNull(strategy, "The responder ID lookup strategy cannot be null");
+    }
+
+    /**
+     * Set the substrings to replace from resolved endpoint with one configured at {@link #endpointReplacement}.
+     * 
+     * @param paths What to set.
+     */
+    public void setEndpointTargets(@Nonnull final List<String> paths) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+        endpointTargets = Constraint.isNotNull(paths, "The endpoint paths to replace cannot be null");
+    }
+
+    /**
+     * Set the replacement substring for the endpoint containing any ones configured at {@link #endpointTargets}.
+     * 
+     * @param path What to set.
+     */
+    public void setEndpointReplacement(@Nullable final String path) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+        endpointReplacement = path;
+    }
+
+    /**
+     * Resolve the set of accepted audiences. The accepted audience resolved by the super-class
+     * {@link AudienceClaimsValidator} is expected to be an endpoint URL of the HTTP request containing the JWT
+     * authentication. If {@link #endpointTargets} and {@link #endpointReplacement} are configured, they're exploited
+     * in adding the an additional accepted audience. The responder ID is also included to the accepted audience values.
+     * 
+     * @param claims the claims fed for the audience lookup strategy
+     * @param context the profile request context fed for the audience lookup strategy
+     * @return the set containing the accepted audience values
+     * @throws JWTValidationException if the audience value could not be resolved via lookup strategy
+     */
+    @Override @Nonnull @NotEmpty protected Set<String> resolveAcceptedAudiences(@Nonnull final JWTClaimsSet claims,
+            @Nonnull final ProfileRequestContext context) throws JWTValidationException {
+        final String endpointAudience = super.resolveAcceptedAudiences(claims, context).iterator().next();
+        final Set<String> result = new HashSet<>();
+        final String responderId = responderIdLookupStrategy.apply(context);
+        if (StringSupport.trimOrNull(responderId) != null) {
+            result.add(responderId);
+        }
+        result.add(endpointAudience);
+        for (final String path : endpointTargets) {
+            if (endpointAudience.contains(path) && endpointReplacement != null) {
+                result.add(endpointAudience.replace(path, endpointReplacement));
+            }
+        }
+        return result;
+    }
+
+}
diff --git a/oidc-common-crypto-impl/src/test/java/net/shibboleth/oidc/security/jwt/claims/impl/AuthenticationAudienceClaimsValidatorTest.java b/oidc-common-crypto-impl/src/test/java/net/shibboleth/oidc/security/jwt/claims/impl/AuthenticationAudienceClaimsValidatorTest.java
new file mode 100644
index 0000000..e187a2f
--- /dev/null
+++ b/oidc-common-crypto-impl/src/test/java/net/shibboleth/oidc/security/jwt/claims/impl/AuthenticationAudienceClaimsValidatorTest.java
@@ -0,0 +1,237 @@
+/* 
+ * 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.oidc.security.jwt.claims.impl;
+
+import java.util.List;
+import java.util.Set;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+
+import org.mockito.Mockito;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.nimbusds.jwt.JWTClaimsSet;
+
+import net.shibboleth.oidc.jwt.claims.JWTValidationException;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+
+/** Test for the {@link AuthenticationAudienceClaimsValidator}. */
+public class AuthenticationAudienceClaimsValidatorTest extends AbstractClaimsValidatorTest {
+    
+    /** The validator to test.*/
+    @Nonnull private AuthenticationAudienceClaimsValidator validator;
+
+    private final Function<ProfileRequestContext, String> responderIdLookup = Mockito.mock(Function.class);
+    
+    @Override
+    @BeforeMethod
+    public void setup() throws ComponentInitializationException {
+        super.setup();
+        validator = new AuthenticationAudienceClaimsValidator();
+        validator.setId("test-validator");
+    }
+
+    @Test(expectedExceptions = JWTValidationException.class)
+    public void doRejectedTest_NoAcceptedAudience() throws JWTValidationException, ComponentInitializationException {
+        final JWTClaimsSet claimsSet = 
+                new JWTClaimsSet.Builder().audience("https://localhost/idp/profile/oauth2/notMatching").build();
+        validator.setExtraAudienceValidation(false);
+        validator.setAudienceLookupStrategy((prc,claims) -> "https://localhost/idp/profile/oauth2/one");
+        validator.initialize();
+        validator.validate(claimsSet, prc);
+    }
+
+    @Test
+    public void doValidTest_EndpointAsOnlyAudience() throws JWTValidationException, ComponentInitializationException {
+        final JWTClaimsSet claimsSet = 
+                new JWTClaimsSet.Builder().audience("https://localhost/idp/profile/oauth2/one").build();
+        validator.setExtraAudienceValidation(false);
+        validator.setAudienceLookupStrategy((prc,claims) -> "https://localhost/idp/profile/oauth2/one");
+        validator.setEndpointTargets(List.of("/profile/oauth2/one", "/profile/oauth2/two"));
+        validator.setEndpointReplacement("/profile/oidc/token");
+        validator.initialize();
+        validator.validate(claimsSet, prc);
+    }
+
+    @Test
+    public void doValidTest_EndpointAsOneAudience_noAdditionalAudience()
+            throws JWTValidationException, ComponentInitializationException {
+        final JWTClaimsSet claimsSet =
+                new JWTClaimsSet.Builder().audience(List.of("https://localhost/idp/profile/oauth2/one", "another"))
+                .build();
+        validator.setExtraAudienceValidation(false);
+        validator.setAudienceLookupStrategy((prc,claims) -> "https://localhost/idp/profile/oauth2/one");
+        validator.setEndpointTargets(List.of("/profile/oauth2/one", "/profile/oauth2/two"));
+        validator.setEndpointReplacement("/profile/oidc/token");
+        validator.initialize();
+        validator.validate(claimsSet, prc);
+    }
+
+    @Test(expectedExceptions = JWTValidationException.class)
+    public void doRejectedTest_EndpointAsOneAudience_noAdditionalAudience()
+            throws JWTValidationException, ComponentInitializationException {
+        final JWTClaimsSet claimsSet =
+                new JWTClaimsSet.Builder().audience(List.of("https://localhost/idp/profile/oauth2/one", "another"))
+                .build();
+        validator.setExtraAudienceValidation(true);
+        validator.setAudienceLookupStrategy((prc,claims) -> "https://localhost/idp/profile/oauth2/one");
+        validator.setEndpointTargets(List.of("/profile/oauth2/one", "/profile/oauth2/two"));
+        validator.setEndpointReplacement("/profile/oidc/token");
+        validator.initialize();
+        validator.validate(claimsSet, prc);
+    }
+
+    @Test
+    public void doValidTest_EndpointAsOneAudience_withTrustedAdditionalAudience()
+            throws JWTValidationException, ComponentInitializationException {
+        final JWTClaimsSet claimsSet =
+                new JWTClaimsSet.Builder().audience(List.of("https://localhost/idp/profile/oauth2/one", "another"))
+                .build();
+        validator.setExtraAudienceValidation(true);
+        validator.setAudienceLookupStrategy((prc,claims) -> "https://localhost/idp/profile/oauth2/one");
+        validator.setEndpointTargets(List.of("/profile/oauth2/one", "/profile/oauth2/two"));
+        validator.setEndpointReplacement("/profile/oidc/token");
+        validator.setAdditionalAudiencesLookupStrategy((prc, claims) -> Set.of("another"));
+        validator.initialize();
+        validator.validate(claimsSet, prc);
+    }
+
+    @Test
+    public void doValidTest_ReplacedEndpointAsOnlyAudience()
+            throws JWTValidationException, ComponentInitializationException {
+        final JWTClaimsSet claimsSet = 
+                new JWTClaimsSet.Builder().audience("https://localhost/idp/profile/oidc/token").build();
+        validator.setExtraAudienceValidation(false);
+        validator.setAudienceLookupStrategy((prc,claims) -> "https://localhost/idp/profile/oauth2/one");
+        validator.setEndpointTargets(List.of("/profile/oauth2/one", "/profile/oauth2/two"));
+        validator.setEndpointReplacement("/profile/oidc/token");
+        validator.initialize();
+        validator.validate(claimsSet, prc);
+    }
+
+    @Test
+    public void doValidTest_ReplacedEndpointAsOneAudience_noAdditionalAudience()
+            throws JWTValidationException, ComponentInitializationException {
+        final JWTClaimsSet claimsSet =
+                new JWTClaimsSet.Builder().audience(List.of("https://localhost/idp/profile/oidc/token", "another"))
+                .build();
+        validator.setExtraAudienceValidation(false);
+        validator.setAudienceLookupStrategy((prc,claims) -> "https://localhost/idp/profile/oauth2/one");
+        validator.setEndpointTargets(List.of("/profile/oauth2/one", "/profile/oauth2/two"));
+        validator.setEndpointReplacement("/profile/oidc/token");
+        validator.initialize();
+        validator.validate(claimsSet, prc);
+    }
+
+    @Test(expectedExceptions = JWTValidationException.class)
+    public void doRejectedTest_ReplacedEndpointAsOneAudience_noMandatoryAdditionalAudience()
+            throws JWTValidationException, ComponentInitializationException {
+        final JWTClaimsSet claimsSet =
+                new JWTClaimsSet.Builder().audience(List.of("https://localhost/idp/profile/oidc/token", "another"))
+                .build();
+        validator.setExtraAudienceValidation(true);
+        validator.setAudienceLookupStrategy((prc,claims) -> "https://localhost/idp/profile/oauth2/one");
+        validator.setEndpointTargets(List.of("/profile/oauth2/one", "/profile/oauth2/two"));
+        validator.setEndpointReplacement("/profile/oidc/token");
+        validator.initialize();
+        validator.validate(claimsSet, prc);
+    }
+
+    @Test
+    public void doValidTest_ReplacedEndpointAsOneAudience_withTrustedAdditionalAudience()
+            throws JWTValidationException, ComponentInitializationException {
+        final JWTClaimsSet claimsSet =
+                new JWTClaimsSet.Builder().audience(List.of("https://localhost/idp/profile/oidc/token", "another"))
+                .build();
+        validator.setExtraAudienceValidation(true);
+        validator.setAudienceLookupStrategy((prc,claims) -> "https://localhost/idp/profile/oauth2/one");
+        validator.setEndpointTargets(List.of("/profile/oauth2/one", "/profile/oauth2/two"));
+        validator.setEndpointReplacement("/profile/oidc/token");
+        validator.setAdditionalAudiencesLookupStrategy((prc, claims) -> Set.of("another"));
+        validator.initialize();
+        validator.validate(claimsSet, prc);
+    }
+
+    @Test
+    public void doValidTest_ResponderIdAsOnlyAudience()
+            throws JWTValidationException, ComponentInitializationException {
+        final JWTClaimsSet claimsSet = 
+                new JWTClaimsSet.Builder().audience("https://op.example.org").build();
+        validator.setExtraAudienceValidation(false);
+        validator.setAudienceLookupStrategy((prc,claims) -> "https://localhost/idp/profile/oauth2/one");
+        validator.setEndpointTargets(List.of("/profile/oauth2/one", "/profile/oauth2/two"));
+        validator.setEndpointReplacement("/profile/oidc/token");
+        Mockito.when(responderIdLookup.apply(Mockito.any())).thenReturn("https://op.example.org");
+        validator.setResponderIdLookupStrategy(responderIdLookup);
+        validator.initialize();
+        validator.validate(claimsSet, prc);
+    }
+
+    @Test
+    public void doValidTest_ResponderIdAsOneAudience_noAdditionalAudience()
+            throws JWTValidationException, ComponentInitializationException {
+        final JWTClaimsSet claimsSet =
+                new JWTClaimsSet.Builder().audience(List.of("https://op.example.org", "another"))
+                .build();
+        validator.setExtraAudienceValidation(false);
+        validator.setAudienceLookupStrategy((prc,claims) -> "https://localhost/idp/profile/oauth2/one");
+        validator.setEndpointTargets(List.of("/profile/oauth2/one", "/profile/oauth2/two"));
+        validator.setEndpointReplacement("/profile/oidc/token");
+        Mockito.when(responderIdLookup.apply(Mockito.any())).thenReturn("https://op.example.org");
+        validator.setResponderIdLookupStrategy(responderIdLookup);
+        validator.initialize();
+        validator.validate(claimsSet, prc);
+    }
+
+    @Test(expectedExceptions = JWTValidationException.class)
+    public void doRejectedTest_ResponderIdAsOneAudience_noMandatoryAdditionalAudience()
+            throws JWTValidationException, ComponentInitializationException {
+        final JWTClaimsSet claimsSet =
+                new JWTClaimsSet.Builder().audience(List.of("https://op.example.org", "another"))
+                .build();
+        validator.setExtraAudienceValidation(true);
+        validator.setAudienceLookupStrategy((prc,claims) -> "https://localhost/idp/profile/oauth2/one");
+        validator.setEndpointTargets(List.of("/profile/oauth2/one", "/profile/oauth2/two"));
+        validator.setEndpointReplacement("/profile/oidc/token");
+        Mockito.when(responderIdLookup.apply(Mockito.any())).thenReturn("https://op.example.org");
+        validator.setResponderIdLookupStrategy(responderIdLookup);
+        validator.initialize();
+        validator.validate(claimsSet, prc);
+    }
+
+    @Test
+    public void doValidTest_ResponderIdAsOneAudience_withTrustedAdditionalAudience()
+            throws JWTValidationException, ComponentInitializationException {
+        final JWTClaimsSet claimsSet =
+                new JWTClaimsSet.Builder().audience(List.of("https://op.example.org", "another"))
+                .build();
+        validator.setExtraAudienceValidation(true);
+        validator.setAudienceLookupStrategy((prc,claims) -> "https://localhost/idp/profile/oauth2/one");
+        validator.setEndpointTargets(List.of("/profile/oauth2/one", "/profile/oauth2/two"));
+        validator.setEndpointReplacement("/profile/oidc/token");
+        validator.setAdditionalAudiencesLookupStrategy((prc, claims) -> Set.of("another"));
+        Mockito.when(responderIdLookup.apply(Mockito.any())).thenReturn("https://op.example.org");
+        validator.setResponderIdLookupStrategy(responderIdLookup);
+        validator.initialize();
+        validator.validate(claimsSet, prc);
+    }
+    
+}

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


More information about the commits mailing list