[java-identity-provider] branch main updated: IDP-2309 - External Authn API should support direct event signaling

Scott Cantor cantor.2 at osu.edu
Wed Mar 5 21:03:04 UTC 2025


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

scantor pushed a commit to branch main
in repository java-identity-provider.

View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=221e8b1af84ca1840e3270e7420d17f7be18f756

The following commit(s) were added to refs/heads/main by this push:
     new 221e8b1af IDP-2309 - External Authn API should support direct event signaling
221e8b1af is described below

commit 221e8b1af84ca1840e3270e7420d17f7be18f756
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Wed Mar 5 16:03:01 2025 -0500

    IDP-2309 - External Authn API should support direct event signaling
    
    https://shibboleth.atlassian.net/browse/IDP-2309
---
 .../idp/authn/ExternalAuthentication.java          |  7 ++++
 .../context/ExternalAuthenticationContext.java     | 31 +++++++++++++++-
 .../idp/authn/impl/ExternalAuthenticationImpl.java |  7 +++-
 .../authn/impl/ValidateExternalAuthentication.java | 15 +++++++-
 .../impl/ValidateExternalAuthenticationTest.java   | 42 +++++++++++++++++++++-
 5 files changed, 98 insertions(+), 4 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 fe356a011..91bdb03c6 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
@@ -78,6 +78,13 @@ public abstract class ExternalAuthentication {
     /** Request attribute to which an exception may be bound. */
     @Nonnull @NotEmpty public static final String AUTHENTICATION_EXCEPTION_KEY = "authnException";
 
+    /**
+     * Request attribute to which a webflow event may be bound.
+     * 
+     * @since 5.2.0
+     */
+    @Nonnull @NotEmpty public static final String AUTHENTICATION_EVENT_KEY = "authnEvent";
+
     /** Request attribute to which a signal not to cache the result may be bound. */
     @Nonnull @NotEmpty public static final String DONOTCACHE_KEY = "doNotCache";
 
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 ee8c122a3..781570349 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
@@ -64,7 +64,10 @@ public final class ExternalAuthenticationContext extends BaseContext {
     
     /** Exception. */
     @Nullable private Exception authnException;
-    
+
+    /** Event. */
+    @Nullable private String authnEvent;
+
     /** Flag preventing caching of result for SSO. */
     private boolean doNotCache;
     
@@ -258,6 +261,32 @@ public final class ExternalAuthenticationContext extends BaseContext {
         return this;
     }
     
+    /**
+     * Get a Spring Web Flow event from the authentication process.
+     * 
+     * @return an event string
+     * 
+     * @since 5.2.0
+     */
+    @Nullable public String getAuthnEvent() {
+        return authnEvent;
+    }
+
+    /**
+     * Set a Spring Web Flow event from the authentication process.
+     * 
+     * @param event event to set
+     * 
+     * @return this context
+     * 
+     * @since 5.2.0
+     */
+    @Nonnull public ExternalAuthenticationContext setAuthnEvent(@Nullable final String event) {
+        authnEvent = event;
+        
+        return this;
+    }
+    
     /**
      * Get the "do not cache" flag.
      * 
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 e6b73841e..d2e02e1b1 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
@@ -158,7 +158,12 @@ public class ExternalAuthenticationImpl extends ExternalAuthentication {
         if (attr != null && attr instanceof Exception) {
             extContext.setAuthnException((Exception) attr);
         }
-        
+
+        attr = request.getAttribute(AUTHENTICATION_EVENT_KEY);
+        if (attr != null && attr instanceof String) {
+            extContext.setAuthnEvent((String) attr);
+        }
+
         attr = request.getAttribute(DONOTCACHE_KEY);
         if (attr != null && attr instanceof Boolean) {
             extContext.setDoNotCache((Boolean) attr);
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 8d85f529d..6e0cf2d6e 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
@@ -167,9 +167,21 @@ public class ValidateExternalAuthentication extends AbstractAuditingValidationAc
     protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext,
             @Nonnull final AuthenticationContext authenticationContext) {
 
+        final String authnEvent = extContext.getAuthnEvent();
         final Exception authnExp = extContext.getAuthnException();
         final String principalName = extContext.getPrincipalName();
-        if (authnExp != null) {
+
+        if (authnEvent != null) {
+            log.info("{} External authentication produced event: {}", getLogPrefix(), authnEvent,
+                    extContext.getAuthnException());
+            if (authnExp != null) {
+                handleError(profileRequestContext, authenticationContext, authnExp, authnEvent);
+            } else {
+                handleError(profileRequestContext, authenticationContext, extContext.getAuthnError(), authnEvent);
+            }
+            recordFailure(profileRequestContext);
+            return;
+        } else if (authnExp != null) {
             log.info("{} External authentication produced exception", getLogPrefix(), extContext.getAuthnException());
             handleError(profileRequestContext, authenticationContext, authnExp,
                     AuthnEventIds.AUTHN_EXCEPTION);
@@ -183,6 +195,7 @@ public class ValidateExternalAuthentication extends AbstractAuditingValidationAc
             recordFailure(profileRequestContext);
             return;
         }
+        
         if (extContext.getSubject() != null) {
             log.info("{} External authentication succeeded for Subject", getLogPrefix());
         } else if (extContext.getPrincipal() != null) {
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 0d7ce5912..2894c362c 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
@@ -38,6 +38,7 @@ import net.shibboleth.idp.authn.principal.ProxyAuthenticationPrincipal;
 import net.shibboleth.idp.authn.principal.UsernamePrincipal;
 import net.shibboleth.idp.authn.testing.TestPrincipal;
 import net.shibboleth.idp.profile.testing.ActionTestingSupport;
+import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.testing.ConstantSupplier;
 
@@ -60,6 +61,7 @@ public class ValidateExternalAuthenticationTest extends BaseAuthenticationContex
         action = new ValidateExternalAuthentication();
         final MockHttpServletRequest request = new MockHttpServletRequest();
         action.setHttpServletRequestSupplier(new ConstantSupplier<>(request));
+        action.setClassifiedMessages(CollectionSupport.singletonMap("Zorkmid2", CollectionSupport.listOf("foo", "bar")));
         action.initialize();
     }
 
@@ -200,4 +202,42 @@ public class ValidateExternalAuthenticationTest extends BaseAuthenticationContex
         Assert.assertNull(ac.getAuthenticationResult());
     }
 
-}
+    @Test public void testEvent() {
+        final AuthenticationContext ac = prc.getSubcontext(AuthenticationContext.class);
+        assert ac != null;
+        final ExternalAuthenticationContext eac =
+                (ExternalAuthenticationContext) ac.addSubcontext(new ExternalAuthenticationContext(ext), true);
+        eac.setAuthnEvent("Zorkmid");
+        
+        final Event event = action.execute(src);
+        ActionTestingSupport.assertEvent(event, "Zorkmid");
+        Assert.assertNull(ac.getAuthenticationResult());
+    }
+
+    @Test public void testEventAndMappedError() {
+        final AuthenticationContext ac = prc.getSubcontext(AuthenticationContext.class);
+        assert ac != null;
+        final ExternalAuthenticationContext eac =
+                (ExternalAuthenticationContext) ac.addSubcontext(new ExternalAuthenticationContext(ext), true);
+        eac.setAuthnEvent("Zorkmid");
+        eac.setAuthnError("foo");
+        
+        final Event event = action.execute(src);
+        ActionTestingSupport.assertEvent(event, "Zorkmid2");
+        Assert.assertNull(ac.getAuthenticationResult());
+    }
+
+    @Test public void testEventAndUnmappedError() {
+        final AuthenticationContext ac = prc.getSubcontext(AuthenticationContext.class);
+        assert ac != null;
+        final ExternalAuthenticationContext eac =
+                (ExternalAuthenticationContext) ac.addSubcontext(new ExternalAuthenticationContext(ext), true);
+        eac.setAuthnEvent("Zorkmid");
+        eac.setAuthnError("Foo");
+        
+        final Event event = action.execute(src);
+        ActionTestingSupport.assertEvent(event, "Zorkmid");
+        Assert.assertNull(ac.getAuthenticationResult());
+    }
+
+}
\ 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