[java-identity-provider] 01/02: IDP-1988 - Build Predicate based on AttributeResolver

Scott Cantor cantor.2 at osu.edu
Mon Aug 1 17:17:03 UTC 2022


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

scantor pushed a commit to branch main
in repository java-identity-provider.

View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=a1712ef4bb2e5add1e5da8fc15d7d5c09023a336

commit a1712ef4bb2e5add1e5da8fc15d7d5c09023a336
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Mon Aug 1 13:04:56 2022 -0400

    IDP-1988 - Build Predicate based on AttributeResolver
    
    https://shibboleth.atlassian.net/browse/IDP-1988
    
    Also fix Instant class used in unit test.
---
 .../impl/AttributeRevocationCondition.java         | 265 +++++++++++++++++++++
 .../impl/AttributeRevocationConditionTest.java     | 172 +++++++++++++
 .../impl/RevocationCacheConditionTest.java         |   6 +-
 .../net/shibboleth/idp/conf/authn-system.xml       |   9 +-
 .../src/main/resources/conf/authn/authn.properties |   2 +-
 5 files changed, 448 insertions(+), 6 deletions(-)

diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/revocation/impl/AttributeRevocationCondition.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/revocation/impl/AttributeRevocationCondition.java
new file mode 100644
index 000000000..311cd28e4
--- /dev/null
+++ b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/revocation/impl/AttributeRevocationCondition.java
@@ -0,0 +1,265 @@
+/*
+ * 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.authn.revocation.impl;
+
+import java.time.DateTimeException;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.function.BiPredicate;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.ScratchContext;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.StringAttributeValue;
+import net.shibboleth.idp.attribute.resolver.AttributeResolver;
+import net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext;
+import net.shibboleth.idp.authn.AuthenticationResult;
+import net.shibboleth.idp.profile.context.navigate.RelyingPartyIdLookupFunction;
+import net.shibboleth.idp.profile.context.navigate.ResponderIdLookupFunction;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.component.AbstractInitializableComponent;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+import net.shibboleth.utilities.java.support.service.ReloadableService;
+
+/**
+ * A condition for login flows that checks for revocation against a resolved
+ * {@link IdPAttribute}.
+ * 
+ * @since 4.3.0
+ */
+public class AttributeRevocationCondition extends AbstractInitializableComponent
+        implements BiPredicate<ProfileRequestContext,AuthenticationResult> {
+
+    /** Class logger. */
+    @Nonnull private final Logger log = LoggerFactory.getLogger(AttributeRevocationCondition.class);
+    
+    /** Lookup strategy for principal name. */
+    @NonnullAfterInit private Function<ProfileRequestContext,String> principalNameLookupStrategy;
+
+    /** Strategy used to locate the identity of the issuer associated with the attribute resolution. */
+    @Nullable private Function<ProfileRequestContext,String> issuerLookupStrategy;
+
+    /** Strategy used to locate the identity of the recipient associated with the attribute resolution. */
+    @Nullable private Function<ProfileRequestContext,String> recipientLookupStrategy;
+    
+    /** Attribute Resolver service. */
+    @NonnullAfterInit private ReloadableService<AttributeResolver> attributeResolver;
+    
+    /** Attribute ID to resolve. */
+    @NonnullAfterInit @NotEmpty private String attributeId;
+    
+    /** Constructor. */
+    public AttributeRevocationCondition() {
+        issuerLookupStrategy = new ResponderIdLookupFunction();
+        recipientLookupStrategy = new RelyingPartyIdLookupFunction();
+    }
+        
+    /**
+     * Set lookup strategy for principal name.
+     * 
+     * @param strategy lookup strategy
+     */
+    public void setPrincipalNameLookupStrategy(@Nonnull final Function<ProfileRequestContext,String> strategy) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+        
+        principalNameLookupStrategy = Constraint.isNotNull(strategy, "Principal name lookup strategy cannot be null");
+    }
+    
+    /**
+     * Set the strategy used to lookup the issuer for this attribute resolution.
+     * 
+     * @param strategy  lookup strategy
+     */
+    public void setIssuerLookupStrategy(@Nullable final Function<ProfileRequestContext,String> strategy) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+        issuerLookupStrategy = strategy;
+    }
+
+    /**
+     * Set the strategy used to lookup the recipient for this attribute resolution.
+     * 
+     * @param strategy  lookup strategy
+     */
+    public void setRecipientLookupStrategy(@Nullable final Function<ProfileRequestContext,String> strategy) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+        recipientLookupStrategy = strategy;
+    }
+    
+    /**
+     * Set {@link AttributeResolver} to use.
+     * 
+     * @param service attribute resolver service
+     */
+    public void setAttributeResolver(@Nonnull final ReloadableService<AttributeResolver> service) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+        
+        attributeResolver = Constraint.isNotNull(service, "ReloadableService<AttributeResolver> cannot be null");
+    }
+    
+    /**
+     * Set the ID of an {@link IdPAttribute} to resolve to obtain revocation records for the principal.
+     * 
+     * @param id attribute ID to resolve
+     */
+    public void setAttributeId(@Nonnull @NotEmpty final String id) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+        
+        attributeId = Constraint.isNotNull(StringSupport.trimOrNull(id), "Attribute ID cannot be null or empty");
+    }
+    
+    /** {@inheritDoc} */
+    @Override
+    protected void doInitialize() throws ComponentInitializationException {
+        super.doInitialize();
+        
+        if (attributeResolver == null) {
+            throw new ComponentInitializationException("ReloadableService<AttributeResolver> cannot be null");
+        } else if (principalNameLookupStrategy == null) {
+            throw new ComponentInitializationException("Principal name lookup strategy cannot be null");
+        } else if (attributeId == null) {
+            throw new ComponentInitializationException("Attribute ID to resolve cannot be null or empty");
+        }
+    }
+
+    /** {@inheritDoc} */
+    public boolean test(@Nullable final ProfileRequestContext input,  @Nullable final AuthenticationResult input2) {
+        
+        if (input == null || input2 == null) {
+            log.error("Called with null inputs");
+            return true;
+        }
+        
+        final String principal = principalNameLookupStrategy.apply(input);
+        if (principal == null) {
+            log.error("Principal lookup strategy returned null value");
+            return true;
+        }
+        
+        log.debug("Checking revocation for principal name {} for {} result via attribute resolver", principal,
+                input2.getAuthenticationFlowId());
+        
+        final ScratchContext context = input.getSubcontext(ScratchContext.class, true);
+        
+        final AttributeResolutionContext resolutionContext = buildResolutionContext(input, principal);
+
+        if (!context.getMap().containsKey(getClass())) {
+            resolutionContext.resolveAttributes(attributeResolver);
+            final Collection<Instant> records = new ArrayList<>();
+            if (resolutionContext.getResolvedIdPAttributes().containsKey(attributeId)) {
+                for (final IdPAttributeValue value :
+                        resolutionContext.getResolvedIdPAttributes().get(attributeId).getValues()) {
+                    if (value instanceof StringAttributeValue) {
+                        try {
+                            records.add(Instant.ofEpochSecond(Long.valueOf(((StringAttributeValue) value).getValue())));
+                            
+                        } catch (final NumberFormatException|DateTimeException e) {
+                            log.error("Error parsing timestamp '{}' into epoch",
+                                    ((StringAttributeValue) value).getValue(), e);
+                        }
+                        
+                    } else {
+                        log.warn("Ignoring non-string attribute value type: {}", value.getClass().getName());
+                    }
+                }
+            } else {
+                log.debug("Resolver did not return an IdPAttribute named {} for principal {}", attributeId, principal);
+            }
+            
+            context.getMap().put(getClass(), records);
+            resolutionContext.getParent().removeSubcontext(resolutionContext);
+        }
+        
+        return isRevoked(principal, input2, (Collection<Instant>) context.getMap().get(getClass()));
+    }
+    
+    /**
+     * Build an {@link AttributeResolutionContext} to use.
+     * 
+     * @param profileRequestContext profile request context
+     * @param principal name of principal
+     * 
+     * @return the attached context
+     */
+    @Nonnull private AttributeResolutionContext buildResolutionContext(
+            @Nonnull final ProfileRequestContext profileRequestContext, @Nonnull @NotEmpty final String principal) {
+        
+        final AttributeResolutionContext resolutionContext = new AttributeResolutionContext();
+        
+        resolutionContext
+            .setPrincipal(principal)
+            .setResolutionLabel("authn/revocation")
+            .setRequestedIdPAttributeNames(Collections.singletonList(attributeId));
+        
+        if (recipientLookupStrategy != null) {
+            resolutionContext.setAttributeRecipientID(recipientLookupStrategy.apply(profileRequestContext));
+        }
+
+        if (issuerLookupStrategy != null) {
+            resolutionContext.setAttributeIssuerID(issuerLookupStrategy.apply(profileRequestContext));
+        }
+        
+        profileRequestContext.addSubcontext(resolutionContext, true);
+        return resolutionContext;
+    }
+
+    /**
+     * Check the revocation records' timestamps for applicability.
+     * 
+     * @param principal name of principal
+     * @param result active result being checked 
+     * @param revocationRecords the records from the cache
+     * 
+     * @return true iff the revocation applies to this result
+     */
+    protected boolean isRevoked(@Nonnull @NotEmpty final String principal, @Nonnull final AuthenticationResult result,
+            @Nonnull @NonnullElements final Collection<Instant> revocationRecords) {
+        
+        for (final Instant i : revocationRecords) {
+            if (result.getAuthenticationInstant().isBefore(i)) {
+                log.info("Authentication result {} for principal {} has been revoked", result.getAuthenticationFlowId(),
+                        principal);
+                return true;
+            }
+        }
+        
+        return false;
+    }
+    
+}
\ No newline at end of file
diff --git a/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/revocation/impl/AttributeRevocationConditionTest.java b/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/revocation/impl/AttributeRevocationConditionTest.java
new file mode 100644
index 000000000..db8763817
--- /dev/null
+++ b/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/revocation/impl/AttributeRevocationConditionTest.java
@@ -0,0 +1,172 @@
+/*
+ * 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.authn.revocation.impl;
+
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.stream.Collectors;
+
+import javax.security.auth.Subject;
+
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.StringAttributeValue;
+import net.shibboleth.idp.attribute.resolver.AttributeResolver;
+import net.shibboleth.idp.attribute.resolver.ResolutionException;
+import net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext;
+import net.shibboleth.idp.authn.AuthenticationResult;
+import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.idp.authn.impl.testing.BaseAuthenticationContextTest;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.logic.FunctionSupport;
+import net.shibboleth.utilities.java.support.service.ReloadableService;
+import net.shibboleth.utilities.java.support.service.ServiceableComponent;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/** {@link AttributeRevocationCondition} unit test. */
+public class AttributeRevocationConditionTest extends BaseAuthenticationContextTest {
+    
+    private Collection<Instant> revocationsToResolve;
+    
+    private AttributeRevocationCondition condition; 
+
+    @BeforeMethod
+    public void setUp() throws ComponentInitializationException {
+        super.setUp();
+        
+        condition = new AttributeRevocationCondition();
+        condition.setPrincipalNameLookupStrategy(FunctionSupport.constant("jdoe"));
+        condition.setAttributeResolver(new MockResolver());
+        condition.setAttributeId("revocation");
+        condition.initialize();
+        
+        authenticationFlows.get(1).setRevocationCondition(condition);
+    }
+    
+    @AfterMethod
+    public void tearDown() {
+        condition.destroy();
+    }
+    
+    
+    @Test public void testNotRevoked() {
+        final AuthenticationResult active = authenticationFlows.get(1).newAuthenticationResult(new Subject());
+        final AuthenticationContext authCtx = prc.getSubcontext(AuthenticationContext.class);
+        authCtx.setActiveResults(Arrays.asList(active));
+
+        Assert.assertTrue(active.test(prc));
+    }
+    
+    @Test public void testRevoked() {
+        final AuthenticationResult active = authenticationFlows.get(1).newAuthenticationResult(new Subject());
+        final AuthenticationContext authCtx = prc.getSubcontext(AuthenticationContext.class);
+        authCtx.setActiveResults(Arrays.asList(active));
+
+        revocationsToResolve = Collections.singletonList(Instant.now().plusSeconds(3600));
+        
+        Assert.assertFalse(active.test(prc));
+    }
+
+    @Test public void testPastRevoked() {
+        final AuthenticationResult active = authenticationFlows.get(1).newAuthenticationResult(new Subject());
+        final AuthenticationContext authCtx = prc.getSubcontext(AuthenticationContext.class);
+        authCtx.setActiveResults(Arrays.asList(active));
+
+        revocationsToResolve = Collections.singletonList(Instant.now().minusSeconds(3600));
+        
+        Assert.assertTrue(active.test(prc));
+    }
+
+    /**
+     * Mock attribute source.
+     */
+    private class MockResolver implements ReloadableService<AttributeResolver> {
+
+        /** {@inheritDoc} */
+        public boolean isInitialized() {
+            return true;
+        }
+
+        /** {@inheritDoc} */
+        public void initialize() throws ComponentInitializationException {            
+        }
+
+        /** {@inheritDoc} */
+        public Instant getLastSuccessfulReloadInstant() {
+            return null;
+        }
+
+        /** {@inheritDoc} */
+        public Instant getLastReloadAttemptInstant() {
+            return null;
+        }
+
+        /** {@inheritDoc} */
+        public Throwable getReloadFailureCause() {
+            return null;
+        }
+
+        /** {@inheritDoc} */
+        public void reload() {
+        }
+
+        /** {@inheritDoc} */
+        public ServiceableComponent<AttributeResolver> getServiceableComponent() {
+            return new ServiceableComponent<AttributeResolver>() {
+
+                public AttributeResolver getComponent() {
+                    return new AttributeResolver() {
+
+                        public String getId() {
+                            return "test";
+                        }
+
+                        public void resolveAttributes(AttributeResolutionContext resolutionContext)
+                                throws ResolutionException {
+                            if ("jdoe".equals(resolutionContext.getPrincipal()) && revocationsToResolve != null) {
+                                final IdPAttribute attr = new IdPAttribute("revocation");
+                                attr.setValues(
+                                        revocationsToResolve.stream()
+                                            .map(i -> StringAttributeValue.valueOf(Long.toString(i.getEpochSecond())))
+                                            .collect(Collectors.toUnmodifiableList())
+                                        );
+                                resolutionContext.setResolvedIdPAttributes(Collections.singletonList(attr));
+                            }
+                        }
+                    };
+                }
+
+                public void pinComponent() {
+                }
+
+                public void unpinComponent() {
+                }
+
+                public void unloadComponent() {
+                }
+            };
+        }
+        
+    }
+    
+}
\ No newline at end of file
diff --git a/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/revocation/impl/RevocationCacheConditionTest.java b/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/revocation/impl/RevocationCacheConditionTest.java
index 9a1021526..f0eec367e 100644
--- a/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/revocation/impl/RevocationCacheConditionTest.java
+++ b/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/revocation/impl/RevocationCacheConditionTest.java
@@ -18,6 +18,7 @@
 package net.shibboleth.idp.authn.revocation.impl;
 
 import java.time.Duration;
+import java.time.Instant;
 import java.util.Arrays;
 
 import javax.security.auth.Subject;
@@ -28,7 +29,6 @@ import net.shibboleth.idp.authn.impl.testing.BaseAuthenticationContextTest;
 import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
 import net.shibboleth.utilities.java.support.logic.FunctionSupport;
 
-import org.joda.time.Instant;
 import org.opensaml.storage.RevocationCache;
 import org.opensaml.storage.impl.MemoryStorageService;
 import org.testng.Assert;
@@ -88,7 +88,7 @@ public class RevocationCacheConditionTest extends BaseAuthenticationContextTest
 
         revocationCache.revoke(RevocationCacheCondition.REVOCATION_CONTEXT,
                 RevocationCacheCondition.PRINCIPAL_REVOCATION_PREFIX + "jdoe",
-                Long.toString(Instant.now().getMillis() / 1000 + 3600L),
+                Long.toString(Instant.now().getEpochSecond() + 3600L),
                 Duration.ofDays(1));
         
         Assert.assertFalse(active.test(prc));
@@ -101,7 +101,7 @@ public class RevocationCacheConditionTest extends BaseAuthenticationContextTest
 
         revocationCache.revoke(RevocationCacheCondition.REVOCATION_CONTEXT,
                 RevocationCacheCondition.PRINCIPAL_REVOCATION_PREFIX + "jdoe",
-                Long.toString(Instant.now().getMillis() / 1000 - 3600L),
+                Long.toString(Instant.now().getEpochSecond() - 3600L),
                 Duration.ofDays(1));
         
         Assert.assertTrue(active.test(prc));
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/conf/authn-system.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/conf/authn-system.xml
index ab7d82961..8746328d7 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/conf/authn-system.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/conf/authn-system.xml
@@ -28,7 +28,7 @@
             p:inactivityTimeout="%{idp.authn.defaultTimeout:PT30M}"
             p:principalWeightMap="#{getObject('shibboleth.AuthenticationPrincipalWeightMap') ?: getObject('shibboleth.DefaultAuthenticationPrincipalWeightMap')}"
             p:principalServiceManager-ref="shibboleth.PrincipalServiceManager"
-            p:revocationCondition="#{%{idp.authn.revocation:false} ? getObject('%{idp.authn.revocation.Condition:shibboleth.RevocationCondition}'.trim()) : null}">
+            p:revocationCondition="#{%{idp.authn.revocation:false} ? getObject('%{idp.authn.revocation.Condition:shibboleth.RevocationCacheCondition}'.trim()) : null}">
         <property name="supportedPrincipals">
             <list>
                 <bean parent="shibboleth.SAML2AuthnContextClassRef"
@@ -536,10 +536,15 @@
     
     <!-- Revocation feature. -->
     
-    <bean id="shibboleth.RevocationCondition" class="net.shibboleth.idp.authn.revocation.impl.RevocationCacheCondition" lazy-init="true"
+    <bean id="shibboleth.RevocationCacheCondition" class="net.shibboleth.idp.authn.revocation.impl.RevocationCacheCondition" lazy-init="true"
         p:revocationCache-ref="%{idp.authn.revocation.cache:shibboleth.AuthnRevocationCache}"
         p:httpServletRequest="#{%{idp.authn.revocation.addressBased:false} ? getObject('shibboleth.HttpServletRequest') : null}"
         p:principalNameLookupStrategy-ref="shibboleth.RevocationPrincipalLookupStrategy" />
+
+    <bean id="shibboleth.AttributeRevocationCondition" class="net.shibboleth.idp.authn.revocation.impl.AttributeRevocationCondition" lazy-init="true"
+        p:principalNameLookupStrategy-ref="shibboleth.RevocationPrincipalLookupStrategy"
+        p:attributeResolver-ref="shibboleth.AttributeResolverService"
+        p:attributeId="#{'%{idp.authn.revocation.attributeId:revocation}'.trim()}" />
         
     <bean id="shibboleth.RevocationPrincipalLookupStrategy" parent="shibboleth.Functions.Compose" lazy-init="true"
         c:g-ref="shibboleth.PrincipalNameLookup.Session"
diff --git a/idp-conf/src/main/resources/conf/authn/authn.properties b/idp-conf/src/main/resources/conf/authn/authn.properties
index 86de8ee7f..af2fdbc66 100644
--- a/idp-conf/src/main/resources/conf/authn/authn.properties
+++ b/idp-conf/src/main/resources/conf/authn/authn.properties
@@ -28,7 +28,7 @@
 #idp.authn.revocation = false
 #idp.authn.revocation.lifetime = %{idp.authn.defaultAuthnLifetime:PT12H}
 # Name of BiCondition to apply for check
-#idp.authn.revocation.Condition = shibboleth.RevocationCondition
+#idp.authn.revocation.Condition = shibboleth.RevocationCacheCondition
 # Set to true to treat lookup failures as being revoked.
 #idp.authn.revocation.strict = false
 # Set to true to check for address-based revocation.

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


More information about the commits mailing list