[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