[java-idp-plugin-webauthn] branch main updated: Tighten context creation in registration flow

Phil Smart philip.smart at jisc.ac.uk
Wed Aug 7 11:02:43 UTC 2024


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

philsmart pushed a commit to branch main
in repository java-idp-plugin-webauthn.

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

The following commit(s) were added to refs/heads/main by this push:
     new ee10645  Tighten context creation in registration flow
ee10645 is described below

commit ee10645476d730cb7d004068fc5e9528f0e24f5b
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Wed Aug 7 12:02:40 2024 +0100

    Tighten context creation in registration flow
---
 .../impl/PopulateWebAuthnRegistrationContext.java  | 37 +++++++++++++++++++++-
 .../webauthn-registration-beans.xml                |  6 +++-
 .../webauthn-registration-flow.xml                 | 10 ++++--
 3 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/PopulateWebAuthnRegistrationContext.java b/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/PopulateWebAuthnRegistrationContext.java
index 4a0ce83..a28c6ca 100644
--- a/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/PopulateWebAuthnRegistrationContext.java
+++ b/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/PopulateWebAuthnRegistrationContext.java
@@ -56,6 +56,9 @@ public class PopulateWebAuthnRegistrationContext extends AbstractProfileAction {
     /** Is the username required? */
     @Nonnull private Predicate<ProfileRequestContext> usernameRequiredPredicate;
     
+    /** Predicate to determine if we should remove any existing registration context. Default is false.*/
+    @Nonnull private Predicate<ProfileRequestContext> removeExistingRegistrationContext;
+    
     /** Constructor.*/
     public PopulateWebAuthnRegistrationContext() {
         // Default creates a WebAuthn registration context under the profile request context.
@@ -64,6 +67,7 @@ public class PopulateWebAuthnRegistrationContext extends AbstractProfileAction {
                 new ChildContextLookup<>(WebAuthnRegistrationContext.class, true);
         usernameRequiredPredicate = PredicateSupport.alwaysFalse();
         usernameLookupStrategy = FunctionSupport.constant(null);
+        removeExistingRegistrationContext = PredicateSupport.alwaysFalse();
 
     }
     
@@ -87,6 +91,28 @@ public class PopulateWebAuthnRegistrationContext extends AbstractProfileAction {
         usernameRequiredPredicate = Constraint.isNotNull(predicate, "Username required predicate can not be null");
     }
     
+    /**
+     * Set a flag to determine if an existing registration context should be removed.
+     * 
+     * @param flag should an existing registration context be removed?
+     */
+    public void setRemoveExistingRegistrationContext(final boolean flag) {
+        checkSetterPreconditions();
+        removeExistingRegistrationContext = flag ? PredicateSupport.alwaysTrue() : PredicateSupport.alwaysFalse();
+    }
+    
+    /**
+     * Set a strategy to determine if an existing registration context should be removed.
+     * 
+     * @param predicate the predicate to set.
+     */
+    public void setRemoveExistingRegistrationContextPredicate(
+            @Nonnull final Predicate<ProfileRequestContext> predicate){
+        checkSetterPreconditions();
+        removeExistingRegistrationContext = Constraint.isNotNull(predicate, 
+                "RemoveExistingRegistrationContext predicate can not be null");
+    }
+    
     /**
      * Set the strategy used to lookup or create the WebAuthn registration context.
      * 
@@ -114,10 +140,19 @@ public class PopulateWebAuthnRegistrationContext extends AbstractProfileAction {
 
     /** {@inheritDoc} */
     @Override protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
-
         
+        // If we want to remove an existing context, first lookup the context (which may create it, so this is not
+        // efficient), then remove it. 
+        if (removeExistingRegistrationContext.test(profileRequestContext)) {
+            final WebAuthnRegistrationContext context = 
+                    webAuthnRegistrationContextCreationStrategy.apply(profileRequestContext);
+            context.removeFromParent();
+        }
+        
+        // Now create the context.
         final WebAuthnRegistrationContext context = 
                 webAuthnRegistrationContextCreationStrategy.apply(profileRequestContext);
+        
         if (context == null) {
             log.error("{} Error creating WebAuthnRegistrationContext", getLogPrefix());
             ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
diff --git a/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-registration/webauthn-registration-beans.xml b/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-registration/webauthn-registration-beans.xml
index 17f1127..90973b0 100644
--- a/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-registration/webauthn-registration-beans.xml
+++ b/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-registration/webauthn-registration-beans.xml
@@ -45,10 +45,14 @@
         p:trim="%{idp.authn.webauthn.registration.username.trim:false}"
         p:transforms="#{getObject('shibboleth.authn.webauthn.registration.UsernameTransformations')}"/>
     
-    <!-- Important that this gets the username from the subject context, not the initial context that is created -->
+    <!-- 
+        Important that this gets the username from the subject context, not the initial context that is created 
+        Also, removes any initial registration contexts to avoid contamination.
+    -->
     <bean id="PopulateWebAuthnRegistrationContext" scope="prototype"
         class="net.shibboleth.idp.plugin.authn.webauthn.admin.impl.PopulateWebAuthnRegistrationContext"
         p:usernameRequired="true"
+        p:removeExistingRegistrationContext="true"
         p:usernameLookupStrategy="#{getObject('%{idp.authn.webauthn.registration.usernameLookupStrategy:shibboleth.authn.webauthn.RegistrationUsernameLookupStrategy}')}">
     </bean>
         
diff --git a/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-registration/webauthn-registration-flow.xml b/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-registration/webauthn-registration-flow.xml
index 02cec12..c83b8b9 100644
--- a/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-registration/webauthn-registration-flow.xml
+++ b/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-registration/webauthn-registration-flow.xml
@@ -3,8 +3,7 @@
     parent="admin.abstract">
     
     
-    <!-- Start action. -->
-        
+    <!-- Start action. -->        
     <action-state id="InitializeProfileRequestContext">
         <evaluate expression="InitializeProfileRequestContext" />
         <evaluate expression="FlowStartPopulateAuditContext" />
@@ -36,7 +35,11 @@
        
     </view-state>
     
-    <!-- TODO if we want to do this, we would want this to populate a different context -->
+    <!-- 
+        This creates an initial context with the username and existing credentials which can be used by the MFA
+        logic to determine which flow should be used e.g. has existing webAuthn credentials or not, and so we do not
+        need username collection during passwordless authentication as we have already collected it.
+    -->
     <action-state id="ExtractUsernameAndPopulateContext">
         <evaluate expression="PopulateInitialWebAuthnRegistrationContext"/>
         <evaluate expression="ExtractUsernameFromForm"/>
@@ -56,6 +59,7 @@
         <transition on="proceed" to="GeneratePublicKeyCredentialCreationOptions" />
     </action-state>   
     
+    <!-- Recreate a registration context from the result of authentication, and create WebAuthn GET creation options -->
      <action-state id="GeneratePublicKeyCredentialCreationOptions">
         <evaluate expression="PopulateWebAuthnRegistrationContext"/>
         <evaluate expression="LookupRegisteredCredentials"/>      

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


More information about the commits mailing list