[java-idp-plugin-webauthn] branch main updated: Add key validation error output to registration views

Phil Smart philip.smart at jisc.ac.uk
Fri Mar 1 12:05:45 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=dd68b01f9fbc36de193739502b310db44a2b7896

The following commit(s) were added to refs/heads/main by this push:
     new dd68b01  Add key validation error output to registration views
dd68b01 is described below

commit dd68b01f9fbc36de193739502b310db44a2b7896
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Fri Mar 1 12:05:42 2024 +0000

    Add key validation error output to registration views
---
 .../admin/WebAuthnRegistrationEventIds.java        | 36 ++++++++++++++++++++
 .../admin/impl/StorePublicKeyCredential.java       |  9 +++--
 .../ValidateAuthenticatorAttestationResponse.java  |  8 ++---
 .../webauthn-registration-flow.xml                 |  8 +++--
 .../authn/webauthn/views/webauthn-register.vm      | 38 ++++++++++++++--------
 5 files changed, 75 insertions(+), 24 deletions(-)

diff --git a/webauthn-api/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/WebAuthnRegistrationEventIds.java b/webauthn-api/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/WebAuthnRegistrationEventIds.java
new file mode 100644
index 0000000..cddaed6
--- /dev/null
+++ b/webauthn-api/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/WebAuthnRegistrationEventIds.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.plugin.authn.webauthn.admin;
+
+import javax.annotation.Nonnull;
+
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+
+/**
+ * Constants to use for {@link org.opensaml.profile.action.ProfileAction}
+ * {@link org.opensaml.profile.context.EventContext} results related to
+ * WebAuthn registration.
+ */
+public final class WebAuthnRegistrationEventIds {
+    
+    /** Private constructor.*/
+    private WebAuthnRegistrationEventIds() {
+        
+    }
+    
+    /** Registration failed. */
+    @Nonnull @NotEmpty public static final String INVALID_REGISTRATION = "InvalidRegistration";
+
+}
diff --git a/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/StorePublicKeyCredential.java b/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/StorePublicKeyCredential.java
index 76497ad..7e29071 100644
--- a/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/StorePublicKeyCredential.java
+++ b/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/StorePublicKeyCredential.java
@@ -24,7 +24,6 @@ import java.util.TreeSet;
 import javax.annotation.Nonnull;
 
 import org.opensaml.profile.action.ActionSupport;
-import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.storage.StorageCapabilities;
 import org.opensaml.storage.StorageSerializer;
@@ -36,7 +35,7 @@ import com.yubico.webauthn.RegistrationResult;
 import com.yubico.webauthn.data.ByteArray;
 import com.yubico.webauthn.data.UserIdentity;
 
-import net.shibboleth.idp.authn.AuthnEventIds;
+import net.shibboleth.idp.plugin.authn.webauthn.admin.WebAuthnRegistrationEventIds;
 import net.shibboleth.idp.plugin.authn.webauthn.context.WebAuthnRegistrationContext;
 import net.shibboleth.idp.plugin.authn.webauthn.storage.CredentialRegistration;
 import net.shibboleth.idp.plugin.authn.webauthn.storage.impl.CredentialRegistrationSerializer;
@@ -96,13 +95,13 @@ public class StorePublicKeyCredential extends AbstractWebAuthnRegistrationAction
 
         if (username == null) {
             log.error("Unable to find username in registration context");
-            ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.INVALID_AUTHN_CTX);
+            ActionSupport.buildEvent(profileRequestContext, WebAuthnRegistrationEventIds.INVALID_REGISTRATION);
             return;
         }        
         final RegistrationResult registrationResult = context.getRegistrationResult();
         if (registrationResult == null) {
             log.error("Unable to find registration result in registration context");
-            ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.INVALID_AUTHN_CTX);
+            ActionSupport.buildEvent(profileRequestContext, WebAuthnRegistrationEventIds.INVALID_REGISTRATION);
             return;
         } 
         try {
@@ -142,7 +141,7 @@ public class StorePublicKeyCredential extends AbstractWebAuthnRegistrationAction
         } catch (final Exception e) {
             log.error("{} Unable to store registration for key '{}'",getLogPrefix(), 
                     registrationResult.getKeyId().getId().getBase64Url(), e);
-            ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
+            ActionSupport.buildEvent(profileRequestContext, WebAuthnRegistrationEventIds.INVALID_REGISTRATION);
             return;
         }
         
diff --git a/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/ValidateAuthenticatorAttestationResponse.java b/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/ValidateAuthenticatorAttestationResponse.java
index 0d68eca..c3713b5 100644
--- a/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/ValidateAuthenticatorAttestationResponse.java
+++ b/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/ValidateAuthenticatorAttestationResponse.java
@@ -29,7 +29,7 @@ import com.yubico.webauthn.data.ClientRegistrationExtensionOutputs;
 import com.yubico.webauthn.data.PublicKeyCredential;
 import com.yubico.webauthn.data.PublicKeyCredentialCreationOptions;
 
-import net.shibboleth.idp.authn.AuthnEventIds;
+import net.shibboleth.idp.plugin.authn.webauthn.admin.WebAuthnRegistrationEventIds;
 import net.shibboleth.idp.plugin.authn.webauthn.context.WebAuthnRegistrationContext;
 import net.shibboleth.idp.plugin.authn.webauthn.exception.RegistrationFailureException;
 import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
@@ -64,14 +64,14 @@ public class ValidateAuthenticatorAttestationResponse extends AbstractWebAuthnRe
         attestation = context.getAuthenticatorAttestationResponse();
         if (attestation == null) {
             log.error("{} Authenticator attestation response was null", getLogPrefix());
-            ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.NO_CREDENTIALS);
+            ActionSupport.buildEvent(profileRequestContext, WebAuthnRegistrationEventIds.INVALID_REGISTRATION);
             return false;
         }
         
         pkCredCreationOptions = context.getPublicKeyCredentialCreationOptions();
         if (pkCredCreationOptions == null) {
             log.error("{} Public key credential creation options was null", getLogPrefix());
-            ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.NO_CREDENTIALS);
+            ActionSupport.buildEvent(profileRequestContext, WebAuthnRegistrationEventIds.INVALID_REGISTRATION);
             return false;
         }
         
@@ -90,7 +90,7 @@ public class ValidateAuthenticatorAttestationResponse extends AbstractWebAuthnRe
             log.info("Public Key Registration was valid");
         } catch (final RegistrationFailureException e) {
             log.warn("{} Public key credential creation options was invalid", getLogPrefix(), e);
-            ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.NO_CREDENTIALS);
+            ActionSupport.buildEvent(profileRequestContext, WebAuthnRegistrationEventIds.INVALID_REGISTRATION);
             return;
         }
     }
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 21e4f41..9131091 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
@@ -85,9 +85,13 @@
    <action-state id="AddKey">
         <evaluate expression="ExtractAuthenticatorAttestationFromFormRequest"/>
         <evaluate expression="ValidateAuthenticatorAttestationResponse"/>
-        <evaluate expression="StorePublicKeyCredential"/>        
-        
+        <evaluate expression="StorePublicKeyCredential"/> 
         <evaluate expression="'proceed'" />
+        
+        <transition on="InvalidRegistration" to="GeneratePublicKeyCredentialCreationOptions">
+            <!-- TODO externalise message bundle-->
+            <set name="flashScope.registrationErrorOutcomes" value="'Key registration unsuccessful'"/>
+        </transition>      
         <transition on="proceed" to="GeneratePublicKeyCredentialCreationOptions">
             <!-- TODO externalise message bundle-->
             <set name="flashScope.registrationOutcomes" value="'Key was registered successfully'"/>
diff --git a/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-register.vm b/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-register.vm
index 9b9a45d..f4b7319 100644
--- a/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-register.vm
+++ b/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-register.vm
@@ -35,7 +35,8 @@
            supported,
          }  from "$request.getContextPath()/js/webauthn/webauthn-json.browser-ponyfill.js";
          
-         async function register() {        
+         async function register() {  
+             clearMessages();            
              var pkCredOptions = $webauthnRegContext.publicKeyCredentialCreationOptionsJSON; 
              var pkCredOptionsParsed = parseCreationOptionsFromJSON({ publicKey: pkCredOptions }); 
              #if($debug == "true")
@@ -53,14 +54,24 @@
                             console.error(err);
                          #end                           
                          document.getElementById("error_div").classList.remove('hidden')
-                         document.getElementById("error_message").innerHTML = err.message;
-                         setTimeout(function () {
-                            document.getElementById("error_div").classList.add('hidden')                            
-                        }.bind(this), 4000); 
+                         document.getElementById("error_message").innerHTML = err.message;                         
                      });    
    
          
           };
+          
+          function clearMessages(){
+             if(document.getElementById('error_div') != null){
+                document.getElementById('error_div').classList.add('hidden');
+             }
+               
+             if (document.getElementById('reg-error-outcome') != null){
+                document.getElementById('reg-error-outcome').classList.add('hidden');
+             }
+             if (document.getElementById('reg-success-outcome') != null){
+                document.getElementById('reg-success-outcome').classList.add('hidden');
+             } 
+          }
          
           function initButton() {
                document.getElementById("registerButton").onclick = register;        
@@ -97,9 +108,14 @@
             <div id="supportedDiv">
                <div class="centre">
                   #if ($registrationOutcomes)
-                    <p>$registrationOutcomes</p>
-                    <hr/>
-                  #end                 
+                    <p id="reg-success-outcome" class="output-message output--success">$registrationOutcomes</p>
+                  #end
+                   #if ($registrationErrorOutcomes)
+                    <p id="reg-error-outcome" class="output-message output--error">$registrationErrorOutcomes</p>
+                  #end 
+                  <div class="hidden output-message output--error" id="error_div">
+                        <p id="error_message"></p>
+                  </div>                
                   <div>
                      <h1>Registered Keys</h1>
                      #if ($webauthnRegContext.existingCredentials)
@@ -142,11 +158,7 @@
                         </div>                        
                      </div>
                     
-                     <div class="hidden output-message output--error" id="error_div">
-                        <span id="error_message"></span>
-                     </div>
-                    
-                    
+                     
                      <form id="authenticatorAttestationForm" action="$flowExecutionUrl" method="post">
                         #parse("csrf/csrf.vm")
                         <input type="hidden" id="credentialNickname" name="credentialNickname"/>

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


More information about the commits mailing list