[java-identity-provider] branch master updated: IDP-1318 - Provide way to set forceAuthn on an RP from the IdP side

Scott Cantor cantor.2 at osu.edu
Fri Sep 7 14:23:03 EDT 2018


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

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

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

The following commit(s) were added to refs/heads/master by this push:
       new  eb41cc9   IDP-1318 - Provide way to set forceAuthn on an RP from the IdP side
eb41cc9 is described below

commit eb41cc9e7cda5dfd85f7203a837ef538ae025448
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Fri Sep 7 14:23:00 2018 -0400

    IDP-1318 - Provide way to set forceAuthn on an RP from the IdP side
    
    https://issues.shibboleth.net/jira/browse/IDP-1318
---
 .../idp/cas/config/impl/LoginConfiguration.java    | 40 ++++++++++++++-
 .../impl/BuildAuthenticationContextAction.java     | 11 ++++
 .../system/conf/relying-party-mddriven.xml         | 24 +++++++++
 .../logic/ForceAuthnProfileConfigPredicate.java    | 58 ++++++++++++++++++++++
 .../config/BrowserSSOProfileConfiguration.java     | 38 ++++++++++++++
 .../config/BrowserSSOProfileConfiguration.java     | 37 ++++++++++++++
 .../impl/InitializeAuthenticationContext.java      | 27 +++++++++-
 7 files changed, 232 insertions(+), 3 deletions(-)

diff --git a/idp-cas-impl/src/main/java/net/shibboleth/idp/cas/config/impl/LoginConfiguration.java b/idp-cas-impl/src/main/java/net/shibboleth/idp/cas/config/impl/LoginConfiguration.java
index 3314e71..a2137bb 100644
--- a/idp-cas-impl/src/main/java/net/shibboleth/idp/cas/config/impl/LoginConfiguration.java
+++ b/idp-cas-impl/src/main/java/net/shibboleth/idp/cas/config/impl/LoginConfiguration.java
@@ -31,6 +31,7 @@ import javax.annotation.Nullable;
 import org.opensaml.profile.context.ProfileRequestContext;
 
 import com.google.common.base.Function;
+import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.ImmutableList;
@@ -86,7 +87,10 @@ public class LoginConfiguration extends AbstractProtocolConfiguration
 
     /** Precedence of name identifier formats to use for requests. */
     @Nonnull @NonnullElements private List<String> nameIDFormatPrecedence;
-
+    
+    /** Whether to mandate forced authentication for the request. */
+    @Nonnull private Predicate<ProfileRequestContext> forceAuthnPredicate;
+    
     /** Creates a new instance. */
     public LoginConfiguration() {
         super(PROFILE_ID);
@@ -225,6 +229,40 @@ public class LoginConfiguration extends AbstractProtocolConfiguration
         nameIDFormatPrecedenceLookupStrategy = strategy;
     }
 
+    /**
+     * Get a condition to determine whether a fresh user presence proof should be required for this request.
+     * 
+     * @return condition
+     * 
+     * @since 3.4.0
+     */
+    @Nonnull public Predicate<ProfileRequestContext> getForceAuthnPredicate() {
+        return forceAuthnPredicate;
+    }
+    
+    /**
+     * Set a condition to determine whether a fresh user presence proof should be required for this request.
+     * 
+     * @param condition condition to set
+     * 
+     * @since 3.4.0
+     */
+    public void setForceAuthnPredicate(@Nonnull final Predicate<ProfileRequestContext> condition) {
+        forceAuthnPredicate = Constraint.isNotNull(condition, "Forced authentication predicate cannot be null");
+    }
+    
+    /**
+     * Set whether a fresh user presence proof should be required for this request.
+     * 
+     * @param flag flag to set
+     * 
+     * @since 3.4.0
+     */
+    public void setForceAuthn(final boolean flag) {
+        forceAuthnPredicate = flag ? Predicates.<ProfileRequestContext>alwaysTrue()
+                : Predicates.<ProfileRequestContext>alwaysFalse();
+    }
+    
     /** {@inheritDoc} */
     @Override
     @Nonnull @NotEmpty protected String getDefaultTicketPrefix() {
diff --git a/idp-cas-impl/src/main/java/net/shibboleth/idp/cas/flow/impl/BuildAuthenticationContextAction.java b/idp-cas-impl/src/main/java/net/shibboleth/idp/cas/flow/impl/BuildAuthenticationContextAction.java
index 325e5c5..277031f 100644
--- a/idp-cas-impl/src/main/java/net/shibboleth/idp/cas/flow/impl/BuildAuthenticationContextAction.java
+++ b/idp-cas-impl/src/main/java/net/shibboleth/idp/cas/flow/impl/BuildAuthenticationContextAction.java
@@ -21,6 +21,8 @@ import javax.annotation.Nonnull;
 
 import net.shibboleth.idp.authn.AuthenticationResult;
 import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.idp.cas.config.impl.ConfigLookupFunction;
+import net.shibboleth.idp.cas.config.impl.LoginConfiguration;
 import net.shibboleth.idp.cas.protocol.ServiceTicketRequest;
 import net.shibboleth.idp.cas.protocol.ServiceTicketResponse;
 
@@ -40,6 +42,10 @@ import org.springframework.webflow.execution.RequestContext;
 public class BuildAuthenticationContextAction extends
         AbstractCASProtocolAction<ServiceTicketRequest, ServiceTicketResponse> {
 
+    /** Profile configuration lookup function. */
+    private final ConfigLookupFunction<LoginConfiguration> configLookupFunction =
+            new ConfigLookupFunction<>(LoginConfiguration.class);
+
     @Nonnull
     @Override
     protected Event doExecute(@Nonnull final RequestContext springRequestContext,
@@ -49,6 +55,11 @@ public class BuildAuthenticationContextAction extends
         ac.setForceAuthn(getCASRequest(profileRequestContext).isRenew());
         ac.setIsPassive(false);
 
+        final LoginConfiguration config = configLookupFunction.apply(profileRequestContext);
+        if (config != null) {
+            ac.setForceAuthn(config.getForceAuthnPredicate().apply(profileRequestContext));
+        }
+        
         final AuthenticationContext initialAuthnContext =
                 profileRequestContext.getSubcontext(AuthenticationContext.class);
         if (initialAuthnContext != null) {
diff --git a/idp-conf/src/main/resources/system/conf/relying-party-mddriven.xml b/idp-conf/src/main/resources/system/conf/relying-party-mddriven.xml
index 2c0b6b1..034c10b 100644
--- a/idp-conf/src/main/resources/system/conf/relying-party-mddriven.xml
+++ b/idp-conf/src/main/resources/system/conf/relying-party-mddriven.xml
@@ -229,6 +229,14 @@
                 <constructor-arg value="false" />
             </bean>
         </property>
+        <property name="forceAuthnPredicate">
+            <bean class="net.shibboleth.utilities.java.support.logic.PredicateSupport" factory-method="fromFunction">
+                <constructor-arg>
+                    <bean parent="shibboleth.MDDrivenBoolProperty" p:propertyName="forceAuthn" />
+                </constructor-arg>
+                <constructor-arg value="false" />
+            </bean>
+        </property>
         <property name="defaultAuthenticationMethodsLookupStrategy">
             <bean parent="shibboleth.MDDrivenListProperty" p:propertyName="defaultAuthenticationMethods"
                 p:propertyType="#{T(net.shibboleth.idp.saml.authn.principal.AuthenticationMethodPrincipal)}" />
@@ -307,6 +315,14 @@
                 <constructor-arg value="true" />
             </bean>
         </property>
+        <property name="forceAuthnPredicate">
+            <bean class="net.shibboleth.utilities.java.support.logic.PredicateSupport" factory-method="fromFunction">
+                <constructor-arg>
+                    <bean parent="shibboleth.MDDrivenBoolProperty" p:propertyName="forceAuthn" />
+                </constructor-arg>
+                <constructor-arg value="false" />
+            </bean>
+        </property>
         <property name="skipEndpointValidationWhenSignedPredicate">
             <bean class="net.shibboleth.utilities.java.support.logic.PredicateSupport" factory-method="fromFunction">
                 <constructor-arg>
@@ -463,6 +479,14 @@
         <property name="nameIDFormatPrecedenceLookupStrategy">
             <bean parent="shibboleth.MDDrivenListProperty" p:propertyName="nameIDFormatPrecedence" />
         </property>
+        <property name="forceAuthnPredicate">
+            <bean class="net.shibboleth.utilities.java.support.logic.PredicateSupport" factory-method="fromFunction">
+                <constructor-arg>
+                    <bean parent="shibboleth.MDDrivenBoolProperty" p:propertyName="forceAuthn" />
+                </constructor-arg>
+                <constructor-arg value="false" />
+            </bean>
+        </property>
     </bean>
 
     <bean id="CAS.ProxyConfiguration.MDDriven" parent="AbstractMDDrivenCASProfile" lazy-init="true"
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/profile/config/logic/ForceAuthnProfileConfigPredicate.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/profile/config/logic/ForceAuthnProfileConfigPredicate.java
new file mode 100644
index 0000000..b753c2e
--- /dev/null
+++ b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/profile/config/logic/ForceAuthnProfileConfigPredicate.java
@@ -0,0 +1,58 @@
+/*
+ * 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.saml.profile.config.logic;
+
+import javax.annotation.Nullable;
+
+import net.shibboleth.idp.profile.context.RelyingPartyContext;
+import net.shibboleth.idp.profile.logic.AbstractRelyingPartyPredicate;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+/**
+ * A predicate that evaluates a {@link ProfileRequestContext} and determines whether forced
+ * authentication should be set.
+ * 
+ * <p>For SAML 1 and SAML 2 SSO profiles, the "forceAuthn" flag is the setting governing
+ * this decision. For other profiles, false is returned.</p> 
+ * 
+ * @since 3.4.0
+ */
+public class ForceAuthnProfileConfigPredicate extends AbstractRelyingPartyPredicate {
+    
+    /** {@inheritDoc} */
+    @Override
+    public boolean apply(@Nullable final ProfileRequestContext input) {
+        
+        final RelyingPartyContext rpc = getRelyingPartyContextLookupStrategy().apply(input);
+        if (rpc != null) {
+            if (rpc.getProfileConfig()
+                    instanceof net.shibboleth.idp.saml.saml1.profile.config.BrowserSSOProfileConfiguration) {
+                return ((net.shibboleth.idp.saml.saml1.profile.config.BrowserSSOProfileConfiguration)
+                        rpc.getProfileConfig()).getForceAuthnPredicate().apply(input);
+            } else if (rpc.getProfileConfig()
+                    instanceof net.shibboleth.idp.saml.saml2.profile.config.BrowserSSOProfileConfiguration) {
+                return ((net.shibboleth.idp.saml.saml2.profile.config.BrowserSSOProfileConfiguration)
+                        rpc.getProfileConfig()).getForceAuthnPredicate().apply(input);
+            }
+        }
+        
+        return false;
+    }
+
+}
\ No newline at end of file
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/saml1/profile/config/BrowserSSOProfileConfiguration.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/saml1/profile/config/BrowserSSOProfileConfiguration.java
index 200d37b..6474863 100644
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/saml1/profile/config/BrowserSSOProfileConfiguration.java
+++ b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/saml1/profile/config/BrowserSSOProfileConfiguration.java
@@ -59,6 +59,9 @@ public class BrowserSSOProfileConfiguration extends AbstractSAML1ArtifactAwarePr
 
     /** Whether responses to the authentication request should include an attribute statement. */
     @Nonnull private Predicate<ProfileRequestContext> includeAttributeStatementPredicate;
+    
+    /** Whether to mandate forced authentication for the request. */
+    @Nonnull private Predicate<ProfileRequestContext> forceAuthnPredicate;
 
     /** Lookup function to supply {@link #defaultAuthenticationMethods} property. */
     @Nullable private Function<ProfileRequestContext,Collection<AuthenticationMethodPrincipal>>
@@ -100,6 +103,7 @@ public class BrowserSSOProfileConfiguration extends AbstractSAML1ArtifactAwarePr
         setSignResponses(Predicates.<ProfileRequestContext>alwaysTrue());
         resolveAttributesPredicate = Predicates.alwaysTrue();
         includeAttributeStatementPredicate = Predicates.alwaysFalse();
+        forceAuthnPredicate = Predicates.alwaysFalse();
         defaultAuthenticationMethods = Collections.emptyList();
         authenticationFlows = Collections.emptySet();
         postAuthenticationFlows = Collections.emptyList();
@@ -198,6 +202,40 @@ public class BrowserSSOProfileConfiguration extends AbstractSAML1ArtifactAwarePr
         includeAttributeStatementPredicate = Constraint.isNotNull(condition,
                 "Include attribute statement predicate cannot be null");
     }
+    
+    /**
+     * Get a condition to determine whether a fresh user presence proof should be required for this request.
+     * 
+     * @return condition
+     * 
+     * @since 3.4.0
+     */
+    @Nonnull public Predicate<ProfileRequestContext> getForceAuthnPredicate() {
+        return forceAuthnPredicate;
+    }
+    
+    /**
+     * Set a condition to determine whether a fresh user presence proof should be required for this request.
+     * 
+     * @param condition condition to set
+     * 
+     * @since 3.4.0
+     */
+    public void setForceAuthnPredicate(@Nonnull final Predicate<ProfileRequestContext> condition) {
+        forceAuthnPredicate = Constraint.isNotNull(condition, "Forced authentication predicate cannot be null");
+    }
+    
+    /**
+     * Set whether a fresh user presence proof should be required for this request.
+     * 
+     * @param flag flag to set
+     * 
+     * @since 3.4.0
+     */
+    public void setForceAuthn(final boolean flag) {
+        forceAuthnPredicate = flag ? Predicates.<ProfileRequestContext>alwaysTrue()
+                : Predicates.<ProfileRequestContext>alwaysFalse();
+    }
 
     /** {@inheritDoc} */
     @Override
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/BrowserSSOProfileConfiguration.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/BrowserSSOProfileConfiguration.java
index 242f7d2..257dff9 100644
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/BrowserSSOProfileConfiguration.java
+++ b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/BrowserSSOProfileConfiguration.java
@@ -64,6 +64,9 @@ public class BrowserSSOProfileConfiguration extends AbstractSAML2ArtifactAwarePr
     /** Whether responses to the authentication request should include an attribute statement. */
     @Nonnull private Predicate<ProfileRequestContext> includeAttributeStatementPredicate;
 
+    /** Whether to mandate forced authentication for the request. */
+    @Nonnull private Predicate<ProfileRequestContext> forceAuthnPredicate;
+    
     /** Whether the response endpoint should be validated if the request is signed. */
     @Nonnull private Predicate<ProfileRequestContext> skipEndpointValidationWhenSignedPredicate;
 
@@ -234,6 +237,40 @@ public class BrowserSSOProfileConfiguration extends AbstractSAML2ArtifactAwarePr
     }
 
     /**
+     * Get a condition to determine whether a fresh user presence proof should be required for this request.
+     * 
+     * @return condition
+     * 
+     * @since 3.4.0
+     */
+    @Nonnull public Predicate<ProfileRequestContext> getForceAuthnPredicate() {
+        return forceAuthnPredicate;
+    }
+    
+    /**
+     * Set a condition to determine whether a fresh user presence proof should be required for this request.
+     * 
+     * @param condition condition to set
+     * 
+     * @since 3.4.0
+     */
+    public void setForceAuthnPredicate(@Nonnull final Predicate<ProfileRequestContext> condition) {
+        forceAuthnPredicate = Constraint.isNotNull(condition, "Forced authentication predicate cannot be null");
+    }
+    
+    /**
+     * Set whether a fresh user presence proof should be required for this request.
+     * 
+     * @param flag flag to set
+     * 
+     * @since 3.4.0
+     */
+    public void setForceAuthn(final boolean flag) {
+        forceAuthnPredicate = flag ? Predicates.<ProfileRequestContext>alwaysTrue()
+                : Predicates.<ProfileRequestContext>alwaysFalse();
+    }
+    
+    /**
      * Get whether the response endpoint should be validated if the request is signed.
      * 
      * @return whether the response endpoint should be validated if the request is signed
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/InitializeAuthenticationContext.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/InitializeAuthenticationContext.java
index b624c5d..9109182 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/InitializeAuthenticationContext.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/InitializeAuthenticationContext.java
@@ -22,6 +22,7 @@ import javax.annotation.Nullable;
 
 import net.shibboleth.idp.authn.context.AuthenticationContext;
 import net.shibboleth.idp.profile.AbstractProfileAction;
+import net.shibboleth.idp.saml.profile.config.logic.ForceAuthnProfileConfigPredicate;
 import net.shibboleth.utilities.java.support.component.ComponentSupport;
 import net.shibboleth.utilities.java.support.logic.Constraint;
 
@@ -34,6 +35,7 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Function;
 import com.google.common.base.Functions;
+import com.google.common.base.Predicate;
 
 /**
  * An action that creates an {@link AuthenticationContext} and attaches it to the current {@link ProfileRequestContext}.
@@ -46,7 +48,7 @@ import com.google.common.base.Functions;
  * {@link AuthenticationContext#setInitialAuthenticationResult(net.shibboleth.idp.authn.AuthenticationResult)}.</p>
  * 
  * @event {@link org.opensaml.profile.action.EventIds#PROCEED_EVENT_ID}
- * @post ProfileRequestContext.getSubcontext(AuthenticationContext.class, false) != true
+ * @post ProfileRequestContext.getSubcontext(AuthenticationContext.class) != true
  * @post SAML 2.0 AuthnRequest policy flags are copied to the {@link AuthenticationContext}
  */
 public class InitializeAuthenticationContext extends AbstractProfileAction {
@@ -54,6 +56,9 @@ public class InitializeAuthenticationContext extends AbstractProfileAction {
     /** Class logger. */
     @Nonnull private final Logger log = LoggerFactory.getLogger(InitializeAuthenticationContext.class);
 
+    /** Extracts forceAuthn property from profile config. */
+    @Nonnull private Predicate<ProfileRequestContext> forceAuthnPredicate;
+    
     /** Strategy used to locate the {@link AuthnRequest} to operate on, if any. */
     @Nonnull private Function<ProfileRequestContext,AuthnRequest> requestLookupStrategy;
     
@@ -62,11 +67,25 @@ public class InitializeAuthenticationContext extends AbstractProfileAction {
 
     /** Constructor. */
     public InitializeAuthenticationContext() {
+        forceAuthnPredicate = new ForceAuthnProfileConfigPredicate();
         requestLookupStrategy =
                 Functions.compose(new MessageLookup<>(AuthnRequest.class), new InboundMessageContextLookup());
     }
     
     /**
+     * Set the predicate to apply to derive the message-independent forced authn default. 
+     * 
+     * @param condition condition to set
+     * 
+     * @since 3.4.0
+     */
+    public void setForceAuthnPredicate(@Nonnull final Predicate<ProfileRequestContext> condition) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        
+        forceAuthnPredicate = Constraint.isNotNull(condition, "Forced authentication predicate cannot be null");
+    }
+    
+    /**
      * Set the strategy used to locate the {@link AuthnRequest} to examine, if any.
      * 
      * @param strategy strategy used to locate the {@link AuthnRequest}
@@ -87,7 +106,7 @@ public class InitializeAuthenticationContext extends AbstractProfileAction {
         
         authnRequest = this.requestLookupStrategy.apply(profileRequestContext);
         if (authnRequest == null) {
-            log.debug("{} No inbound AuthnRequest, passive and forced flags will be off", getLogPrefix());
+            log.debug("{} No inbound AuthnRequest, passive flag will be off", getLogPrefix());
         }
         
         return true;
@@ -110,6 +129,10 @@ public class InitializeAuthenticationContext extends AbstractProfileAction {
             authnCtx.setInitialAuthenticationResult(initialAuthnContext.getAuthenticationResult());
         }
         
+        if (!authnCtx.isForceAuthn()) {
+            authnCtx.setForceAuthn(forceAuthnPredicate.apply(profileRequestContext));
+        }
+        
         profileRequestContext.addSubcontext(authnCtx, true);
 
         log.debug("{} Created authentication context: {}", getLogPrefix(), authnCtx);

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


More information about the commits mailing list