[java-idp-plugin-duo] branch dev/JDUO-80 updated: Add passwordless to deprecated class for tests and add more tests.

Scott Cantor cantor.2 at osu.edu
Thu Dec 28 15:36:37 UTC 2023


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

scantor pushed a commit to branch dev/JDUO-80
in repository java-idp-plugin-duo.

View the commit online:
http://git.shibboleth.net/view/?p=java-idp-plugin-duo.git;a=commit;h=0c18d20e0f686f1777a48d953dccaf6898cb4290

The following commit(s) were added to refs/heads/dev/JDUO-80 by this push:
     new 0c18d20e Add passwordless to deprecated class for tests and add more tests.
0c18d20e is described below

commit 0c18d20e0f686f1777a48d953dccaf6898cb4290
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Thu Dec 28 10:36:34 2023 -0500

    Add passwordless to deprecated class for tests and add more tests.
---
 .../plugin/authn/duo/SimpleDuoOIDCIntegration.java |  32 +++++-
 .../authn/duo/impl/AbstractDuoActionTest.java      |   2 +
 .../impl/PopulateDuoAuthenticationContextTest.java | 113 ++++++++++++++++++++-
 3 files changed, 137 insertions(+), 10 deletions(-)

diff --git a/idp-duo-api/src/main/java/net/shibboleth/idp/plugin/authn/duo/SimpleDuoOIDCIntegration.java b/idp-duo-api/src/main/java/net/shibboleth/idp/plugin/authn/duo/SimpleDuoOIDCIntegration.java
index 29add449..c6d80a8a 100644
--- a/idp-duo-api/src/main/java/net/shibboleth/idp/plugin/authn/duo/SimpleDuoOIDCIntegration.java
+++ b/idp-duo-api/src/main/java/net/shibboleth/idp/plugin/authn/duo/SimpleDuoOIDCIntegration.java
@@ -44,9 +44,11 @@ import net.shibboleth.shared.primitive.StringSupport;
  */
 @ThreadSafe
 @Deprecated(forRemoval=true, since="2.1.0")
-public final class SimpleDuoOIDCIntegration 
-            extends AbstractInitializableComponent implements DuoOIDCIntegration {
+public final class SimpleDuoOIDCIntegration extends AbstractInitializableComponent implements DuoOIDCIntegration {
         
+    /** Passwordless indicator. */
+    @GuardedBy("this") private boolean passwordless;
+    
     /** API host. */
     @GuardedBy("this") @NonnullAfterInit @NotEmpty private String apiHost;
     
@@ -76,6 +78,26 @@ public final class SimpleDuoOIDCIntegration
         supportedPrincipals = new Subject();
     }
 
+    /**
+     * Sets whether this integration is suitable for use as a single factor.
+     * 
+     * <p>Defaults to false.</p>
+     * 
+     * @param flag flag to set
+     * 
+     * @since 2.1.0
+     */
+    public synchronized void setPasswordless(final boolean flag) {
+        checkSetterPreconditions();
+        passwordless = flag;
+    }
+    
+    /** {@inheritDoc} */
+    public synchronized boolean isPasswordless() {
+        checkComponentActive();
+        return passwordless;
+    }
+    
     /** {@inheritDoc} */
     @Nonnull @NotEmpty public synchronized String getAPIHost() {
         checkComponentActive();
@@ -235,9 +257,9 @@ public final class SimpleDuoOIDCIntegration
     /** {@inheritDoc} */
     @Override
     protected void doInitialize() throws ComponentInitializationException {
-        if (getAPIHost() == null || getClientId() == null || getSecretKey() == null 
-                ||  getHealthCheckEndpoint() == null || getAuthorizeEndpoint() == null
-                || getTokenEndpoint() == null || getRedirectURI() == null) {
+        if (apiHost == null || clientId == null || secretKey == null 
+                ||  healthEndpoint == null || authorizeEndpoint == null
+                || tokenEndpoint == null || redirectURI == null) {
             throw new ComponentInitializationException("API host, clientId, secret key,"
                     + "token endpoint, health check endpoint, authorization endpoint, and "
                     + "redirectURI must be set");
diff --git a/idp-duo-impl/src/test/java/net/shibboleth/idp/plugin/authn/duo/impl/AbstractDuoActionTest.java b/idp-duo-impl/src/test/java/net/shibboleth/idp/plugin/authn/duo/impl/AbstractDuoActionTest.java
index 40f82746..4adf1333 100644
--- a/idp-duo-impl/src/test/java/net/shibboleth/idp/plugin/authn/duo/impl/AbstractDuoActionTest.java
+++ b/idp-duo-impl/src/test/java/net/shibboleth/idp/plugin/authn/duo/impl/AbstractDuoActionTest.java
@@ -49,6 +49,7 @@ import net.shibboleth.idp.profile.context.navigate.WebflowRequestContextProfileR
 import net.shibboleth.idp.profile.testing.RequestContextBuilder;
 import net.shibboleth.shared.codec.Base64Support;
 import net.shibboleth.shared.codec.EncodingException;
+import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.component.ComponentInitializationException;
 
 
@@ -896,6 +897,7 @@ public abstract class AbstractDuoActionTest {
         integ.setAuthorizeEndpoint(AUTHORIZE_URI);
         integ.setTokenEndpoint(TOKEN_URI);
         integ.setHealthCheckEndpoint(HEALTH_URI);
+        integ.setAllowedOrigins(CollectionSupport.singletonList("https://example.com"));
         //do not initialize so the tests can mutate and initialize if required
         //integ.initialize();
         return integ;
diff --git a/idp-duo-impl/src/test/java/net/shibboleth/idp/plugin/authn/duo/impl/PopulateDuoAuthenticationContextTest.java b/idp-duo-impl/src/test/java/net/shibboleth/idp/plugin/authn/duo/impl/PopulateDuoAuthenticationContextTest.java
index c91c3a06..6b37df43 100644
--- a/idp-duo-impl/src/test/java/net/shibboleth/idp/plugin/authn/duo/impl/PopulateDuoAuthenticationContextTest.java
+++ b/idp-duo-impl/src/test/java/net/shibboleth/idp/plugin/authn/duo/impl/PopulateDuoAuthenticationContextTest.java
@@ -27,6 +27,7 @@ import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import net.shibboleth.idp.authn.AuthnEventIds;
+import net.shibboleth.idp.authn.context.AuthenticationContext;
 import net.shibboleth.idp.plugin.authn.duo.DefaultDuoOIDCIntegration;
 import net.shibboleth.idp.plugin.authn.duo.DuoClientException;
 import net.shibboleth.idp.plugin.authn.duo.DuoOIDCClient;
@@ -35,13 +36,14 @@ import net.shibboleth.idp.plugin.authn.duo.DuoOIDCIntegration;
 import net.shibboleth.idp.plugin.authn.duo.DuoRegistryException;
 import net.shibboleth.idp.plugin.authn.duo.SimpleDuoOIDCIntegration;
 import net.shibboleth.idp.plugin.authn.duo.context.DuoOIDCAuthenticationContext;
+import net.shibboleth.idp.plugin.authn.duo.context.DuoPasswordlessContext;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.testing.ConstantSupplier;
 
 /**
  * Tests for the {@link PopulateDuoAuthenticationContext} strategy.
  */
-public class PopulateDuoAuthenticationContextTest extends AbstractDuoActionTest{
+public class PopulateDuoAuthenticationContextTest extends AbstractDuoActionTest {
 
     /** The action to test. */
     private PopulateDuoAuthenticationContext action;
@@ -80,7 +82,7 @@ public class PopulateDuoAuthenticationContextTest extends AbstractDuoActionTest{
         integ.setAuthorizeEndpoint(AUTHORIZE_URI);
         integ.setTokenEndpoint(TOKEN_URI);
         integ.setHealthCheckEndpoint(HEALTH_URI);
-        
+        integ.initialize();
         
         //set the duo integration strategy to lookup 
         action.setStandardDuoIntegrationLookupStrategy(prc -> integ);
@@ -105,6 +107,53 @@ public class PopulateDuoAuthenticationContextTest extends AbstractDuoActionTest{
         assertEquals(duoContext.getRedirectURIOverride(), null);
     }
     
+    /**
+     * Test successful passwordless execution assuming a client that does not support dynamic redirect URIs.
+     * 
+     * @throws ComponentInitializationException on error.
+     * @throws DuoClientException  on error.
+     * @throws DuoRegistryException one error.
+     */
+    @Test
+    public void testPasswordlessExecuteSuccessWithStaticClient() 
+            throws ComponentInitializationException, DuoRegistryException, DuoClientException {
+        
+        final SimpleDuoOIDCIntegration integ = new SimpleDuoOIDCIntegration();
+        integ.setPasswordless(true);
+        integ.setAPIHost(API_HOST);       
+        integ.setClientId(CLIENT_ID);
+        integ.setRedirectURI("https://simple-static.redirect/");
+        integ.setSecretKey(SECRET);
+        integ.setAuthorizeEndpoint(AUTHORIZE_URI);
+        integ.setTokenEndpoint(TOKEN_URI);
+        integ.setHealthCheckEndpoint(HEALTH_URI);
+        integ.initialize();
+        
+        //set the duo integration strategy to lookup 
+        action.setPasswordlessDuoIntegrationLookupStrategy(prc -> integ);
+
+        action.setHttpServletRequestSupplier(new ConstantSupplier<>(request));
+        final DuoOIDCClientRegistry mockClientRegistry = Mockito.mock(DuoOIDCClientRegistry.class);
+        final DuoOIDCClient mockClient = Mockito.mock(DuoOIDCClient.class);
+        Mockito.when(mockClientRegistry.getClientOrCreate(any(DuoOIDCIntegration.class))).thenReturn(mockClient);
+        
+        action.setClientRegistry(mockClientRegistry);
+        action.initialize();
+
+        final DuoPasswordlessContext passwordlessCtx =
+                prc.ensureSubcontext(AuthenticationContext.class).ensureSubcontext(DuoPasswordlessContext.class);
+        passwordlessCtx.setUsername("jdoe");
+        
+        final Event event = action.execute(src);
+        //success here is a null event
+        assertNull(event);
+        //simple client, so no override set
+        final var duoContext = ac.getSubcontext(DuoOIDCAuthenticationContext.class);
+        assertNotNull(duoContext);
+        assert duoContext != null;
+        assertEquals(duoContext.getRedirectURIOverride(), null);
+    }
+    
     /**
      * Test that should return an authentication exception if the integration is dynamic
      * but a redirectURI strategy has not been set.
@@ -181,9 +230,53 @@ public class PopulateDuoAuthenticationContextTest extends AbstractDuoActionTest{
                 .getRedirectURIOverride(), "https://example.com/idp/profile/Authn/Duo/2FA/callback");
     }
     
-    
-    
-    
+    /**
+     * Test successful execution assuming a client that does not support dynamic redirect URIs.
+     * 
+     * @throws ComponentInitializationException on error.
+     * @throws DuoClientException  on error.
+     * @throws DuoRegistryException one error.
+     */
+    @Test
+    public void testPasswordlessExecuteSuccessWithDynamicClient() 
+            throws ComponentInitializationException, DuoRegistryException, DuoClientException {
+        final DefaultDuoOIDCIntegration integ = createDummyDuoIntegration();
+        integ.setPasswordless(true);
+        //cleanout pre-registered redirect
+        integ.setRegisteredRedirectURI(null);
+        integ.initialize();
+        
+        //set the duo integration strategy to lookup this 
+        action.setPasswordlessDuoIntegrationLookupStrategy(prc -> integ);
+        action.setRedirectURICreationStrategy((http,duoInteg) 
+                -> "https://example.com/idp/profile/Authn/Duo/2FA/callback");
+        action.setHttpServletRequestSupplier(new ConstantSupplier<>(request));
+        //set http params
+        request.addHeader("Host", "example.com");
+        request.setServerPort(443);
+        request.setScheme("https");
+        //mock
+        final DuoOIDCClientRegistry mockClientRegistry = Mockito.mock(DuoOIDCClientRegistry.class);
+        final DuoOIDCClient mockClient = Mockito.mock(DuoOIDCClient.class);
+        Mockito.when(mockClientRegistry.getClientOrCreate(any(DuoOIDCIntegration.class))).thenReturn(mockClient);
+      
+        action.setClientRegistry(mockClientRegistry);
+        action.initialize();
+        
+        final DuoPasswordlessContext passwordlessCtx =
+                prc.ensureSubcontext(AuthenticationContext.class).ensureSubcontext(DuoPasswordlessContext.class);
+        passwordlessCtx.setUsername("jdoe");
+        
+        final Event event = action.execute(src);
+        //success here is a null event
+        assertNull(event);
+        assertEquals(integ.getRedirectURI(), "https://example.com/idp/profile/Authn/Duo/2FA/callback");
+        final var duoContext = ac.getSubcontext(DuoOIDCAuthenticationContext.class);
+        assertNotNull(duoContext);
+        assert duoContext != null;
+        assertEquals(duoContext
+                .getRedirectURIOverride(), "https://example.com/idp/profile/Authn/Duo/2FA/callback");
+    }
     
     /**
      * Test unsuccessful execution if there is no duo integration specified.
@@ -233,6 +326,8 @@ public class PopulateDuoAuthenticationContextTest extends AbstractDuoActionTest{
     public void testExecuteNullUsername() throws ComponentInitializationException, 
             DuoRegistryException, DuoClientException {
         final DefaultDuoOIDCIntegration integ = createDummyDuoIntegration();
+        integ.initialize();
+        
         //set the duo integration strategy to lookup this 
         action.setStandardDuoIntegrationLookupStrategy(prc -> integ);
         //lookup a username
@@ -259,6 +354,8 @@ public class PopulateDuoAuthenticationContextTest extends AbstractDuoActionTest{
     public void testExecuteNullRedirectURI() throws ComponentInitializationException, 
             DuoRegistryException, DuoClientException {
         final DefaultDuoOIDCIntegration integ = createDummyDuoIntegration();
+        integ.initialize();
+        
         //set the duo integration strategy to lookup this 
         action.setStandardDuoIntegrationLookupStrategy(prc -> integ);
         //lookup a username
@@ -284,6 +381,8 @@ public class PopulateDuoAuthenticationContextTest extends AbstractDuoActionTest{
     public void testExecuteClientException() throws ComponentInitializationException, 
             DuoRegistryException, DuoClientException {
         final DefaultDuoOIDCIntegration integ = createDummyDuoIntegration();
+        integ.initialize();
+        
         //set the duo integration strategy to lookup this 
         action.setStandardDuoIntegrationLookupStrategy(prc -> integ);
         //lookup a username
@@ -313,6 +412,8 @@ public class PopulateDuoAuthenticationContextTest extends AbstractDuoActionTest{
     public void testExecuteNoHttpRequest() throws ComponentInitializationException, 
             DuoRegistryException, DuoClientException {
         final DefaultDuoOIDCIntegration integ = createDummyDuoIntegration();
+        integ.initialize();
+
         //set the duo integration strategy to lookup this 
         action.setStandardDuoIntegrationLookupStrategy(prc -> integ);
         //lookup a username
@@ -343,6 +444,8 @@ public class PopulateDuoAuthenticationContextTest extends AbstractDuoActionTest{
     public void testExecuteNoDuoContext() throws ComponentInitializationException, 
             DuoRegistryException, DuoClientException {
         final DefaultDuoOIDCIntegration integ = createDummyDuoIntegration();
+        integ.initialize();
+
         //set the duo integration strategy to lookup this 
         action.setStandardDuoIntegrationLookupStrategy(prc -> integ);
         //lookup a username

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


More information about the commits mailing list