[java-identity-provider] branch master updated: IDP-1494 - Login flow for proxied SAML authentication
Scott Cantor
cantor.2 at osu.edu
Wed Nov 27 10:14:15 EST 2019
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=f093b5b8d22ff92c9e7bd48e1944f91c8bebef2d
The following commit(s) were added to refs/heads/master by this push:
new f093b5b IDP-1494 - Login flow for proxied SAML authentication
f093b5b is described below
commit f093b5b8d22ff92c9e7bd48e1944f91c8bebef2d
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Wed Nov 27 10:14:09 2019 -0500
IDP-1494 - Login flow for proxied SAML authentication
https://issues.shibboleth.net/jira/browse/IDP-1494
Add in processing of Scoping element.
Add cross-protocol proxy count config control.
Add option to ignore request content for compatibility.
Rename some new properties for consistency.
Some misc. test changes.
---
.../admin/BasicAdministrativeFlowDescriptor.java | 48 ++++++-
.../config/AuthenticationProfileConfiguration.java | 14 ++
.../idp/authn/context/AuthenticationContext.java | 55 +++++++-
.../MockAuthenticationProfileConfiguration.java | 22 +++
.../authn/impl/BaseAuthenticationContextTest.java | 8 +-
.../idp/cas/config/impl/LoginConfiguration.java | 44 +++++-
.../impl/BuildAuthenticationContextAction.java | 7 +-
idp-conf/src/main/resources/conf/errors.xml | 1 +
.../system/conf/relying-party-mddriven.xml | 6 +
.../resources/system/conf/relying-party-system.xml | 3 +
.../system/flows/authn/proxy/saml-proxy-beans.xml | 2 +-
.../system/flows/saml/saml-abstract-beans.xml | 5 +-
.../config/BrowserSSOProfileConfiguration.java | 44 +++++-
.../config/BrowserSSOProfileConfiguration.java | 3 +
.../config/navigate/ProxyCountLookupFunction.java | 52 +++++++
.../impl/InitializeAuthenticationContext.java | 153 ++++++++++++++++++++-
.../saml/saml2/profile/impl/AddAuthnRequest.java | 6 +-
.../profile/impl/ProcessRequestedAuthnContext.java | 6 +-
.../impl/SAML2StringAttributeTranscoderTest.java | 9 +-
.../SAML2XMLObjectAttributeTranscoderTest.java | 35 +++--
.../impl/InitializeAuthenticationContextTest.java | 147 ++++++++++++++++----
.../impl/ProcessRequestedAuthnContextTest.java | 3 +-
22 files changed, 591 insertions(+), 82 deletions(-)
diff --git a/idp-admin-api/src/main/java/net/shibboleth/idp/admin/BasicAdministrativeFlowDescriptor.java b/idp-admin-api/src/main/java/net/shibboleth/idp/admin/BasicAdministrativeFlowDescriptor.java
index 5974034..8263296 100644
--- a/idp-admin-api/src/main/java/net/shibboleth/idp/admin/BasicAdministrativeFlowDescriptor.java
+++ b/idp-admin-api/src/main/java/net/shibboleth/idp/admin/BasicAdministrativeFlowDescriptor.java
@@ -31,6 +31,7 @@ import javax.annotation.Nullable;
import net.shibboleth.idp.profile.config.AbstractProfileConfiguration;
import net.shibboleth.idp.profile.config.SecurityConfiguration;
import net.shibboleth.utilities.java.support.annotation.ParameterName;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonNegative;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
import net.shibboleth.utilities.java.support.annotation.constraint.NotLive;
@@ -99,6 +100,9 @@ public class BasicAdministrativeFlowDescriptor extends AbstractProfileConfigurat
/** Whether to mandate forced authentication for the request. */
@Nonnull private Predicate<ProfileRequestContext> forceAuthnPredicate;
+ /** Lookup function to supply proxyCount property. */
+ @Nonnull private Function<ProfileRequestContext,Integer> proxyCountLookupStrategy;
+
/** Builder factory for XMLObjects needed in UIInfo emulation. */
@Nonnull private final XMLObjectBuilderFactory builderFactory;
@@ -123,6 +127,7 @@ public class BasicAdministrativeFlowDescriptor extends AbstractProfileConfigurat
defaultAuthenticationMethodsLookupStrategy = FunctionSupport.constant(null);
authenticationFlowsLookupStrategy = FunctionSupport.constant(null);
postAuthenticationFlowsLookupStrategy = FunctionSupport.constant(null);
+ proxyCountLookupStrategy = FunctionSupport.constant(null);
}
/** {@inheritDoc} */
@@ -237,7 +242,7 @@ public class BasicAdministrativeFlowDescriptor extends AbstractProfileConfigurat
((SAMLObjectBuilder<org.opensaml.saml.ext.saml2mdui.Logo>)
builderFactory.<org.opensaml.saml.ext.saml2mdui.Logo>getBuilderOrThrow(
org.opensaml.saml.ext.saml2mdui.Logo.DEFAULT_ELEMENT_NAME)).buildObject();
- logo.setURL(src.getValue());
+ logo.setURI(src.getValue());
logo.setXMLLang(src.getLang());
logo.setHeight(src.getHeight());
logo.setWidth(src.getWidth());
@@ -256,7 +261,7 @@ public class BasicAdministrativeFlowDescriptor extends AbstractProfileConfigurat
final InformationURL url =
((SAMLObjectBuilder<InformationURL>) builderFactory.<InformationURL>getBuilderOrThrow(
InformationURL.DEFAULT_ELEMENT_NAME)).buildObject();
- url.setValue(s.getValue());
+ url.setURI(s.getValue());
url.setXMLLang(s.getLang());
uiInfo.getInformationURLs().add(url);
}
@@ -273,7 +278,7 @@ public class BasicAdministrativeFlowDescriptor extends AbstractProfileConfigurat
final PrivacyStatementURL url =
((SAMLObjectBuilder<PrivacyStatementURL>) builderFactory.<PrivacyStatementURL>getBuilderOrThrow(
PrivacyStatementURL.DEFAULT_ELEMENT_NAME)).buildObject();
- url.setValue(s.getValue());
+ url.setURI(s.getValue());
url.setXMLLang(s.getLang());
uiInfo.getPrivacyStatementURLs().add(url);
}
@@ -477,6 +482,43 @@ public class BasicAdministrativeFlowDescriptor extends AbstractProfileConfigurat
}
/** {@inheritDoc} */
+ @Nullable public Integer getProxyCount(@Nullable final ProfileRequestContext profileRequestContext) {
+ final Integer count = proxyCountLookupStrategy.apply(profileRequestContext);
+ if (count != null) {
+ Constraint.isGreaterThanOrEqual(0, count, "Proxy count must be greater than or equal to 0");
+ }
+ return count;
+ }
+
+ /**
+ * Sets the maximum number of times an assertion may be proxied outbound and/or
+ * the maximum number of hops between the relying party and a proxied authentication
+ * authority inbound.
+ *
+ * @param count proxy count
+ *
+ * @since 4.0.0
+ */
+ public void setProxyCount(@Nullable @NonNegative final Integer count) {
+ if (count != null) {
+ Constraint.isGreaterThanOrEqual(0, count, "Proxy count must be greater than or equal to 0");
+ }
+ proxyCountLookupStrategy = FunctionSupport.constant(count);
+ }
+
+ /**
+ * Set a lookup strategy for the maximum number of times an assertion may be proxied outbound and/or
+ * the maximum number of hops between the relying party and a proxied authentication authority inbound.
+ *
+ * @param strategy lookup strategy
+ *
+ * @since 4.0.0
+ */
+ public void setProxyCountLookupStrategy(@Nonnull final Function<ProfileRequestContext,Integer> strategy) {
+ proxyCountLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
+ }
+
+ /** {@inheritDoc} */
@Override public int hashCode() {
return getId().hashCode();
}
diff --git a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/config/AuthenticationProfileConfiguration.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/config/AuthenticationProfileConfiguration.java
index 4ee4f91..2187fe9 100644
--- a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/config/AuthenticationProfileConfiguration.java
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/config/AuthenticationProfileConfiguration.java
@@ -27,6 +27,7 @@ import javax.annotation.Nullable;
import org.opensaml.profile.context.ProfileRequestContext;
import net.shibboleth.idp.profile.config.ProfileConfiguration;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonNegative;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
import net.shibboleth.utilities.java.support.annotation.constraint.NotLive;
import net.shibboleth.utilities.java.support.annotation.constraint.Unmodifiable;
@@ -94,6 +95,19 @@ public interface AuthenticationProfileConfiguration extends ProfileConfiguration
boolean isForceAuthn(@Nullable final ProfileRequestContext profileRequestContext);
/**
+ * Gets the maximum number of times an assertion may be proxied outbound and/or
+ * the maximum number of hops between the relying party and a proxied authentication
+ * authority inbound.
+ *
+ * @param profileRequestContext current profile request context
+ *
+ * @return maximum number of times an assertion or authentication may be proxied
+ *
+ * @since 4.0.0
+ */
+ @NonNegative @Nullable Integer getProxyCount(@Nullable final ProfileRequestContext profileRequestContext);
+
+ /**
* Get whether this profile is for functionality local to the IdP.
*
* <p>Most authentication profiles are non-local, designed to issue security tokens to other
diff --git a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/AuthenticationContext.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/AuthenticationContext.java
index fc9abd1..f0aa6cb 100644
--- a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/AuthenticationContext.java
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/AuthenticationContext.java
@@ -25,9 +25,11 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -41,6 +43,7 @@ import net.shibboleth.idp.authn.principal.PrincipalSupportingComponent;
import net.shibboleth.idp.authn.principal.ProxyAuthenticationPrincipal;
import net.shibboleth.idp.profile.context.RelyingPartyContext;
import net.shibboleth.utilities.java.support.annotation.constraint.Live;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonNegative;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
import net.shibboleth.utilities.java.support.logic.Constraint;
@@ -83,7 +86,13 @@ public final class AuthenticationContext extends BaseContext {
/** Name of a proxied authentication source to use. */
@Nullable private String authenticatingAuthority;
+
+ /** Allowable proxy count upstream. */
+ @Nullable @NonNegative private Integer proxyCount;
+ /** Allowable proxied sources of authority. */
+ @Nullable @NonnullElements private Set<String> proxiableAuthorities;
+
/** Lookup strategy for a fixed event to return from validators for testing. */
@Nullable private Function<ProfileRequestContext,String> fixedEventLookupStrategy;
@@ -132,6 +141,8 @@ public final class AuthenticationContext extends BaseContext {
stateMap = new HashMap<>();
resultCacheable = true;
+
+ proxiableAuthorities = new HashSet<>();
}
/**
@@ -359,7 +370,6 @@ public final class AuthenticationContext extends BaseContext {
* @since 3.4.0
*/
@Nonnull public AuthenticationContext setMaxAge(@Nullable final Duration age) {
-
Constraint.isFalse(age != null && (age.isNegative() || age.isZero()), "MaxAge must be null or greater than 0");
maxAge = age;
@@ -397,6 +407,49 @@ public final class AuthenticationContext extends BaseContext {
}
/**
+ * Get the allowable number of hops upstream to permit for proxied authentication.
+ *
+ * <p>This follows SAML semantics, but is not strictly specific to it.</p>
+ *
+ * @return proxy count, null for no limit, zero for no proxying
+ *
+ * @since 4.0.0
+ */
+ @Nullable @NonNegative public Integer getProxyCount() {
+ return proxyCount;
+ }
+
+ /**
+ * Set the allowable number of hops upstream to permit for proxied authentication.
+ *
+ * @param count proxy count, null for no limit, zero for no proxying
+ *
+ * @return this context
+ *
+ * @since 4.0.0
+ */
+ @Nonnull public AuthenticationContext setProxyCount(@Nullable @NonNegative final Integer count) {
+ if (count != null) {
+ Constraint.isGreaterThanOrEqual(0, count, "Proxy count cannot be negative");
+ }
+ proxyCount = count;
+ return this;
+ }
+
+ /**
+ * Get a live set of the authorities to which proxying is suggested.
+ *
+ * <p>This follows SAML semantics and is non-critical, but is not strictly specific to it.</p>
+ *
+ * @return advisory set of authorities
+ *
+ * @since 4.0.0
+ */
+ @Nonnull @NonnullElements @Live public Set<String> getProxiableAuthorities() {
+ return proxiableAuthorities;
+ }
+
+ /**
* Get optional lookup strategy to return a fixed event to return from credential validation
* to exercise error and warning logic.
*
diff --git a/idp-authn-api/src/test/java/net/shibboleth/idp/authn/config/MockAuthenticationProfileConfiguration.java b/idp-authn-api/src/test/java/net/shibboleth/idp/authn/config/MockAuthenticationProfileConfiguration.java
index 06c6361..a03d514 100644
--- a/idp-authn-api/src/test/java/net/shibboleth/idp/authn/config/MockAuthenticationProfileConfiguration.java
+++ b/idp-authn-api/src/test/java/net/shibboleth/idp/authn/config/MockAuthenticationProfileConfiguration.java
@@ -34,6 +34,7 @@ import com.google.common.base.Predicates;
import net.shibboleth.idp.authn.config.AuthenticationProfileConfiguration;
import net.shibboleth.idp.profile.config.AbstractProfileConfiguration;
import net.shibboleth.idp.profile.config.SecurityConfiguration;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonNegative;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
import net.shibboleth.utilities.java.support.annotation.constraint.NotLive;
@@ -60,6 +61,9 @@ public class MockAuthenticationProfileConfiguration extends AbstractProfileConfi
/** ForceAuthn predicate. */
@Nonnull private Predicate<ProfileRequestContext> forceAuthnPredicate;
+ /** Proxy count. */
+ @Nonnull private Integer proxyCount;
+
/**
* Constructor.
*
@@ -161,4 +165,22 @@ public class MockAuthenticationProfileConfiguration extends AbstractProfileConfi
return forceAuthnPredicate.test(profileRequestContext);
}
+ /** {@inheritDoc} */
+ @Nullable @NonNegative public Integer getProxyCount(@Nullable final ProfileRequestContext profileRequestContext) {
+ return proxyCount;
+ }
+
+ /**
+ * Set proxy count.
+ *
+ * @param count the count
+ */
+ public void setProxyCount(@Nullable @NonNegative final Integer count) {
+ if (count != null) {
+ proxyCount = Constraint.isGreaterThanOrEqual(0, count, "Proxy count cannot be negative");
+ } else {
+ proxyCount = null;
+ }
+ }
+
}
\ No newline at end of file
diff --git a/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/impl/BaseAuthenticationContextTest.java b/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/impl/BaseAuthenticationContextTest.java
index bc5f27f..9a09e09 100644
--- a/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/impl/BaseAuthenticationContextTest.java
+++ b/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/impl/BaseAuthenticationContextTest.java
@@ -22,25 +22,25 @@ import net.shibboleth.idp.authn.context.AuthenticationContext;
import net.shibboleth.idp.profile.RequestContextBuilder;
import net.shibboleth.idp.profile.context.navigate.WebflowRequestContextProfileRequestContextLookup;
+import java.util.List;
+
import org.opensaml.core.OpenSAMLInitBaseTestCase;
import org.opensaml.profile.context.ProfileRequestContext;
import org.springframework.webflow.execution.RequestContext;
-import com.google.common.collect.ImmutableList;
-
/** Base class for further action tests. */
public class BaseAuthenticationContextTest extends OpenSAMLInitBaseTestCase {
protected RequestContext src;
protected ProfileRequestContext prc;
- protected ImmutableList<AuthenticationFlowDescriptor> authenticationFlows;
+ protected List<AuthenticationFlowDescriptor> authenticationFlows;
protected void initializeMembers() throws Exception {
src = new RequestContextBuilder().buildRequestContext();
prc = new WebflowRequestContextProfileRequestContextLookup().apply(src);
prc.addSubcontext(new AuthenticationContext(), true);
- authenticationFlows = ImmutableList.of(new AuthenticationFlowDescriptor(),
+ authenticationFlows = List.of(new AuthenticationFlowDescriptor(),
new AuthenticationFlowDescriptor(), new AuthenticationFlowDescriptor());
authenticationFlows.get(0).setId("test1");
authenticationFlows.get(1).setId("test2");
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 ea5ee9d..850460f 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
@@ -34,6 +34,7 @@ import com.google.common.base.Predicates;
import net.shibboleth.idp.authn.config.AuthenticationProfileConfiguration;
import net.shibboleth.idp.saml.authn.principal.AuthnContextClassRefPrincipal;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonNegative;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
import net.shibboleth.utilities.java.support.annotation.constraint.NotLive;
@@ -76,6 +77,9 @@ public class LoginConfiguration extends AbstractProtocolConfiguration
/** Whether to mandate forced authentication for the request. */
@Nonnull private Predicate<ProfileRequestContext> forceAuthnPredicate;
+ /** Lookup function to supply proxyCount property. */
+ @Nonnull private Function<ProfileRequestContext,Integer> proxyCountLookupStrategy;
+
/** Creates a new instance. */
public LoginConfiguration() {
super(PROFILE_ID);
@@ -85,6 +89,7 @@ public class LoginConfiguration extends AbstractProtocolConfiguration
defaultAuthenticationContextsLookupStrategy = FunctionSupport.constant(null);
nameIDFormatPrecedenceLookupStrategy = FunctionSupport.constant(null);
forceAuthnPredicate = Predicates.alwaysFalse();
+ proxyCountLookupStrategy = FunctionSupport.constant(null);
}
/** {@inheritDoc} */
@@ -246,7 +251,44 @@ public class LoginConfiguration extends AbstractProtocolConfiguration
public void setForceAuthnPredicate(@Nonnull final Predicate<ProfileRequestContext> condition) {
forceAuthnPredicate = Constraint.isNotNull(condition, "Forced authentication predicate cannot be null");
}
-
+
+ /** {@inheritDoc} */
+ @Nullable public Integer getProxyCount(@Nullable final ProfileRequestContext profileRequestContext) {
+ final Integer count = proxyCountLookupStrategy.apply(profileRequestContext);
+ if (count != null) {
+ Constraint.isGreaterThanOrEqual(0, count, "Proxy count must be greater than or equal to 0");
+ }
+ return count;
+ }
+
+ /**
+ * Sets the maximum number of times an assertion may be proxied outbound and/or
+ * the maximum number of hops between the relying party and a proxied authentication
+ * authority inbound.
+ *
+ * @param count proxy count
+ *
+ * @since 4.0.0
+ */
+ public void setProxyCount(@Nullable @NonNegative final Integer count) {
+ if (count != null) {
+ Constraint.isGreaterThanOrEqual(0, count, "Proxy count must be greater than or equal to 0");
+ }
+ proxyCountLookupStrategy = FunctionSupport.constant(count);
+ }
+
+ /**
+ * Set a lookup strategy for the maximum number of times an assertion may be proxied outbound and/or
+ * the maximum number of hops between the relying party and a proxied authentication authority inbound.
+ *
+ * @param strategy lookup strategy
+ *
+ * @since 4.0.0
+ */
+ public void setProxyCountLookupStrategy(@Nonnull final Function<ProfileRequestContext,Integer> strategy) {
+ proxyCountLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
+ }
+
/** {@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 8028677..3e98888 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
@@ -72,13 +72,18 @@ public class BuildAuthenticationContextAction
ac.setForceAuthn(request.isRenew());
ac.setIsPassive(false);
+ final LoginConfiguration config = configLookupFunction.apply(profileRequestContext);
+
if (!ac.isForceAuthn()) {
- final LoginConfiguration config = configLookupFunction.apply(profileRequestContext);
if (config != null) {
ac.setForceAuthn(config.isForceAuthn(profileRequestContext));
}
}
+ if (config != null) {
+ ac.setProxyCount(config.getProxyCount(profileRequestContext));
+ }
+
profileRequestContext.addSubcontext(ac, true);
profileRequestContext.setBrowserProfile(true);
}
diff --git a/idp-conf/src/main/resources/conf/errors.xml b/idp-conf/src/main/resources/conf/errors.xml
index 1be4f6e..a2e8ca4 100644
--- a/idp-conf/src/main/resources/conf/errors.xml
+++ b/idp-conf/src/main/resources/conf/errors.xml
@@ -69,6 +69,7 @@
<entry key="UnableToEncode" value-ref="shibboleth.SAML2Status.UnsupportedBinding" />
+ <entry key="AccessDenied" value-ref="shibboleth.SAML2Status.RequestDenied" />
<entry key="MessageReplay" value-ref="shibboleth.SAML2Status.RequestDenied" />
<entry key="MessageExpired" value-ref="shibboleth.SAML2Status.RequestDenied" />
<entry key="MessageAuthenticationError" value-ref="shibboleth.SAML2Status.RequestDenied" />
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 bb06b8e..eb11b1d 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
@@ -275,6 +275,9 @@
<property name="nameIDFormatPrecedenceLookupStrategy">
<bean parent="shibboleth.MDDrivenListProperty" p:propertyName="nameIDFormatPrecedence" />
</property>
+ <property name="proxyCountLookupStrategy">
+ <bean parent="shibboleth.MDDrivenIntProperty" p:propertyName="proxyCount" />
+ </property>
</bean>
<bean id="SAML1.AttributeQuery.MDDriven" parent="AbstractMDDrivenSAMLProfile" lazy-init="true"
@@ -642,6 +645,9 @@
<constructor-arg value="false" />
</bean>
</property>
+ <property name="proxyCountLookupStrategy">
+ <bean parent="shibboleth.MDDrivenIntProperty" p:propertyName="proxyCount" />
+ </property>
</bean>
<bean id="CAS.ProxyConfiguration.MDDriven" parent="AbstractMDDrivenCASProfile" lazy-init="true"
diff --git a/idp-conf/src/main/resources/system/conf/relying-party-system.xml b/idp-conf/src/main/resources/system/conf/relying-party-system.xml
index 4d51c42..8eff3b2 100644
--- a/idp-conf/src/main/resources/system/conf/relying-party-system.xml
+++ b/idp-conf/src/main/resources/system/conf/relying-party-system.xml
@@ -92,6 +92,9 @@
<util:constant id="SAML2.SSO.FEATURE_AUTHNCONTEXT"
static-field="net.shibboleth.idp.saml.saml2.profile.config.BrowserSSOProfileConfiguration.FEATURE_AUTHNCONTEXT"/>
+ <util:constant id="SAML2.SSO.FEATURE_SCOPING"
+ static-field="net.shibboleth.idp.saml.saml2.profile.config.BrowserSSOProfileConfiguration.FEATURE_SCOPING"/>
+
<bean id="SAML2.ECP" lazy-init="true"
class="net.shibboleth.idp.saml.saml2.profile.config.ECPProfileConfiguration"
p:inboundInterceptorFlows="security-policy/saml2-ecp"
diff --git a/idp-conf/src/main/resources/system/flows/authn/proxy/saml-proxy-beans.xml b/idp-conf/src/main/resources/system/flows/authn/proxy/saml-proxy-beans.xml
index cee5e27..d508137 100644
--- a/idp-conf/src/main/resources/system/flows/authn/proxy/saml-proxy-beans.xml
+++ b/idp-conf/src/main/resources/system/flows/authn/proxy/saml-proxy-beans.xml
@@ -143,7 +143,7 @@
p:noResultIsError="false">
<property name="activationCondition">
<bean class="net.shibboleth.idp.saml.profile.config.logic.SignRequestsPredicate"
- p:honorMetadata="%{idp.signing.honorWantAuthnRequestsSigned:true}" />
+ p:honorMetadata="%{idp.saml.honorWantAuthnRequestsSigned:true}" />
</property>
</bean>
</constructor-arg>
diff --git a/idp-conf/src/main/resources/system/flows/saml/saml-abstract-beans.xml b/idp-conf/src/main/resources/system/flows/saml/saml-abstract-beans.xml
index 2ce289e..137d1a9 100644
--- a/idp-conf/src/main/resources/system/flows/saml/saml-abstract-beans.xml
+++ b/idp-conf/src/main/resources/system/flows/saml/saml-abstract-beans.xml
@@ -164,7 +164,7 @@
<bean parent="shibboleth.Conditions.OR">
<constructor-arg>
<bean class="net.shibboleth.idp.saml.profile.config.logic.SignAssertionsPredicate"
- p:honorMetadata="%{idp.signing.honorWantAssertionsSigned:true}" />
+ p:honorMetadata="%{idp.saml.honorWantAssertionsSigned:true}" />
</constructor-arg>
<constructor-arg ref="shibboleth.Conditions.IssuingDelegatedAssertion" />
</bean>
@@ -228,7 +228,8 @@
p:storageServices="#{ getObject('shibboleth.ClientStorageServices') ?: getObject('shibboleth.DefaultClientStorageServices') }" />
<bean id="InitializeAuthenticationContext"
- class="net.shibboleth.idp.saml.profile.impl.InitializeAuthenticationContext" scope="prototype" />
+ class="net.shibboleth.idp.saml.profile.impl.InitializeAuthenticationContext" scope="prototype"
+ p:honorAuthnRequest="%{idp.saml.honorAuthnRequest:true}" />
<bean id="ResolveAttributes" class="net.shibboleth.idp.profile.impl.ResolveAttributes" scope="prototype"
c:resolverService-ref="shibboleth.AttributeResolverService"
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 4b6180e..90a32e6 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
@@ -34,6 +34,7 @@ import com.google.common.base.Predicates;
import net.shibboleth.idp.authn.config.AuthenticationProfileConfiguration;
import net.shibboleth.idp.saml.authn.principal.AuthenticationMethodPrincipal;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonNegative;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
import net.shibboleth.utilities.java.support.annotation.constraint.NotLive;
@@ -70,7 +71,10 @@ public class BrowserSSOProfileConfiguration extends AbstractSAML1ArtifactAwarePr
/** Lookup function to supply NameIdentifier formats. */
@Nonnull private Function<ProfileRequestContext,Collection<String>> nameIDFormatPrecedenceLookupStrategy;
-
+
+ /** Lookup function to supply proxyCount property. */
+ @Nonnull private Function<ProfileRequestContext,Integer> proxyCountLookupStrategy;
+
/** Constructor. */
public BrowserSSOProfileConfiguration() {
this(PROFILE_ID);
@@ -91,6 +95,7 @@ public class BrowserSSOProfileConfiguration extends AbstractSAML1ArtifactAwarePr
defaultAuthenticationMethodsLookupStrategy = FunctionSupport.constant(null);
nameIDFormatPrecedenceLookupStrategy = FunctionSupport.constant(null);
forceAuthnPredicate = Predicates.alwaysFalse();
+ proxyCountLookupStrategy = FunctionSupport.constant(null);
}
/**
@@ -325,4 +330,41 @@ public class BrowserSSOProfileConfiguration extends AbstractSAML1ArtifactAwarePr
nameIDFormatPrecedenceLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
}
+ /** {@inheritDoc} */
+ @Nullable public Integer getProxyCount(@Nullable final ProfileRequestContext profileRequestContext) {
+ final Integer count = proxyCountLookupStrategy.apply(profileRequestContext);
+ if (count != null) {
+ Constraint.isGreaterThanOrEqual(0, count, "Proxy count must be greater than or equal to 0");
+ }
+ return count;
+ }
+
+ /**
+ * Sets the maximum number of times an assertion may be proxied outbound and/or
+ * the maximum number of hops between the relying party and a proxied authentication
+ * authority inbound.
+ *
+ * @param count proxy count
+ *
+ * @since 4.0.0
+ */
+ public void setProxyCount(@Nullable @NonNegative final Integer count) {
+ if (count != null) {
+ Constraint.isGreaterThanOrEqual(0, count, "Proxy count must be greater than or equal to 0");
+ }
+ proxyCountLookupStrategy = FunctionSupport.constant(count);
+ }
+
+ /**
+ * Set a lookup strategy for the maximum number of times an assertion may be proxied outbound and/or
+ * the maximum number of hops between the relying party and a proxied authentication authority inbound.
+ *
+ * @param strategy lookup strategy
+ *
+ * @since 4.0.0
+ */
+ public void setProxyCountLookupStrategy(@Nonnull final Function<ProfileRequestContext,Integer> strategy) {
+ proxyCountLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
+ }
+
}
\ No newline at end of file
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 5f2f49d..8d9086e 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
@@ -62,6 +62,9 @@ public class BrowserSSOProfileConfiguration extends AbstractSAML2ArtifactAwarePr
/** Bit constant for RequestedAuthnContext feature. */
public static final int FEATURE_AUTHNCONTEXT = 0x1;
+
+ /** Bit constant for Scoping feature. */
+ public static final int FEATURE_SCOPING = 0x2;
/** Whether attributes should be resolved in the course of the profile. */
@Nonnull private Predicate<ProfileRequestContext> resolveAttributesPredicate;
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/navigate/ProxyCountLookupFunction.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/navigate/ProxyCountLookupFunction.java
new file mode 100644
index 0000000..c2d1155
--- /dev/null
+++ b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/navigate/ProxyCountLookupFunction.java
@@ -0,0 +1,52 @@
+/*
+ * 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.saml2.profile.config.navigate;
+
+import javax.annotation.Nullable;
+
+import net.shibboleth.idp.profile.config.ProfileConfiguration;
+import net.shibboleth.idp.profile.context.RelyingPartyContext;
+import net.shibboleth.idp.profile.context.navigate.AbstractRelyingPartyLookupFunction;
+import net.shibboleth.idp.saml.saml2.profile.config.SAML2ProfileConfiguration;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+/**
+ * A function that returns the allowable proxy count based on the result of
+ * {@link SAML2ProfileConfiguration#getProxyCount()}, if such a profile is available
+ * from a {@link RelyingPartyContext} obtained via a lookup function,
+ * by default a child of the {@link ProfileRequestContext}.
+ *
+ * <p>If a specific setting is unavailable, a null is returned.</p>
+ */
+public class ProxyCountLookupFunction extends AbstractRelyingPartyLookupFunction<Integer> {
+
+ /** {@inheritDoc} */
+ @Nullable public Integer apply(@Nullable final ProfileRequestContext input) {
+ final RelyingPartyContext rpc = getRelyingPartyContextLookupStrategy().apply(input);
+ if (rpc != null) {
+ final ProfileConfiguration pc = rpc.getProfileConfig();
+ if (pc != null && pc instanceof SAML2ProfileConfiguration) {
+ return ((SAML2ProfileConfiguration) pc).getProxyCount(input);
+ }
+ }
+
+ return null;
+ }
+
+}
\ No newline at end of file
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 d3add6e..44e95f4 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
@@ -17,8 +17,10 @@
package net.shibboleth.idp.saml.profile.impl;
+import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
+import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -26,13 +28,22 @@ import javax.annotation.Nullable;
import net.shibboleth.idp.authn.config.navigate.ForceAuthnProfileConfigPredicate;
import net.shibboleth.idp.authn.context.AuthenticationContext;
import net.shibboleth.idp.profile.AbstractProfileAction;
+import net.shibboleth.idp.profile.context.RelyingPartyContext;
+import net.shibboleth.idp.saml.saml2.profile.config.BrowserSSOProfileConfiguration;
+import net.shibboleth.idp.saml.saml2.profile.config.navigate.ProxyCountLookupFunction;
import net.shibboleth.utilities.java.support.component.ComponentSupport;
import net.shibboleth.utilities.java.support.logic.Constraint;
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
import org.opensaml.messaging.context.navigate.MessageLookup;
+import org.opensaml.profile.action.ActionSupport;
+import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
import org.opensaml.saml.saml2.core.AuthnRequest;
+import org.opensaml.saml.saml2.core.IDPEntry;
+import org.opensaml.saml.saml2.core.IDPList;
+import org.opensaml.saml.saml2.core.Scoping;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -40,30 +51,59 @@ import org.slf4j.LoggerFactory;
* An action that creates an {@link AuthenticationContext} and attaches it to the current {@link ProfileRequestContext}.
*
* <p>If the incoming message is a SAML 2.0 {@link AuthnRequest}, then basic authentication policy (IsPassive,
- * ForceAuthn) is copied into the context from the request.</p>
+ * ForceAuthn, Scoping) is copied into the context from the request.</p>
+ *
+ * @event {@link EventIds#PROCEED_EVENT_ID}
+ * @event {@link EventIds#ACCESS_DENIED}
*
- * @event {@link org.opensaml.profile.action.EventIds#PROCEED_EVENT_ID}
* @post ProfileRequestContext.getSubcontext(AuthenticationContext.class) != true
- * @post SAML 2.0 AuthnRequest policy flags are copied to the {@link AuthenticationContext}
+ * @post SAML 2.0 AuthnRequest policy flags are (optionally) copied to the {@link AuthenticationContext}
*/
public class InitializeAuthenticationContext extends AbstractProfileAction {
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(InitializeAuthenticationContext.class);
+ /** Strategy used to look up a {@link RelyingPartyContext} for configuration options. */
+ @Nonnull private Function<ProfileRequestContext,RelyingPartyContext> relyingPartyContextLookupStrategy;
+
/** Extracts forceAuthn property from profile config. */
@Nonnull private Predicate<ProfileRequestContext> forceAuthnPredicate;
+ /** Strategy used to determine proxy count from configuration. */
+ @Nullable private Function<ProfileRequestContext,Integer> proxyCountLookupStrategy;
+
/** Strategy used to locate the {@link AuthnRequest} to operate on, if any. */
@Nonnull private Function<ProfileRequestContext,AuthnRequest> requestLookupStrategy;
+ /** Whether to honor various policy in an {@link AuthnRequest}. */
+ private boolean honorAuthnRequest;
+
/** Incoming SAML 2.0 request, if present. */
@Nullable private AuthnRequest authnRequest;
/** Constructor. */
public InitializeAuthenticationContext() {
+ relyingPartyContextLookupStrategy = new ChildContextLookup<>(RelyingPartyContext.class);
forceAuthnPredicate = new ForceAuthnProfileConfigPredicate();
+ proxyCountLookupStrategy = new ProxyCountLookupFunction();
requestLookupStrategy = new MessageLookup<>(AuthnRequest.class).compose(new InboundMessageContextLookup());
+ honorAuthnRequest = true;
+ }
+
+ /**
+ * Set the strategy used to return the {@link RelyingPartyContext} for configuration options.
+ *
+ * @param strategy lookup strategy
+ *
+ * @since 4.0.0
+ */
+ public void setRelyingPartyContextLookupStrategy(
+ @Nonnull final Function<ProfileRequestContext,RelyingPartyContext> strategy) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ relyingPartyContextLookupStrategy =
+ Constraint.isNotNull(strategy, "RelyingPartyContext lookup strategy cannot be null");
}
/**
@@ -80,6 +120,19 @@ public class InitializeAuthenticationContext extends AbstractProfileAction {
}
/**
+ * Set the lookup function to apply to derive the proxy count from the configuration.
+ *
+ * @param strategy lookup strategy
+ *
+ * @since 4.0.0
+ */
+ public void setProxyCountLookupStrategy(@Nonnull final Function<ProfileRequestContext,Integer> strategy) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ proxyCountLookupStrategy = Constraint.isNotNull(strategy, "Proxy count lookup strategy 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}
@@ -90,6 +143,22 @@ public class InitializeAuthenticationContext extends AbstractProfileAction {
requestLookupStrategy = Constraint.isNotNull(strategy, "AuthnRequest lookup strategy cannot be null");
}
+ /**
+ * Sets whether to honor various policy in an {@link AuthnRequest} such as IsPassive, ForceAuthn, and Scoping.
+ *
+ * <p>Turning this off constitutes a standards violation and is provided for compatibility with garbage SAML
+ * implementations and incompetent deployers.</p>
+ *
+ * @param flag flag to set
+ *
+ * @since 4.0.0
+ */
+ public void setHonorAuthnRequest(final boolean flag) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ honorAuthnRequest = flag;
+ }
+
/** {@inheritDoc} */
@Override
protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
@@ -98,11 +167,13 @@ public class InitializeAuthenticationContext extends AbstractProfileAction {
return false;
}
- authnRequest = this.requestLookupStrategy.apply(profileRequestContext);
- if (authnRequest == null) {
- log.debug("{} No inbound AuthnRequest, passive flag will be off", getLogPrefix());
- }
+ authnRequest = requestLookupStrategy.apply(profileRequestContext);
+ if (authnRequest != null && !honorAuthnRequest) {
+ log.warn("{} Ignoring incoming AuthnRequest policy content in violation of SAML standard",
+ getLogPrefix());
+ authnRequest = null;
+ }
return true;
}
@@ -113,6 +184,9 @@ public class InitializeAuthenticationContext extends AbstractProfileAction {
final AuthenticationContext authnCtx = new AuthenticationContext();
if (authnRequest != null) {
+ if (!processScoping(profileRequestContext, authnCtx)) {
+ return;
+ }
authnCtx.setForceAuthn(authnRequest.isForceAuthn());
authnCtx.setIsPassive(authnRequest.isPassive());
}
@@ -121,9 +195,74 @@ public class InitializeAuthenticationContext extends AbstractProfileAction {
authnCtx.setForceAuthn(forceAuthnPredicate.test(profileRequestContext));
}
+ // Merge requested and pre-configured proxy count.
+
+ final Integer reqCount = authnCtx.getProxyCount();
+ Integer configCount = proxyCountLookupStrategy.apply(profileRequestContext);
+ if (configCount != null && configCount < 0) {
+ configCount = 0;
+ }
+
+ if (reqCount != null) {
+ if (configCount != null) {
+ authnCtx.setProxyCount(Integer.min(configCount, reqCount));
+ log.debug("{} Combined requested and configured proxy count: {}", getLogPrefix(),
+ authnCtx.getProxyCount());
+ }
+ } else {
+ authnCtx.setProxyCount(configCount);
+ }
+
profileRequestContext.addSubcontext(authnCtx, true);
log.debug("{} Created authentication context: {}", getLogPrefix(), authnCtx);
}
+ /**
+ * Check an inbound {@link AuthnRequest} for a {@link Scoping} element.
+ *
+ * @param profileRequestContext current profile request context
+ * @param authenticationContext the context to populate
+ *
+ * @return true iff processing should continue
+ */
+ private boolean processScoping(@Nonnull final ProfileRequestContext profileRequestContext,
+ @Nonnull final AuthenticationContext authenticationContext) {
+
+ final Scoping scoping = authnRequest.getScoping();
+ if (scoping == null) {
+ log.debug("{} AuthnRequest did not contain Scoping, nothing to do", getLogPrefix());
+ return true;
+ }
+
+ // Check if permitted.
+ final RelyingPartyContext rpContext = relyingPartyContextLookupStrategy.apply(profileRequestContext);
+ if (rpContext != null && rpContext.getProfileConfig() != null
+ && rpContext.getProfileConfig() instanceof BrowserSSOProfileConfiguration) {
+ if (((BrowserSSOProfileConfiguration) rpContext.getProfileConfig()).isFeatureDisallowed(
+ profileRequestContext, BrowserSSOProfileConfiguration.FEATURE_SCOPING)) {
+ log.warn("{} Incoming Scoping disallowed by profile configuration", getLogPrefix());
+ ActionSupport.buildEvent(profileRequestContext, EventIds.ACCESS_DENIED);
+ return false;
+ }
+ }
+
+ // The IDPList doesn't have mandatory semantics, other than disallowing removal.
+
+ final IDPList idpList = scoping.getIDPList();
+ if (idpList != null && idpList.getIDPEntrys() != null) {
+ final Set<String> requestedAuthorities = idpList.getIDPEntrys()
+ .stream()
+ .map(IDPEntry::getProviderID)
+ .filter(id -> id != null)
+ .collect(Collectors.toUnmodifiableSet());
+ authenticationContext.getProxiableAuthorities().addAll(requestedAuthorities);
+ }
+
+ if (scoping.getProxyCount() != null) {
+ authenticationContext.setProxyCount(Integer.max(0, scoping.getProxyCount()));
+ }
+ return true;
+ }
+
}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnRequest.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnRequest.java
index 185ff8b..8593ad0 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnRequest.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnRequest.java
@@ -101,11 +101,7 @@ public class AddAuthnRequest extends AbstractAuthenticationAction {
/** Constructor. */
public AddAuthnRequest() {
// Default strategy is a 16-byte secure random source.
- idGeneratorLookupStrategy = new Function<>() {
- public IdentifierGenerationStrategy apply(final ProfileRequestContext input) {
- return new SecureRandomIdentifierGenerationStrategy();
- }
- };
+ idGeneratorLookupStrategy = prc -> new SecureRandomIdentifierGenerationStrategy();
// Fool the parent class into looking above instead of below the PRC for the context.
setAuthenticationContextLookupStrategy(new ParentContextLookup<>(AuthenticationContext.class));
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ProcessRequestedAuthnContext.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ProcessRequestedAuthnContext.java
index d56edb1..97414d8 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ProcessRequestedAuthnContext.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/ProcessRequestedAuthnContext.java
@@ -29,7 +29,6 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.shibboleth.idp.authn.AbstractAuthenticationAction;
-import net.shibboleth.idp.authn.AuthnEventIds;
import net.shibboleth.idp.authn.context.AuthenticationContext;
import net.shibboleth.idp.authn.context.RequestedPrincipalContext;
import net.shibboleth.idp.profile.context.RelyingPartyContext;
@@ -67,8 +66,7 @@ import org.slf4j.LoggerFactory;
*
* @event {@link EventIds#PROCEED_EVENT_ID}
* @event {@link EventIds#INVALID_MSG_CTX}
- *
- * @post ProfileRequestContext.
+ * @event {@link EventIds#ACCESS_DENIED}
*/
public class ProcessRequestedAuthnContext extends AbstractAuthenticationAction {
@@ -206,7 +204,7 @@ public class ProcessRequestedAuthnContext extends AbstractAuthenticationAction {
if (((BrowserSSOProfileConfiguration) rpContext.getProfileConfig()).isFeatureDisallowed(
profileRequestContext, BrowserSSOProfileConfiguration.FEATURE_AUTHNCONTEXT)) {
log.warn("{} Incoming RequestedAuthnContext disallowed by profile configuration", getLogPrefix());
- ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.INVALID_AUTHN_CTX);
+ ActionSupport.buildEvent(profileRequestContext, EventIds.ACCESS_DENIED);
return;
}
}
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2StringAttributeTranscoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2StringAttributeTranscoderTest.java
index 4babccc..685d8a2 100644
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2StringAttributeTranscoderTest.java
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2StringAttributeTranscoderTest.java
@@ -17,7 +17,6 @@
package net.shibboleth.idp.saml.attribute.transcoding.impl;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -165,7 +164,7 @@ public class SAML2StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
@Test(expectedExceptions = {AttributeEncodingException.class,}) public void inappropriate() throws Exception {
final int[] intArray = {1, 2, 3, 4};
final List<IdPAttributeValue> values =
- Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), new IdPAttributeValue() {
+ List.of(new ByteAttributeValue(new byte[] {1, 2, 3,}), new IdPAttributeValue() {
@Override
public Object getNativeValue() {
return intArray;
@@ -188,7 +187,7 @@ public class SAML2StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
@Test public void single() throws Exception {
final List<IdPAttributeValue> values =
- Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), new StringAttributeValue(STRING_1));
+ List.of(new ByteAttributeValue(new byte[] {1, 2, 3,}), new StringAttributeValue(STRING_1));
final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
inputAttribute.setValues(values);
@@ -223,7 +222,7 @@ public class SAML2StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
@Test public void singleRequested() throws Exception {
final List<IdPAttributeValue> values =
- Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), new StringAttributeValue(STRING_1));
+ List.of(new ByteAttributeValue(new byte[] {1, 2, 3,}), new StringAttributeValue(STRING_1));
final IdPRequestedAttribute inputAttribute = new IdPRequestedAttribute(ATTR_NAME);
inputAttribute.setRequired(true);
@@ -307,7 +306,7 @@ public class SAML2StringAttributeTranscoderTest extends OpenSAMLInitBaseTestCase
@Test public void multi() throws Exception {
final List<IdPAttributeValue> values =
- Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}),
+ List.of(new ByteAttributeValue(new byte[] {1, 2, 3,}),
new StringAttributeValue(STRING_1),
new StringAttributeValue(STRING_2),
new ScopedStringAttributeValue(STRING_1, STRING_2));
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2XMLObjectAttributeTranscoderTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2XMLObjectAttributeTranscoderTest.java
index d8bcb1c..9c7337f 100644
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2XMLObjectAttributeTranscoderTest.java
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/attribute/transcoding/impl/SAML2XMLObjectAttributeTranscoderTest.java
@@ -17,7 +17,6 @@
package net.shibboleth.idp.saml.attribute.transcoding.impl;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -46,8 +45,8 @@ import net.shibboleth.utilities.java.support.component.ComponentInitializationEx
import org.opensaml.core.OpenSAMLInitBaseTestCase;
import org.opensaml.core.xml.XMLObject;
import org.opensaml.core.xml.XMLObjectBuilder;
+import org.opensaml.core.xml.XMLObjectBuilderFactory;
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
-import org.opensaml.core.xml.schema.XSAny;
import org.opensaml.core.xml.schema.XSString;
import org.opensaml.saml.common.SAMLObjectBuilder;
import org.opensaml.saml.saml2.core.Attribute;
@@ -63,7 +62,7 @@ public class SAML2XMLObjectAttributeTranscoderTest extends OpenSAMLInitBaseTestC
private AttributeTranscoderRegistryImpl registry;
- private XMLObjectBuilder<XSAny> anyBuilder;
+ private SAMLObjectBuilder<AttributeValue> anyBuilder;
private XMLObjectBuilder<XSString> stringBuilder;
@@ -79,15 +78,13 @@ public class SAML2XMLObjectAttributeTranscoderTest extends OpenSAMLInitBaseTestC
@BeforeClass public void setUp() throws ComponentInitializationException {
- anyBuilder = XMLObjectProviderRegistrySupport.getBuilderFactory().<XSAny>getBuilderOrThrow(XSAny.TYPE_NAME);
- stringBuilder = XMLObjectProviderRegistrySupport.getBuilderFactory().<XSString>getBuilderOrThrow(XSString.TYPE_NAME);
+ final XMLObjectBuilderFactory bf = XMLObjectProviderRegistrySupport.getBuilderFactory();
- attributeBuilder = (SAMLObjectBuilder<Attribute>)
- XMLObjectProviderRegistrySupport.getBuilderFactory().<Attribute>getBuilderOrThrow(
- Attribute.TYPE_NAME);
- reqAttributeBuilder = (SAMLObjectBuilder<RequestedAttribute>)
- XMLObjectProviderRegistrySupport.getBuilderFactory().<RequestedAttribute>getBuilderOrThrow(
- RequestedAttribute.TYPE_NAME);
+ anyBuilder = (SAMLObjectBuilder<AttributeValue>) bf.<AttributeValue>getBuilderOrThrow(AttributeValue.DEFAULT_ELEMENT_NAME);
+ stringBuilder = bf.<XSString>getBuilderOrThrow(XSString.TYPE_NAME);
+
+ attributeBuilder = (SAMLObjectBuilder<Attribute>) bf.<Attribute>getBuilderOrThrow(Attribute.TYPE_NAME);
+ reqAttributeBuilder = (SAMLObjectBuilder<RequestedAttribute>) bf.<RequestedAttribute>getBuilderOrThrow(RequestedAttribute.TYPE_NAME);
registry = new AttributeTranscoderRegistryImpl();
registry.setId("test");
@@ -172,7 +169,7 @@ public class SAML2XMLObjectAttributeTranscoderTest extends OpenSAMLInitBaseTestC
@Test(expectedExceptions = {AttributeEncodingException.class,}) public void inappropriate() throws Exception {
final int[] intArray = {1, 2, 3, 4};
final List<IdPAttributeValue> values =
- Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), new IdPAttributeValue() {
+ List.of(new ByteAttributeValue(new byte[] {1, 2, 3,}), new IdPAttributeValue() {
@Override
public Object getNativeValue() {
return intArray;
@@ -195,7 +192,7 @@ public class SAML2XMLObjectAttributeTranscoderTest extends OpenSAMLInitBaseTestC
@Test public void single() throws Exception {
final List<IdPAttributeValue> values =
- Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), objectFor(STRING_1));
+ List.of(new ByteAttributeValue(new byte[] {1, 2, 3,}), objectFor(STRING_1));
final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
inputAttribute.setValues(values);
@@ -225,7 +222,7 @@ public class SAML2XMLObjectAttributeTranscoderTest extends OpenSAMLInitBaseTestC
@Test public void singleRequested() throws Exception {
final List<IdPAttributeValue> values =
- Arrays.asList(new ByteAttributeValue(new byte[] {1, 2, 3,}), objectFor(STRING_1));
+ List.of(new ByteAttributeValue(new byte[] {1, 2, 3,}), objectFor(STRING_1));
final IdPRequestedAttribute inputAttribute = new IdPRequestedAttribute(ATTR_NAME);
inputAttribute.setRequired(true);
@@ -260,7 +257,7 @@ public class SAML2XMLObjectAttributeTranscoderTest extends OpenSAMLInitBaseTestC
final XSString stringValue = stringBuilder.buildObject(new QName("Foo"));
stringValue.setValue(STRING_1);
- final XSAny attrValue = anyBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ final AttributeValue attrValue = anyBuilder.buildObject();
attrValue.getUnknownXMLObjects().add(stringValue);
final Attribute samlAttribute = attributeBuilder.buildObject();
@@ -290,7 +287,7 @@ public class SAML2XMLObjectAttributeTranscoderTest extends OpenSAMLInitBaseTestC
final XSString stringValue = stringBuilder.buildObject(new QName("Foo"));
stringValue.setValue(STRING_1);
- final XSAny attrValue = anyBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ final AttributeValue attrValue = anyBuilder.buildObject();
attrValue.getUnknownXMLObjects().add(stringValue);
final RequestedAttribute samlAttribute = reqAttributeBuilder.buildObject();
@@ -317,7 +314,7 @@ public class SAML2XMLObjectAttributeTranscoderTest extends OpenSAMLInitBaseTestC
@Test public void multi() throws Exception {
final List<IdPAttributeValue> values =
- Arrays.asList(objectFor(STRING_1), objectFor(STRING_2));
+ List.of(objectFor(STRING_1), objectFor(STRING_2));
final IdPAttribute inputAttribute = new IdPAttribute(ATTR_NAME);
inputAttribute.setValues(values);
@@ -355,13 +352,13 @@ public class SAML2XMLObjectAttributeTranscoderTest extends OpenSAMLInitBaseTestC
final XSString stringValue = stringBuilder.buildObject(new QName("Foo"));
stringValue.setValue(STRING_1);
- final XSAny attrValue = anyBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ final AttributeValue attrValue = anyBuilder.buildObject();
attrValue.getUnknownXMLObjects().add(stringValue);
final XSString stringValue2 = stringBuilder.buildObject(new QName("Bar"));
stringValue2.setValue(STRING_2);
- final XSAny attrValue2 = anyBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME);
+ final AttributeValue attrValue2 = anyBuilder.buildObject();
attrValue2.getUnknownXMLObjects().add(stringValue2);
final Attribute samlAttribute = attributeBuilder.buildObject();
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/profile/impl/InitializeAuthenticationContextTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/profile/impl/InitializeAuthenticationContextTest.java
index 558fca5..9388220 100644
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/profile/impl/InitializeAuthenticationContextTest.java
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/profile/impl/InitializeAuthenticationContextTest.java
@@ -20,29 +20,45 @@ package net.shibboleth.idp.saml.profile.impl;
import net.shibboleth.idp.authn.context.AuthenticationContext;
import net.shibboleth.idp.profile.ActionTestingSupport;
import net.shibboleth.idp.profile.RequestContextBuilder;
+import net.shibboleth.idp.profile.context.RelyingPartyContext;
import net.shibboleth.idp.profile.context.navigate.WebflowRequestContextProfileRequestContextLookup;
+import net.shibboleth.idp.saml.saml2.profile.config.BrowserSSOProfileConfiguration;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.logic.FunctionSupport;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import java.util.Set;
+
+import org.opensaml.core.OpenSAMLInitBaseTestCase;
+import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.saml.common.SAMLObjectBuilder;
import org.opensaml.saml.saml2.core.AuthnRequest;
+import org.opensaml.saml.saml2.core.Scoping;
+import org.opensaml.saml.saml2.profile.SAML2ActionTestingSupport;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/** {@link InitializeAuthenticationContext} unit test. */
-public class InitializeAuthenticationContextTest {
-
- /** Test that the action functions properly if there is no inbound message context. */
- @Test public void testNoInboundMessageContext() throws Exception {
+public class InitializeAuthenticationContextTest extends OpenSAMLInitBaseTestCase {
+
+ private InitializeAuthenticationContext action;
+
+ @BeforeMethod
+ public void setUp() throws ComponentInitializationException {
+ action = new InitializeAuthenticationContext();
+ action.setProxyCountLookupStrategy(FunctionSupport.constant(1));
+ action.initialize();
+ }
+
+ /** Test that the action functions properly if there is no inbound message context.
+ * @throws ComponentInitializationException */
+ @Test public void testNoInboundMessageContext() throws ComponentInitializationException {
final RequestContext requestCtx = new RequestContextBuilder().buildRequestContext();
final ProfileRequestContext prc = new WebflowRequestContextProfileRequestContextLookup().apply(requestCtx);
prc.setInboundMessageContext(null);
- final InitializeAuthenticationContext action = new InitializeAuthenticationContext();
- action.initialize();
-
final Event event = action.execute(requestCtx);
ActionTestingSupport.assertProceedEvent(event);
@@ -50,16 +66,14 @@ public class InitializeAuthenticationContextTest {
Assert.assertNotNull(authnCtx);
Assert.assertFalse(authnCtx.isForceAuthn());
Assert.assertFalse(authnCtx.isPassive());
+ Assert.assertEquals(authnCtx.getProxyCount(), Integer.valueOf(1));
}
/** Test that the action functions properly if there is no inbound message. */
- @Test public void testNoInboundMessage() throws Exception {
+ @Test public void testNoInboundMessage() throws ComponentInitializationException {
final RequestContext requestCtx = new RequestContextBuilder().setInboundMessage(null).buildRequestContext();
final ProfileRequestContext prc = new WebflowRequestContextProfileRequestContextLookup().apply(requestCtx);
- final InitializeAuthenticationContext action = new InitializeAuthenticationContext();
- action.initialize();
-
final Event event = action.execute(requestCtx);
ActionTestingSupport.assertProceedEvent(event);
@@ -67,19 +81,17 @@ public class InitializeAuthenticationContextTest {
Assert.assertNotNull(authnCtx);
Assert.assertFalse(authnCtx.isForceAuthn());
Assert.assertFalse(authnCtx.isPassive());
+ Assert.assertEquals(authnCtx.getProxyCount(), Integer.valueOf(1));
}
/** Test that the action functions properly if the inbound message is not a SAML 2 AuthnRequest. */
- @Test public void testSAML1AuthnRequest() throws Exception {
+ @Test public void testSAML1AuthnRequest() throws ComponentInitializationException {
final RequestContext requestCtx =
new RequestContextBuilder().setInboundMessage(
new IdPInitiatedSSORequest("https://sp.example.org/sp", null, null, null)
).buildRequestContext();
final ProfileRequestContext prc = new WebflowRequestContextProfileRequestContextLookup().apply(requestCtx);
-
- final InitializeAuthenticationContext action = new InitializeAuthenticationContext();
- action.initialize();
-
+
final Event event = action.execute(requestCtx);
ActionTestingSupport.assertProceedEvent(event);
@@ -87,14 +99,12 @@ public class InitializeAuthenticationContextTest {
Assert.assertNotNull(authnCtx);
Assert.assertFalse(authnCtx.isForceAuthn());
Assert.assertFalse(authnCtx.isPassive());
+ Assert.assertEquals(authnCtx.getProxyCount(), Integer.valueOf(1));
}
/** Test that the action proceeds properly if the inbound message is a SAML2 AuthnRequest. */
- @Test public void testCreateAuthenticationContext() throws Exception {
- final SAMLObjectBuilder<AuthnRequest> builder = (SAMLObjectBuilder<AuthnRequest>)
- XMLObjectProviderRegistrySupport.getBuilderFactory().<AuthnRequest>getBuilderOrThrow(
- AuthnRequest.DEFAULT_ELEMENT_NAME);
- final AuthnRequest authnRequest = builder.buildObject();
+ @Test public void testCreateAuthenticationContext() throws ComponentInitializationException {
+ final AuthnRequest authnRequest = SAML2ActionTestingSupport.buildAuthnRequest();
authnRequest.setIsPassive(true);
authnRequest.setForceAuthn(true);
@@ -102,9 +112,6 @@ public class InitializeAuthenticationContextTest {
new RequestContextBuilder().setInboundMessage(authnRequest).buildRequestContext();
final ProfileRequestContext prc = new WebflowRequestContextProfileRequestContextLookup().apply(requestCtx);
- final InitializeAuthenticationContext action = new InitializeAuthenticationContext();
- action.initialize();
-
final Event event = action.execute(requestCtx);
ActionTestingSupport.assertProceedEvent(event);
@@ -112,6 +119,94 @@ public class InitializeAuthenticationContextTest {
Assert.assertNotNull(authnCtx);
Assert.assertTrue(authnCtx.isForceAuthn());
Assert.assertTrue(authnCtx.isPassive());
+ Assert.assertEquals(authnCtx.getProxyCount(), Integer.valueOf(1));
+ }
+
+ @Test public void testAuthnRequestIgnored() throws ComponentInitializationException {
+ final AuthnRequest authnRequest = SAML2ActionTestingSupport.buildAuthnRequest();
+ authnRequest.setIsPassive(true);
+ authnRequest.setForceAuthn(true);
+
+ final RequestContext requestCtx =
+ new RequestContextBuilder().setInboundMessage(authnRequest).buildRequestContext();
+ final ProfileRequestContext prc = new WebflowRequestContextProfileRequestContextLookup().apply(requestCtx);
+
+ final Scoping scoping = SAML2ActionTestingSupport.buildScoping(0, null);
+ ((AuthnRequest) prc.getInboundMessageContext().getMessage()).setScoping(scoping);
+
+ action = new InitializeAuthenticationContext();
+ action.setProxyCountLookupStrategy(FunctionSupport.constant(1));
+ action.setHonorAuthnRequest(false);
+ action.initialize();
+
+ final Event event = action.execute(requestCtx);
+ ActionTestingSupport.assertProceedEvent(event);
+
+ final AuthenticationContext authnCtx = prc.getSubcontext(AuthenticationContext.class);
+ Assert.assertNotNull(authnCtx);
+ Assert.assertFalse(authnCtx.isForceAuthn());
+ Assert.assertFalse(authnCtx.isPassive());
+ Assert.assertEquals(authnCtx.getProxyCount(), Integer.valueOf(1));
+ }
+
+ @Test public void testScopingDisallowed() throws ComponentInitializationException {
+ final AuthnRequest authnRequest = SAML2ActionTestingSupport.buildAuthnRequest();
+ authnRequest.setIsPassive(true);
+ authnRequest.setForceAuthn(true);
+
+ final RequestContext requestCtx =
+ new RequestContextBuilder().setInboundMessage(authnRequest).buildRequestContext();
+ final ProfileRequestContext prc = new WebflowRequestContextProfileRequestContextLookup().apply(requestCtx);
+
+ final Scoping scoping = SAML2ActionTestingSupport.buildScoping(0, null);
+ ((AuthnRequest) prc.getInboundMessageContext().getMessage()).setScoping(scoping);
+
+ final BrowserSSOProfileConfiguration config = new BrowserSSOProfileConfiguration();
+ config.setDisallowedFeatures(BrowserSSOProfileConfiguration.FEATURE_SCOPING);
+
+ prc.getSubcontext(RelyingPartyContext.class, true).setProfileConfig(config);
+
+ final Event event = action.execute(requestCtx);
+ ActionTestingSupport.assertEvent(event, EventIds.ACCESS_DENIED);
+ final AuthenticationContext authnCtx = prc.getSubcontext(AuthenticationContext.class);
+ Assert.assertNull(authnCtx);
+ }
+
+ @Test public void testProxyCount() throws ComponentInitializationException {
+ final AuthnRequest authnRequest = SAML2ActionTestingSupport.buildAuthnRequest();
+ authnRequest.setIsPassive(true);
+ authnRequest.setForceAuthn(true);
+
+ final RequestContext requestCtx =
+ new RequestContextBuilder().setInboundMessage(authnRequest).buildRequestContext();
+ final ProfileRequestContext prc = new WebflowRequestContextProfileRequestContextLookup().apply(requestCtx);
+
+ final Scoping scoping = SAML2ActionTestingSupport.buildScoping(0, null);
+ ((AuthnRequest) prc.getInboundMessageContext().getMessage()).setScoping(scoping);
+
+ final Event event = action.execute(requestCtx);
+ ActionTestingSupport.assertProceedEvent(event);
+ final AuthenticationContext authnCtx = prc.getSubcontext(AuthenticationContext.class);
+ Assert.assertEquals(authnCtx.getProxyCount(), Integer.valueOf(0));
+ }
+
+ @Test public void testProxyList() throws ComponentInitializationException {
+ final AuthnRequest authnRequest = SAML2ActionTestingSupport.buildAuthnRequest();
+ authnRequest.setIsPassive(true);
+ authnRequest.setForceAuthn(true);
+
+ final RequestContext requestCtx =
+ new RequestContextBuilder().setInboundMessage(authnRequest).buildRequestContext();
+ final ProfileRequestContext prc = new WebflowRequestContextProfileRequestContextLookup().apply(requestCtx);
+
+ final Scoping scoping = SAML2ActionTestingSupport.buildScoping(0, Set.of("foo", "bar"));
+ ((AuthnRequest) prc.getInboundMessageContext().getMessage()).setScoping(scoping);
+
+ final Event event = action.execute(requestCtx);
+ ActionTestingSupport.assertProceedEvent(event);
+ final AuthenticationContext authnCtx = prc.getSubcontext(AuthenticationContext.class);
+ Assert.assertEquals(authnCtx.getProxyCount(), Integer.valueOf(0));
+ Assert.assertEquals(authnCtx.getProxiableAuthorities(), Set.of("foo", "bar"));
}
}
\ No newline at end of file
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/ProcessRequestedAuthnContextTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/ProcessRequestedAuthnContextTest.java
index c643888..0c2394f 100644
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/ProcessRequestedAuthnContextTest.java
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/ProcessRequestedAuthnContextTest.java
@@ -20,7 +20,6 @@ package net.shibboleth.idp.saml.saml2.profile.impl;
import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
-import net.shibboleth.idp.authn.AuthnEventIds;
import net.shibboleth.idp.authn.context.AuthenticationContext;
import net.shibboleth.idp.authn.context.RequestedPrincipalContext;
import net.shibboleth.idp.profile.ActionTestingSupport;
@@ -121,7 +120,7 @@ public class ProcessRequestedAuthnContextTest extends OpenSAMLInitBaseTestCase {
BrowserSSOProfileConfiguration.FEATURE_AUTHNCONTEXT);
final Event event = action.execute(src);
- ActionTestingSupport.assertEvent(event, AuthnEventIds.INVALID_AUTHN_CTX);
+ ActionTestingSupport.assertEvent(event, EventIds.ACCESS_DENIED);
Assert.assertNull(ac.getSubcontext(RequestedPrincipalContext.class));
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list