[java-identity-provider] branch master updated: IDP-1266 - RFE to deployer-constructed RequestedPrincipalContext

Scott Cantor cantor.2 at osu.edu
Tue Sep 4 17:47:09 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=1850ece08f838d668b5fb2eeb4dd82aacca2114f

The following commit(s) were added to refs/heads/master by this push:
       new  1850ece   IDP-1266 - RFE to deployer-constructed RequestedPrincipalContext
1850ece is described below

commit 1850ece08f838d668b5fb2eeb4dd82aacca2114f
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Sep 4 17:47:07 2018 -0400

    IDP-1266 - RFE to deployer-constructed RequestedPrincipalContext
    
    https://issues.shibboleth.net/jira/browse/IDP-1266
---
 .../idp/authn/context/AuthenticationContext.java   | 132 ++++++++++++++++++---
 .../authn/context/AuthenticationContextTest.java   |  50 +++++++-
 2 files changed, 161 insertions(+), 21 deletions(-)

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 e6d1388..a88bbbc 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
@@ -17,10 +17,14 @@
 
 package net.shibboleth.idp.authn.context;
 
+import java.lang.reflect.Constructor;
 import java.security.Principal;
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 
 import javax.annotation.Nonnull;
@@ -45,6 +49,8 @@ import org.opensaml.profile.context.ProfileRequestContext;
 
 import com.google.common.base.Function;
 import com.google.common.base.MoreObjects;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Collections2;
 
 /**
  * A context representing the state of an authentication attempt, this is the primary
@@ -91,11 +97,7 @@ public final class AuthenticationContext extends BaseContext {
     /** Previously attempted flows (could be failures or intermediate results). */
     @Nonnull @NonnullElements private final Map<String,AuthenticationFlowDescriptor> intermediateFlows;
     
-    /**
-     * Old copy of registry, moved to {@link RequestedPrincipalContext}.
-     * 
-     * @deprecated
-     */
+    /** Instance of registry used for auto-creation of {@link RequestedPrincipalContext}. */
     @Nullable private PrincipalEvalPredicateFactoryRegistry evalRegistry;
     
     /** Authentication flow being attempted to authenticate the user. */
@@ -215,12 +217,11 @@ public final class AuthenticationContext extends BaseContext {
     /**
      * Get the registry of predicate factories for custom principal evaluation.
      * 
-     * <p>This object is only needed when evaluating a {@link RequestedPrincipalContext}, so the
-     * presence of it at this level of the tree is historical.</p>
+     * <p>This object is only needed when evaluating a {@link RequestedPrincipalContext}, so the presence of it at
+     * this level of the tree is solely for use by the {@link #addRequestedPrincipalContext(String, List, boolean)}
+     * helper method.</p>
      * 
      * @return predicate factory registry
-     * 
-     * @deprecated Use {@link RequestedPrincipalContext#getPrincipalEvalPredicateFactoryRegistry()} instead.
      */
     @Nonnull public PrincipalEvalPredicateFactoryRegistry getPrincipalEvalPredicateFactoryRegistry() {
         
@@ -235,22 +236,27 @@ public final class AuthenticationContext extends BaseContext {
     }
 
     /**
-     * Set the registry of predicate factories for custom principal evaluation.
+     * Set the registry of predicate factories for custom principal evaluation to inject into instances of
+     * {@link RequestedPrincipalContext} created via the {@link #addRequestedPrincipalContext(String, List, boolean)}
+     * helper method.
+     * 
+     * <p>It also propagates this object into any existing {@link RequestedPrincipalContext} subcontext.</p>
      * 
      * @param registry predicate factory registry
      * 
-     * @deprecated Use {@link RequestedPrincipalContext#setPrincipalEvalPredicateFactoryRegistry(
-     * PrincipalEvalPredicateFactoryRegistry)} instead.
+     * @return this context
      */
-    public void setPrincipalEvalPredicateFactoryRegistry(
+    @Nonnull public AuthenticationContext setPrincipalEvalPredicateFactoryRegistry(
             @Nullable final PrincipalEvalPredicateFactoryRegistry registry) {
         
+        evalRegistry = registry;
+        
         final RequestedPrincipalContext rpCtx = getSubcontext(RequestedPrincipalContext.class);
         if (rpCtx != null) {
             rpCtx.setPrincipalEvalPredicateFactoryRegistry(registry);
-        } else {
-            evalRegistry = registry;
         }
+        
+        return this;
     }
     
     /**
@@ -601,6 +607,102 @@ public final class AuthenticationContext extends BaseContext {
             return true;
         }
     }
+
+    /**
+     * Add (or replace) a {@link RequestedPrincipalContext} as a child of this context using the
+     * supplied parameters and the previously established {@link PrincipalEvalPredicateFactoryRegistry}
+     * for comparison handling.
+     * 
+     * @param operator matching operator
+     * @param className name of class to wrap principal names
+     * @param principal name of principal to request
+     * @param replace whether to replace an existing context or simply return false
+     * 
+     * @return true iff a new context was created
+     * 
+     * @throws Exception if the principal class can't be loaded or instantiated as required
+     */
+    public boolean addRequestedPrincipalContext(@Nonnull @NotEmpty final String operator,
+            @Nonnull @NotEmpty final String className, @Nonnull @NotEmpty final String principal,
+            final boolean replace) throws Exception {
+        
+        return addRequestedPrincipalContext(operator, className, Collections.singletonList(principal), replace);
+    }
+    
+    /**
+     * Add (or replace) a {@link RequestedPrincipalContext} as a child of this context using the
+     * supplied parameters and the previously established {@link PrincipalEvalPredicateFactoryRegistry}
+     * for comparison handling.
+     * 
+     * @param operator matching operator
+     * @param className name of class to wrap principal names
+     * @param principals names of principals to request
+     * @param replace whether to replace an existing context or simply return false
+     * 
+     * @return true iff a new context was created
+     * 
+     * @throws Exception if the principal class can't be loaded or instantiated as required
+     */
+    public boolean addRequestedPrincipalContext(@Nonnull @NotEmpty final String operator,
+            @Nonnull @NotEmpty final String className, @Nonnull final Collection<String> principals,
+            final boolean replace) throws Exception {
+        
+        final Class<? extends Principal> claz = Class.forName(className).asSubclass(Principal.class);
+        final Constructor<? extends Principal> ctor = claz.getConstructor(String.class);
+        
+        final List<Principal> prins = new ArrayList<>(principals.size());
+        for (final String prin : Collections2.filter(principals, Predicates.notNull())) {
+            prins.add(ctor.newInstance(prin));
+        }
+        
+        return addRequestedPrincipalContext(operator, prins, replace);
+    }
+
+    /**
+     * Add (or replace) a {@link RequestedPrincipalContext} as a child of this context using the
+     * supplied parameters and the previously established {@link PrincipalEvalPredicateFactoryRegistry}
+     * for comparison handling.
+     * 
+     * @param operator matching operator
+     * @param principal principal to request
+     * @param replace whether to replace an existing context or simply return false
+     * 
+     * @return true iff a new context was created
+     */
+    public boolean addRequestedPrincipalContext(@Nonnull @NotEmpty final String operator,
+            @Nonnull final Principal principal, final boolean replace) {
+        
+        return addRequestedPrincipalContext(operator, Collections.singletonList(principal), replace);
+    }
+    
+    /**
+     * Add (or replace) a {@link RequestedPrincipalContext} as a child of this context using the
+     * supplied parameters and the previously established {@link PrincipalEvalPredicateFactoryRegistry}
+     * for comparison handling.
+     * 
+     * @param operator matching operator
+     * @param principals principals to request
+     * @param replace whether to replace an existing context or simply return false
+     * 
+     * @return true iff a new context was created
+     */
+    public boolean addRequestedPrincipalContext(@Nonnull @NotEmpty final String operator,
+            @Nonnull @NonnullElements final List<Principal> principals, final boolean replace) {
+        
+        RequestedPrincipalContext rpCtx = getSubcontext(RequestedPrincipalContext.class);
+        if (rpCtx != null && !replace) {
+            return false;
+        }
+        
+        rpCtx = new RequestedPrincipalContext();
+        rpCtx.setOperator(operator)
+            .setPrincipalEvalPredicateFactoryRegistry(evalRegistry)
+            .setRequestedPrincipals(principals);
+        
+        addSubcontext(rpCtx, true);
+        
+        return true;
+    }
     
     /** {@inheritDoc} */
     @Override
diff --git a/idp-authn-api/src/test/java/net/shibboleth/idp/authn/context/AuthenticationContextTest.java b/idp-authn-api/src/test/java/net/shibboleth/idp/authn/context/AuthenticationContextTest.java
index 60405fd..e7cb816 100644
--- a/idp-authn-api/src/test/java/net/shibboleth/idp/authn/context/AuthenticationContextTest.java
+++ b/idp-authn-api/src/test/java/net/shibboleth/idp/authn/context/AuthenticationContextTest.java
@@ -18,20 +18,24 @@
 package net.shibboleth.idp.authn.context;
 
 import java.util.Arrays;
+import java.util.Collections;
 
 import javax.security.auth.Subject;
 
 import net.shibboleth.idp.authn.AuthenticationFlowDescriptor;
 import net.shibboleth.idp.authn.AuthenticationResult;
+import net.shibboleth.idp.authn.principal.PrincipalEvalPredicateFactoryRegistry;
+import net.shibboleth.idp.authn.principal.TestPrincipal;
 
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
 /** {@link AuthenticationContext} unit test. */
+ at Test
 public class AuthenticationContextTest {
 
     /** Tests initiation instant instantiation. */
-    @Test public void testInitiationInstant() throws Exception {
+    public void testInitiationInstant() throws Exception {
         long start = System.currentTimeMillis();
         // this is here to allow the event's creation time to deviate from the 'start' time
         Thread.sleep(50);
@@ -41,7 +45,7 @@ public class AuthenticationContextTest {
     }
 
     /** Tests mutating forcing authentication. */
-    @Test public void testForcingAuthentication() throws Exception {
+    public void testForcingAuthentication() throws Exception {
         AuthenticationContext ctx = new AuthenticationContext();
         Assert.assertFalse(ctx.isForceAuthn());
 
@@ -50,7 +54,7 @@ public class AuthenticationContextTest {
     }
 
     /** Tests active results. */
-    @Test public void testActiveResults() throws Exception {
+    public void testActiveResults() throws Exception {
         final AuthenticationResult result = new AuthenticationResult("test", new Subject());
 
         final AuthenticationContext ctx = new AuthenticationContext();
@@ -63,7 +67,7 @@ public class AuthenticationContextTest {
     }
     
     /** Tests potential flow instantiation. */
-    @Test public void testPotentialFlows() throws Exception {
+    public void testPotentialFlows() throws Exception {
         AuthenticationContext ctx = new AuthenticationContext();
         Assert.assertTrue(ctx.getPotentialFlows().isEmpty());
 
@@ -76,7 +80,7 @@ public class AuthenticationContextTest {
     }
 
     /** Tests mutating attempted flow. */
-    @Test public void testAttemptedFlow() throws Exception {
+    public void testAttemptedFlow() throws Exception {
         final AuthenticationContext ctx = new AuthenticationContext();
         Assert.assertNull(ctx.getAttemptedFlow());
 
@@ -87,7 +91,7 @@ public class AuthenticationContextTest {
     }
 
     /** Tests setting completion instant. */
-    @Test public void testCompletionInstant() throws Exception {
+    public void testCompletionInstant() throws Exception {
         final AuthenticationContext ctx = new AuthenticationContext();
         Assert.assertEquals(ctx.getCompletionInstant(), 0);
 
@@ -99,4 +103,38 @@ public class AuthenticationContextTest {
         Assert.assertTrue(ctx.getCompletionInstant() > now);
     }
     
+    /** Tests RequestedPrincipalContext helpers. */
+    public void testRequestedPrincipalContextHelpers() throws Exception {
+        final AuthenticationContext ctx = new AuthenticationContext();
+        ctx.setPrincipalEvalPredicateFactoryRegistry(new PrincipalEvalPredicateFactoryRegistry());
+        
+        ctx.addRequestedPrincipalContext("foo", new TestPrincipal("bar"), false);
+        RequestedPrincipalContext rpCtx = ctx.getSubcontext(RequestedPrincipalContext.class);
+        Assert.assertNotNull(rpCtx);
+        Assert.assertEquals(rpCtx.getOperator(), "foo");
+        Assert.assertEquals(rpCtx.getRequestedPrincipals(), Collections.singletonList(new TestPrincipal("bar")));
+        
+        Assert.assertFalse(ctx.addRequestedPrincipalContext("foo", new TestPrincipal("bar"), false));
+        
+        ctx.addRequestedPrincipalContext("fob", TestPrincipal.class.getName(), "baz", true);
+        rpCtx = ctx.getSubcontext(RequestedPrincipalContext.class);
+        Assert.assertNotNull(rpCtx);
+        Assert.assertEquals(rpCtx.getOperator(), "fob");
+        Assert.assertEquals(rpCtx.getRequestedPrincipals(), Collections.singletonList(new TestPrincipal("baz")));
+
+        ctx.addRequestedPrincipalContext("fog", TestPrincipal.class.getName(), Arrays.asList("baf", "bag"), true);
+        rpCtx = ctx.getSubcontext(RequestedPrincipalContext.class);
+        Assert.assertNotNull(rpCtx);
+        Assert.assertEquals(rpCtx.getOperator(), "fog");
+        Assert.assertEquals(rpCtx.getRequestedPrincipals().size(), 2);
+    }
+    
+    @Test(expectedExceptions = ClassCastException.class)
+    public void testRequestedPrincipalContextHelperBadType() throws Exception {
+        final AuthenticationContext ctx = new AuthenticationContext();
+        ctx.setPrincipalEvalPredicateFactoryRegistry(new PrincipalEvalPredicateFactoryRegistry());
+        
+        ctx.addRequestedPrincipalContext("fob", AuthenticationContext.class.getName(), "baz", false);
+    }
+    
 }
\ 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