[java-idp-plugin-duo] branch main updated: JDUO-81 - Enhance per-integration capabilites for Subject manipulation

Scott Cantor cantor.2 at osu.edu
Wed Apr 24 15:54:08 UTC 2024


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

scantor pushed a commit to branch main
in repository java-idp-plugin-duo.

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

The following commit(s) were added to refs/heads/main by this push:
     new 56f57611 JDUO-81 - Enhance per-integration capabilites for Subject manipulation
56f57611 is described below

commit 56f57611ddbbf2ce20e7c19da7b91d535d7a73ad
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Wed Apr 24 11:54:05 2024 -0400

    JDUO-81 - Enhance per-integration capabilites for Subject manipulation
    
    https://shibboleth.atlassian.net/browse/JDUO-81
---
 .../authn/duo/DefaultDuoOIDCIntegration.java       | 37 +++++++++++++++++++---
 .../idp/plugin/authn/duo/DuoOIDCIntegration.java   | 20 ++++++++++++
 .../impl/ValidateDuoTokenAuthenticationResult.java | 19 +++++++++--
 3 files changed, 69 insertions(+), 7 deletions(-)

diff --git a/idp-duo-api/src/main/java/net/shibboleth/idp/plugin/authn/duo/DefaultDuoOIDCIntegration.java b/idp-duo-api/src/main/java/net/shibboleth/idp/plugin/authn/duo/DefaultDuoOIDCIntegration.java
index 936df113..6175eeb4 100644
--- a/idp-duo-api/src/main/java/net/shibboleth/idp/plugin/authn/duo/DefaultDuoOIDCIntegration.java
+++ b/idp-duo-api/src/main/java/net/shibboleth/idp/plugin/authn/duo/DefaultDuoOIDCIntegration.java
@@ -18,6 +18,7 @@ import java.security.Principal;
 import java.util.Collection;
 import java.util.Objects;
 import java.util.Set;
+import java.util.function.Function;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -25,6 +26,7 @@ import javax.annotation.concurrent.GuardedBy;
 import javax.annotation.concurrent.ThreadSafe;
 import javax.security.auth.Subject;
 
+import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
 
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
@@ -90,6 +92,10 @@ public final class DefaultDuoOIDCIntegration
     
     /** Container for supported principals. */
     @GuardedBy("this") @Nonnull private final Subject supportedPrincipals;
+    
+    /** Hook to map context information to principal collections.*/
+    @GuardedBy("this") @Nullable private Function<ProfileRequestContext,Collection<Principal>>
+    contextToPrincipalMappingStrategy;
 
     /** Constructor. */
     public DefaultDuoOIDCIntegration() {
@@ -315,22 +321,45 @@ public final class DefaultDuoOIDCIntegration
      */
     public synchronized <T extends Principal> void setSupportedPrincipals(
             @Nullable @NonnullElements final Collection<T> principals) {
-        checkSetterPreconditions();         
+        checkSetterPreconditions();
         supportedPrincipals.getPrincipals().clear();
         
         if (principals != null && !principals.isEmpty()) {
             supportedPrincipals.getPrincipals().addAll(Set.copyOf(principals));
         }
     }
-
+    
+    /**
+     * Set the context to principal mapping strategy for mapping context information into 
+     * principal collections.
+     * 
+     * @param hook principal mapping hook
+     */
+    public void setContextToPrincipalMappingStrategy(
+            @Nullable final Function<ProfileRequestContext,Collection<Principal>> hook) {
+        checkSetterPreconditions();
+        
+        contextToPrincipalMappingStrategy = hook;
+    }
+    
+    /**
+     * Get the context to principal mapping strategy for mapping context information into 
+     * principal collections.
+     * 
+     * @return the mapping hook
+     */
+    @Nullable public Function<ProfileRequestContext,Collection<Principal>> getContextToPrincipalMappingStrategy() {
+        checkComponentActive();
+        return contextToPrincipalMappingStrategy;
+    }
+    
     /** {@inheritDoc} */
     @Override
     protected void doInitialize() throws ComponentInitializationException {
         synchronized (this) {
             if (apiHost == null || clientId == null || secretKey == null 
                     ||  healthEndpoint == null || authorizeEndpoint == null
-                    || tokenEndpoint == null || (registeredRedirectURI == null 
-                    && allowedOrigins.isEmpty())) {
+                    || tokenEndpoint == null || (registeredRedirectURI == null && allowedOrigins.isEmpty())) {
                 throw new ComponentInitializationException("API host, clientId, secret key,"
                         + "token endpoint, health check endpoint, authorization endpoint, and one of "
                         + "redirectURI or allowed redirect URI origins must be set");
diff --git a/idp-duo-api/src/main/java/net/shibboleth/idp/plugin/authn/duo/DuoOIDCIntegration.java b/idp-duo-api/src/main/java/net/shibboleth/idp/plugin/authn/duo/DuoOIDCIntegration.java
index 4bf6ec95..f48896fe 100644
--- a/idp-duo-api/src/main/java/net/shibboleth/idp/plugin/authn/duo/DuoOIDCIntegration.java
+++ b/idp-duo-api/src/main/java/net/shibboleth/idp/plugin/authn/duo/DuoOIDCIntegration.java
@@ -14,10 +14,16 @@
 
 package net.shibboleth.idp.plugin.authn.duo;
 
+import java.security.Principal;
+import java.util.Collection;
 import java.util.Set;
+import java.util.function.Function;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
+import javax.security.auth.Subject;
+
+import org.opensaml.profile.context.ProfileRequestContext;
 
 import net.shibboleth.idp.authn.principal.PrincipalSupportingComponent;
 import net.shibboleth.shared.annotation.constraint.NonnullElements;
@@ -105,5 +111,19 @@ public interface DuoOIDCIntegration extends PrincipalSupportingComponent {
     default @Nullable @NonnullElements @Unmodifiable @NotLive Set<String> getAllowedFactors() {
         return null;
     }
+ 
     
+    /**
+     * Get a context to principal mapping strategy for mapping context information into 
+     * principal collections to insert into {@link Subject}.
+     * 
+     * @return the mapping hook or null
+     * 
+     * @since 2.1.0
+     */
+    default @Nullable public Function<ProfileRequestContext,Collection<Principal>> 
+                getContextToPrincipalMappingStrategy() {
+        return null;
+    }
+        
 }
\ No newline at end of file
diff --git a/idp-duo-impl/src/main/java/net/shibboleth/idp/plugin/authn/duo/impl/ValidateDuoTokenAuthenticationResult.java b/idp-duo-impl/src/main/java/net/shibboleth/idp/plugin/authn/duo/impl/ValidateDuoTokenAuthenticationResult.java
index 7c7d71ea..4890178c 100644
--- a/idp-duo-impl/src/main/java/net/shibboleth/idp/plugin/authn/duo/impl/ValidateDuoTokenAuthenticationResult.java
+++ b/idp-duo-impl/src/main/java/net/shibboleth/idp/plugin/authn/duo/impl/ValidateDuoTokenAuthenticationResult.java
@@ -307,9 +307,22 @@ public class ValidateDuoTokenAuthenticationResult extends AbstractAuditingValida
         // Always add any principals specified on the integration
         subject.getPrincipals().addAll(duoIntegration.getSupportedPrincipals(Principal.class));
         
-        // add any further principals from a function hook that can inspect the Duo response if the
-        // mapping strategy is set.
-        final var contextToPrincipalStrategy = getContextToPrincipalMappingStrategy();
+        // Add any further principals from a function hook that can inspect the Duo response if the
+        // mapping strategy is set. Both per-integration and global strategies are supported.
+        
+        var contextToPrincipalStrategy = duoIntegration.getContextToPrincipalMappingStrategy();
+        if (contextToPrincipalStrategy != null) {
+            final Collection<Principal> mapped = contextToPrincipalStrategy.apply(prc);
+            if (mapped != null) {
+                subject.getPrincipals().addAll(mapped);
+                if (log.isDebugEnabled()) {
+                    log.debug("{} Added mapped Principals: {}", getLogPrefix(),
+                            mapped.stream().map(Principal::getName).collect(Collectors.toUnmodifiableList()));
+                }
+            }
+        }
+        
+        contextToPrincipalStrategy = getContextToPrincipalMappingStrategy();
         if (contextToPrincipalStrategy != null) {
             final Collection<Principal> mapped = contextToPrincipalStrategy.apply(prc);
             if (mapped != null) {

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


More information about the commits mailing list