[java-identity-provider] branch master updated: IDP-1117 - Support for AuthenticatingAuthority
Scott Cantor
cantor.2 at osu.edu
Wed Aug 22 12:39:37 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=8b966a5832a02163d750c9f024bb70349845a5fa
The following commit(s) were added to refs/heads/master by this push:
new 8b966a5 IDP-1117 - Support for AuthenticatingAuthority
8b966a5 is described below
commit 8b966a5832a02163d750c9f024bb70349845a5fa
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Wed Aug 22 12:38:21 2018 -0400
IDP-1117 - Support for AuthenticatingAuthority
https://issues.shibboleth.net/jira/browse/IDP-1117
---
.../idp/authn/ExternalAuthentication.java | 7 ++
.../context/ExternalAuthenticationContext.java | 82 +++++++++++++++++++---
.../principal/ProxyAuthenticationPrincipal.java | 20 +++++-
.../idp/authn/impl/ExternalAuthenticationImpl.java | 5 ++
.../idp/authn/impl/RemoteUserAuthServlet.java | 47 ++++++++++++-
.../authn/impl/ValidateExternalAuthentication.java | 7 ++
.../impl/ValidateExternalAuthenticationTest.java | 23 +++++-
.../resources/system/conf/general-authn-system.xml | 1 +
.../profile/impl/AddAuthnStatementToAssertion.java | 23 ++++++
.../impl/AddAuthnStatementToAssertionTest.java | 40 ++++++++---
10 files changed, 232 insertions(+), 23 deletions(-)
diff --git a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/ExternalAuthentication.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/ExternalAuthentication.java
index 66e6001..586911f 100644
--- a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/ExternalAuthentication.java
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/ExternalAuthentication.java
@@ -48,6 +48,13 @@ public class ExternalAuthentication {
/** Request attribute to which an authentication timestamp may be bound. */
@Nonnull @NotEmpty public static final String AUTHENTICATION_INSTANT_KEY = "authnInstant";
+ /**
+ * Request attribute to which a collection of authenticating authorities may be bound.
+ *
+ * @since 3.4.0
+ */
+ @Nonnull @NotEmpty public static final String AUTHENTICATING_AUTHORITIES_KEY = "authnAuthorities";
+
/** Request attribute to which an error message may be bound. */
@Nonnull @NotEmpty public static final String AUTHENTICATION_ERROR_KEY = "authnError";
diff --git a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/ExternalAuthenticationContext.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/ExternalAuthenticationContext.java
index 56921f6..5eb5f06 100644
--- a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/ExternalAuthenticationContext.java
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/ExternalAuthenticationContext.java
@@ -18,13 +18,18 @@
package net.shibboleth.idp.authn.context;
import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Collection;
+import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.security.auth.Subject;
import org.joda.time.DateTime;
import org.opensaml.messaging.context.BaseContext;
+import net.shibboleth.utilities.java.support.annotation.constraint.Live;
+
/**
* A context representing the state of an externalized authentication attempt,
* a case where authentication happens outside of a web flow.
@@ -49,6 +54,9 @@ public final class ExternalAuthenticationContext extends BaseContext {
/** Time of authentication. */
@Nullable private DateTime authnInstant;
+ /** Proxied authenticating sources. */
+ @Nonnull private Collection<String> authenticatingAuthorities;
+
/** Error message. */
@Nullable private String authnError;
@@ -61,6 +69,11 @@ public final class ExternalAuthenticationContext extends BaseContext {
/** Flag indicating this "new" result is really "old". */
private boolean previousResult;
+ /** Constructor. */
+ public ExternalAuthenticationContext() {
+ authenticatingAuthorities = new ArrayList<>();
+ }
+
/**
* Get the flow execution URL to return control to.
*
@@ -75,9 +88,13 @@ public final class ExternalAuthenticationContext extends BaseContext {
* Set the flow execution URL to return control to.
*
* @param url return location
+ *
+ * @return this context
*/
- public void setFlowExecutionUrl(@Nullable final String url) {
+ @Nonnull public ExternalAuthenticationContext setFlowExecutionUrl(@Nullable final String url) {
flowExecutionUrl = url;
+
+ return this;
}
/**
@@ -93,9 +110,13 @@ public final class ExternalAuthenticationContext extends BaseContext {
* Set a {@link Principal} that was authenticated.
*
* @param prin principal to set
+ *
+ * @return this context
*/
- public void setPrincipal(@Nullable final Principal prin) {
+ @Nonnull public ExternalAuthenticationContext setPrincipal(@Nullable final Principal prin) {
principal = prin;
+
+ return this;
}
/**
@@ -111,9 +132,13 @@ public final class ExternalAuthenticationContext extends BaseContext {
* Set the name of a principal that was authenticated.
*
* @param name name of principal to set
+ *
+ * @return this context
*/
- public void setPrincipalName(@Nullable final String name) {
+ @Nonnull public ExternalAuthenticationContext setPrincipalName(@Nullable final String name) {
principalName = name;
+
+ return this;
}
/**
@@ -128,10 +153,14 @@ public final class ExternalAuthenticationContext extends BaseContext {
/**
* Set a {@link Subject} that was authenticated.
*
- * @param sub The subject to set.
+ * @param sub The subject to set
+ *
+ * @return this context
*/
- public void setSubject(@Nullable final Subject sub) {
+ @Nonnull public ExternalAuthenticationContext setSubject(@Nullable final Subject sub) {
subject = sub;
+
+ return this;
}
/**
@@ -147,9 +176,24 @@ public final class ExternalAuthenticationContext extends BaseContext {
* Set the time of authentication.
*
* @param instant time of authentication to set
+ *
+ * @return this context
*/
- public void setAuthnInstant(final DateTime instant) {
+ @Nonnull public ExternalAuthenticationContext setAuthnInstant(@Nullable final DateTime instant) {
authnInstant = instant;
+
+ return this;
+ }
+
+ /**
+ * Get a mutable, ordered list of proxied authentication sources.
+ *
+ * @return proxied authentication sources
+ *
+ * @since 3.4.0
+ */
+ @Nonnull @Live public Collection<String> getAuthenticatingAuthorities() {
+ return authenticatingAuthorities;
}
/**
@@ -165,9 +209,13 @@ public final class ExternalAuthenticationContext extends BaseContext {
* Set an error message from the authentication process.
*
* @param message message to set
+ *
+ * @return this context
*/
- public void setAuthnError(final String message) {
+ @Nonnull public ExternalAuthenticationContext setAuthnError(@Nullable final String message) {
authnError = message;
+
+ return this;
}
/**
@@ -183,9 +231,13 @@ public final class ExternalAuthenticationContext extends BaseContext {
* Set an exception from the authentication process.
*
* @param exception exception to set
+ *
+ * @return this context
*/
- public void setAuthnException(final Exception exception) {
+ @Nonnull public ExternalAuthenticationContext setAuthnException(@Nullable final Exception exception) {
authnException = exception;
+
+ return this;
}
/**
@@ -200,10 +252,14 @@ public final class ExternalAuthenticationContext extends BaseContext {
/**
* Set the "do not cache" flag.
*
- * @param flag flag to set
+ * @param flag flag to set
+ *
+ * @return this context
*/
- public void setDoNotCache(final boolean flag) {
+ @Nonnull public ExternalAuthenticationContext setDoNotCache(final boolean flag) {
doNotCache = flag;
+
+ return this;
}
/**
@@ -224,9 +280,13 @@ public final class ExternalAuthenticationContext extends BaseContext {
*
* @param flag flag to set
*
+ * @return this context
+ *
* @since 3.3.0
*/
- public void setPreviousResult(final boolean flag) {
+ @Nonnull public ExternalAuthenticationContext setPreviousResult(final boolean flag) {
previousResult = flag;
+
+ return this;
}
}
\ No newline at end of file
diff --git a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/principal/ProxyAuthenticationPrincipal.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/principal/ProxyAuthenticationPrincipal.java
index bb782c3..b26e4fa 100644
--- a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/principal/ProxyAuthenticationPrincipal.java
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/principal/ProxyAuthenticationPrincipal.java
@@ -26,10 +26,17 @@ import javax.annotation.Nonnull;
import net.shibboleth.utilities.java.support.annotation.constraint.Live;
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;
import com.google.common.base.MoreObjects;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Collections2;
-/** Principal that wraps a set of proxied authentication authorities. */
+/**
+ * Principal that wraps a set of proxied authentication authorities.
+ *
+ * @since 3.4.0
+ */
public class ProxyAuthenticationPrincipal implements Principal {
/** The authorities. */
@@ -40,6 +47,17 @@ public class ProxyAuthenticationPrincipal implements Principal {
authorities = new ArrayList<>();
}
+ /**
+ * Constructor.
+ *
+ * @param proxiedAuthorities initial set of authorities
+ */
+ public ProxyAuthenticationPrincipal(@Nonnull @NonnullElements final Collection<String> proxiedAuthorities) {
+ Constraint.isNotNull(proxiedAuthorities, "Proxied authority collection cannot be null");
+
+ authorities = new ArrayList<>(Collections2.filter(proxiedAuthorities, Predicates.notNull()));
+ }
+
/** {@inheritDoc} */
@Nonnull @NotEmpty public String getName() {
return authorities.toString();
diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ExternalAuthenticationImpl.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ExternalAuthenticationImpl.java
index 4aca5f2..d942a58 100644
--- a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ExternalAuthenticationImpl.java
+++ b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ExternalAuthenticationImpl.java
@@ -160,6 +160,11 @@ public class ExternalAuthenticationImpl extends ExternalAuthentication {
extContext.setAuthnInstant((DateTime) attr);
}
+ attr = request.getAttribute(AUTHENTICATING_AUTHORITIES_KEY);
+ if (attr != null && attr instanceof Collection<?>) {
+ extContext.getAuthenticatingAuthorities().addAll((Collection<String>) attr);
+ }
+
attr = request.getAttribute(AUTHENTICATION_ERROR_KEY);
if (attr != null && attr instanceof String) {
extContext.setAuthnError((String) attr);
diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/RemoteUserAuthServlet.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/RemoteUserAuthServlet.java
index 12305f3..e265a96 100644
--- a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/RemoteUserAuthServlet.java
+++ b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/RemoteUserAuthServlet.java
@@ -82,7 +82,10 @@ public class RemoteUserAuthServlet extends HttpServlet {
/** Init parameter identifying a header to check for one or more authentication method strings. */
@Nonnull @NotEmpty private static final String AUTHN_METHOD_HEADER_PARAM = "authnMethodHeader";
-
+
+ /** Init parameter identifying a header to check for one or more proxied authenticating authority strings. */
+ @Nonnull @NotEmpty private static final String AUTHN_AUTHORITY_HEADER_PARAM = "authnAuthorityHeader";
+
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(RemoteUserAuthServlet.class);
@@ -101,6 +104,9 @@ public class RemoteUserAuthServlet extends HttpServlet {
/** Header to check for authentication method strings. */
@Nullable @NotEmpty private String authnMethodHeader;
+ /** Header to check for proxied authenticating authority strings. */
+ @Nullable @NotEmpty private String authnAuthorityHeader;
+
/** Constructor. */
public RemoteUserAuthServlet() {
checkRemoteUser = true;
@@ -153,6 +159,17 @@ public class RemoteUserAuthServlet extends HttpServlet {
authnMethodHeader = StringSupport.trimOrNull(header);
}
+ /**
+ * Set the name of a request header to check for authenticating authority strings.
+ *
+ * @param header request header name
+ *
+ * @since 3.4.0
+ */
+ public void setAuthnAuthorityHeader(@Nullable @NotEmpty final String header) {
+ authnAuthorityHeader = StringSupport.trimOrNull(header);
+ }
+
// Checkstyle: CyclomaticComplexity OFF
/** {@inheritDoc} */
@Override
@@ -189,7 +206,12 @@ public class RemoteUserAuthServlet extends HttpServlet {
if (param != null) {
setAuthnMethodHeader(param);
}
-
+
+ param = config.getInitParameter(AUTHN_AUTHORITY_HEADER_PARAM);
+ if (param != null) {
+ setAuthnAuthorityHeader(param);
+ }
+
log.info("RemoteUserAuthServlet {} process REMOTE_USER, along with attributes {} and headers {}",
new Object[] {checkRemoteUser ? "will" : "will not", checkAttributes, checkHeaders,});
if (subjectAttribute != null) {
@@ -199,6 +221,10 @@ public class RemoteUserAuthServlet extends HttpServlet {
if (authnMethodHeader != null) {
log.info("RemoteUserAuthServlet will check for authentication methods in header: {}", authnMethodHeader);
}
+ if (authnAuthorityHeader != null) {
+ log.info("RemoteUserAuthServlet will check for authenticating authorities in header: {}",
+ authnAuthorityHeader);
+ }
}
// Checkstyle: MethodLength|ReturnCount OFF
@@ -259,6 +285,23 @@ public class RemoteUserAuthServlet extends HttpServlet {
return;
}
+ if (authnAuthorityHeader != null) {
+ // Check for proxied authorities.
+ final Enumeration<String> authorities = httpRequest.getHeaders(authnAuthorityHeader);
+ if (authorities != null && authorities.hasMoreElements()) {
+ final Collection<String> copied = new ArrayList<>();
+ while (authorities.hasMoreElements()) {
+ final String authority = authorities.nextElement();
+ if (!Strings.isNullOrEmpty(authority)) {
+ copied.add(authority);
+ }
+ }
+ if (!copied.isEmpty()) {
+ httpRequest.setAttribute(ExternalAuthentication.AUTHENTICATING_AUTHORITIES_KEY, copied);
+ }
+ }
+ }
+
if (authnMethodHeader != null) {
// Check for authentication methods.
final Enumeration<String> methods = httpRequest.getHeaders(authnMethodHeader);
diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateExternalAuthentication.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateExternalAuthentication.java
index 0a40cea..d0a4819 100644
--- a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateExternalAuthentication.java
+++ b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateExternalAuthentication.java
@@ -29,6 +29,7 @@ import net.shibboleth.idp.authn.AbstractValidationAction;
import net.shibboleth.idp.authn.AuthnEventIds;
import net.shibboleth.idp.authn.context.AuthenticationContext;
import net.shibboleth.idp.authn.context.ExternalAuthenticationContext;
+import net.shibboleth.idp.authn.principal.ProxyAuthenticationPrincipal;
import net.shibboleth.idp.authn.principal.UsernamePrincipal;
import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
import net.shibboleth.utilities.java.support.component.ComponentSupport;
@@ -165,6 +166,12 @@ public class ValidateExternalAuthentication extends AbstractValidationAction {
recordSuccess();
+ if (!extContext.getAuthenticatingAuthorities().isEmpty()) {
+ final ProxyAuthenticationPrincipal proxied =
+ new ProxyAuthenticationPrincipal(extContext.getAuthenticatingAuthorities());
+ extContext.getSubject().getPrincipals().add(proxied);
+ }
+
if (extContext.doNotCache()) {
log.debug("{} Disabling caching of authentication result", getLogPrefix());
authenticationContext.setResultCacheable(false);
diff --git a/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/impl/ValidateExternalAuthenticationTest.java b/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/impl/ValidateExternalAuthenticationTest.java
index f4cbe03..a73aba0 100644
--- a/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/impl/ValidateExternalAuthenticationTest.java
+++ b/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/impl/ValidateExternalAuthenticationTest.java
@@ -17,6 +17,9 @@
package net.shibboleth.idp.authn.impl;
+import java.util.Arrays;
+import java.util.Set;
+
import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;
import javax.servlet.http.HttpServletRequest;
@@ -25,6 +28,7 @@ import net.shibboleth.idp.authn.AuthnEventIds;
import net.shibboleth.idp.authn.context.AuthenticationContext;
import net.shibboleth.idp.authn.context.AuthenticationErrorContext;
import net.shibboleth.idp.authn.context.ExternalAuthenticationContext;
+import net.shibboleth.idp.authn.principal.ProxyAuthenticationPrincipal;
import net.shibboleth.idp.authn.principal.TestPrincipal;
import net.shibboleth.idp.authn.principal.UsernamePrincipal;
import net.shibboleth.idp.profile.ActionTestingSupport;
@@ -126,7 +130,24 @@ public class ValidateExternalAuthenticationTest extends BaseAuthenticationContex
Assert.assertTrue(ac.getAuthenticationResult().isPreviousResult());
Assert.assertEquals(ts.getMillis(), ac.getAuthenticationResult().getAuthenticationInstant());
}
-
+
+ @Test public void testAuthnAuthorities() {
+ final AuthenticationContext ac = prc.getSubcontext(AuthenticationContext.class);
+ final ExternalAuthenticationContext eac = ac.getSubcontext(ExternalAuthenticationContext.class, true);
+ eac.setPrincipalName("foo");
+ eac.getAuthenticatingAuthorities().addAll(Arrays.asList("foo", "bar", "baz"));
+ eac.setPreviousResult(true);
+
+ final Event event = action.execute(src);
+ ActionTestingSupport.assertProceedEvent(event);
+ Assert.assertNotNull(ac.getAuthenticationResult());
+ Assert.assertTrue(ac.getAuthenticationResult().isPreviousResult());
+ final Set<ProxyAuthenticationPrincipal> prin =
+ ac.getAuthenticationResult().getSubject().getPrincipals(ProxyAuthenticationPrincipal.class);
+ Assert.assertEquals(prin.size(), 1);
+ Assert.assertEquals(prin.iterator().next().getAuthorities(), Arrays.asList("foo", "bar", "baz"));
+ }
+
@Test public void testException() {
final AuthenticationContext ac = prc.getSubcontext(AuthenticationContext.class);
final ExternalAuthenticationContext eac = ac.getSubcontext(ExternalAuthenticationContext.class, true);
diff --git a/idp-conf/src/main/resources/system/conf/general-authn-system.xml b/idp-conf/src/main/resources/system/conf/general-authn-system.xml
index dc00594..47d7d52 100644
--- a/idp-conf/src/main/resources/system/conf/general-authn-system.xml
+++ b/idp-conf/src/main/resources/system/conf/general-authn-system.xml
@@ -57,6 +57,7 @@
<bean class="net.shibboleth.idp.authn.principal.impl.IdPAttributePrincipalSerializer" />
<bean class="net.shibboleth.idp.authn.principal.impl.PasswordPrincipalSerializer"
p:dataSealer="#{'%{idp.sealer.storeResource:}'.trim().length() > 0 ? getObject('shibboleth.DataSealer') : null}" />
+ <bean class="net.shibboleth.idp.authn.principal.impl.ProxyAuthenticationPrincipalSerializer" />
</list>
</property>
</bean>
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnStatementToAssertion.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnStatementToAssertion.java
index 760d87c..ec2c9e5 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnStatementToAssertion.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnStatementToAssertion.java
@@ -18,6 +18,7 @@
package net.shibboleth.idp.saml.saml2.profile.impl;
import java.security.Principal;
+import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -25,6 +26,7 @@ import javax.annotation.Nullable;
import net.shibboleth.idp.authn.context.AuthenticationContext;
import net.shibboleth.idp.authn.context.RequestedPrincipalContext;
import net.shibboleth.idp.authn.principal.DefaultPrincipalDeterminationStrategy;
+import net.shibboleth.idp.authn.principal.ProxyAuthenticationPrincipal;
import org.opensaml.profile.action.ActionSupport;
import org.opensaml.profile.action.EventIds;
@@ -45,6 +47,7 @@ import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
import org.opensaml.saml.common.SAMLObjectBuilder;
import org.opensaml.saml.saml2.core.SubjectLocality;
import org.opensaml.saml.saml2.core.Assertion;
+import org.opensaml.saml.saml2.core.AuthenticatingAuthority;
import org.opensaml.saml.saml2.core.AuthnContext;
import org.opensaml.saml.saml2.core.AuthnStatement;
import org.opensaml.saml.saml2.core.Response;
@@ -165,6 +168,7 @@ public class AddAuthnStatementToAssertion extends BaseAddAuthenticationStatement
log.debug("{} Added AuthenticationStatement to Assertion {}", getLogPrefix(), assertion.getID());
}
+// Checkstyle: CyclomaticComplexity OFF
/**
* Build the {@link AuthnStatement} to be added to the {@link Response}.
*
@@ -208,6 +212,24 @@ public class AddAuthnStatementToAssertion extends BaseAddAuthenticationStatement
classRefLookupStrategy.apply(profileRequestContext).getAuthnContextClassRef());
}
+ final Set<ProxyAuthenticationPrincipal> proxyPrincipals =
+ getAuthenticationResult().getSubject().getPrincipals(ProxyAuthenticationPrincipal.class);
+ if (proxyPrincipals != null && !proxyPrincipals.isEmpty()) {
+ if (proxyPrincipals.size() == 1) {
+ final SAMLObjectBuilder<AuthenticatingAuthority> authorityBuilder =
+ (SAMLObjectBuilder<AuthenticatingAuthority>) bf.<AuthenticatingAuthority>getBuilderOrThrow(
+ AuthenticatingAuthority.DEFAULT_ELEMENT_NAME);
+ for (final String authority : proxyPrincipals.iterator().next().getAuthorities()) {
+ final AuthenticatingAuthority aa = authorityBuilder.buildObject();
+ aa.setURI(authority);
+ authnContext.getAuthenticatingAuthorities().add(aa);
+ }
+ } else {
+ log.warn("{} Multiple ProxyAuthenticationPrincipals, skipping AuthenticatingAuthority population",
+ getLogPrefix());
+ }
+ }
+
if (sessionLifetimeLookupStrategy != null) {
final Long lifetime = sessionLifetimeLookupStrategy.apply(profileRequestContext);
if (lifetime != null && lifetime > 0) {
@@ -227,6 +249,7 @@ public class AddAuthnStatementToAssertion extends BaseAddAuthenticationStatement
return statement;
}
+// Checkstyle: CyclomaticComplexity ON
/**
* Default strategy for obtaining assertion to modify.
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnStatementToAssertionTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnStatementToAssertionTest.java
index 9c3d813..f11b5d6 100644
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnStatementToAssertionTest.java
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnStatementToAssertionTest.java
@@ -17,12 +17,15 @@
package net.shibboleth.idp.saml.saml2.profile.impl;
+import java.util.Arrays;
+
import javax.security.auth.Subject;
import net.shibboleth.idp.authn.AuthenticationResult;
import net.shibboleth.idp.authn.AuthnEventIds;
import net.shibboleth.idp.authn.context.AuthenticationContext;
import net.shibboleth.idp.authn.context.RequestedPrincipalContext;
+import net.shibboleth.idp.authn.principal.ProxyAuthenticationPrincipal;
import net.shibboleth.idp.profile.ActionTestingSupport;
import org.opensaml.profile.action.EventIds;
@@ -69,13 +72,13 @@ public class AddAuthnStatementToAssertionTest extends OpenSAMLInitBaseTestCase {
}
/** Test that the action errors out properly if there is no authentication context. */
- @Test public void testNoAuthnContext() throws Exception {
+ @Test public void testNoAuthnContext() {
final Event event = action.execute(rc);
ActionTestingSupport.assertEvent(event, AuthnEventIds.INVALID_AUTHN_CTX);
}
/** Test that the action errors out properly if there is no relying party context. */
- @Test public void testNoRelyingPartyContext() throws Exception {
+ @Test public void testNoRelyingPartyContext() {
prc.getSubcontext(AuthenticationContext.class, true);
prc.removeSubcontext(RelyingPartyContext.class);
@@ -84,7 +87,7 @@ public class AddAuthnStatementToAssertionTest extends OpenSAMLInitBaseTestCase {
}
/** Test that the action errors out properly if there is no context. */
- @Test public void testNoContext() throws Exception {
+ @Test public void testNoContext() {
prc.setOutboundMessageContext(null);
prc.getSubcontext(AuthenticationContext.class, true).setAuthenticationResult(
new AuthenticationResult("Test", new AuthnContextClassRefPrincipal("Test")));
@@ -101,8 +104,9 @@ public class AddAuthnStatementToAssertionTest extends OpenSAMLInitBaseTestCase {
ActionTestingSupport.assertEvent(event, AuthnEventIds.INVALID_AUTHN_CTX);
}
- /** Test that the authentication statement is properly added. */
- @Test public void testAddAuthenticationStatement() throws Exception {
+ /** Test that the authentication statement is properly added.
+ * @throws InterruptedException */
+ @Test public void testAddAuthenticationStatement() throws InterruptedException {
final long now = System.currentTimeMillis();
// this is here to allow the event's creation time to deviate from the 'start' time
Thread.sleep(50);
@@ -138,10 +142,11 @@ public class AddAuthnStatementToAssertionTest extends OpenSAMLInitBaseTestCase {
Assert.assertNotNull(authnContext);
Assert.assertNotNull(authnContext.getAuthnContextClassRef());
Assert.assertEquals(authnContext.getAuthnContextClassRef().getAuthnContextClassRef(), "Test");
+ Assert.assertTrue(authnContext.getAuthenticatingAuthorities().isEmpty());
}
/** Test that the authentication statement is properly added. */
- @Test public void testSessionNotOnOrAfter() throws Exception {
+ @Test public void testSessionNotOnOrAfter() {
final BrowserSSOProfileConfiguration ssoConfig = new BrowserSSOProfileConfiguration();
ssoConfig.setMaximumSPSessionLifetime(60 * 60 * 1000);
ssoConfig.setSecurityConfiguration(new SecurityConfiguration());
@@ -160,7 +165,7 @@ public class AddAuthnStatementToAssertionTest extends OpenSAMLInitBaseTestCase {
}
/** Test that the authentication statement is properly added with the right method. */
- @Test public void testAddAuthenticationStatementAndMethod() throws Exception {
+ @Test public void testAddAuthenticationStatementAndMethod() {
final Subject subject = new Subject();
subject.getPrincipals().add(new AuthnContextClassRefPrincipal("Foo"));
subject.getPrincipals().add(new AuthnContextClassRefPrincipal("Bar"));
@@ -180,7 +185,7 @@ public class AddAuthnStatementToAssertionTest extends OpenSAMLInitBaseTestCase {
Assert.assertEquals(response.getAssertions().size(), 1);
Assert.assertNotNull(response.getAssertions().get(0));
- Assertion assertion = response.getAssertions().get(0);
+ final Assertion assertion = response.getAssertions().get(0);
Assert.assertEquals(assertion.getAuthnStatements().size(), 1);
Assert.assertNotNull(assertion.getAuthnStatements().get(0));
@@ -189,6 +194,25 @@ public class AddAuthnStatementToAssertionTest extends OpenSAMLInitBaseTestCase {
Assert.assertNotNull(authnContext);
Assert.assertNotNull(authnContext.getAuthnContextClassRef());
Assert.assertEquals(authnContext.getAuthnContextClassRef().getAuthnContextClassRef(), "Bar");
+ Assert.assertTrue(authnContext.getAuthenticatingAuthorities().isEmpty());
}
+ @Test public void testAuthenticatingAuthorities() {
+ prc.getSubcontext(AuthenticationContext.class, true).setAuthenticationResult(
+ new AuthenticationResult("Test", new ProxyAuthenticationPrincipal(Arrays.asList("foo", "bar", "baz"))));
+
+ final Event event = action.execute(rc);
+ ActionTestingSupport.assertProceedEvent(event);
+
+ final Response response = (Response) prc.getOutboundMessageContext().getMessage();
+ final Assertion assertion = response.getAssertions().get(0);
+ final AuthnStatement authenticationStatement = assertion.getAuthnStatements().get(0);
+ final AuthnContext authnContext = authenticationStatement.getAuthnContext();
+ Assert.assertNotNull(authnContext);
+ Assert.assertEquals(authnContext.getAuthenticatingAuthorities().size(), 3);
+ Assert.assertEquals(authnContext.getAuthenticatingAuthorities().get(0).getURI(), "foo");
+ Assert.assertEquals(authnContext.getAuthenticatingAuthorities().get(1).getURI(), "bar");
+ Assert.assertEquals(authnContext.getAuthenticatingAuthorities().get(2).getURI(), "baz");
+ }
+
}
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list