[java-idp-plugin-webauthn] branch main updated: Improve CSP in views

Phil Smart philip.smart at jisc.ac.uk
Fri May 31 15:37:23 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=cc320a9ba239f83e231594acacab09756b1354bb

The following commit(s) were added to refs/heads/main by this push:
     new cc320a9  Improve CSP in views
cc320a9 is described below

commit cc320a9ba239f83e231594acacab09756b1354bb
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Fri May 31 16:37:21 2024 +0100

    Improve CSP in views
---
 .../webauthn/views/webauthn-authn-username.vm      | 12 ++---
 .../plugin/authn/webauthn/views/webauthn-authn.vm  | 54 +++++++++++-----------
 .../plugin/authn/webauthn/views/webauthn-end.vm    |  4 ++
 .../webauthn/views/webauthn-management-search.vm   |  6 ++-
 .../authn/webauthn/views/webauthn-management.vm    | 20 ++++----
 .../webauthn/views/webauthn-register-username.vm   |  8 +---
 .../authn/webauthn/views/webauthn-register.vm      | 33 +++++++------
 7 files changed, 68 insertions(+), 69 deletions(-)

diff --git a/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-authn-username.vm b/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-authn-username.vm
index 1a2fc08..bcc208b 100644
--- a/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-authn-username.vm
+++ b/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-authn-username.vm
@@ -22,12 +22,10 @@
 #if ($eventCtx)
 #set ($eventId = $eventCtx.getEvent())
 #end
-#set ($nonce = $cspNonce.generateIdentifier())
-$response.addHeader("Content-Security-Policy", "script-src-elem 'nonce-$nonce'")
-## TODO fix this
-#set ($onClick = "document.forms.password.j_username.value = document.forms.passwordless.j_username.value")
-### TODO ADD THIS BACK
-###$response.addHeader("Content-Security-Policy", "script-src-attr 'unsafe-hashes' 'sha256-$cspDigester.apply($onClick)'")
+
+## Add CSP directives
+$response.addHeader("Content-Security-Policy", "default-src 'none'")
+
 ##
 <!DOCTYPE html>
 <html>
@@ -38,7 +36,7 @@ $response.addHeader("Content-Security-Policy", "script-src-elem 'nonce-$nonce'")
         <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0">
         <link rel="stylesheet" type="text/css" href="$request.getContextPath()#springMessageText("idp.css", "/css/placeholder.css")">
     </head>
-    <body onLoad="$onLoad">
+    <body>
         <main class="main">
             <header>
                 <img class="main-logo" src="$request.getContextPath()#springMessageText("idp.logo", "/images/placeholder-logo.png")" alt="#springMessageText("idp.logo.alt-text", "logo")" />
diff --git a/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-authn.vm b/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-authn.vm
index 98643b9..0ceabcd 100644
--- a/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-authn.vm
+++ b/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-authn.vm
@@ -20,6 +20,11 @@
 ##
 #set ($debug = $environment.getProperty("idp.authn.webauthn.ui.debug", "false"))
 #set ($rpContext = $profileRequestContext.getSubcontext('net.shibboleth.profile.context.RelyingPartyContext'))
+
+## Add CSP directives
+#set ($nonce = $cspNonce.generateIdentifier())
+$response.addHeader("Content-Security-Policy", "default-src 'none'; style-src 'self'; img-src https:; script-src-elem 'nonce-$nonce'")
+
 ##
 <!DOCTYPE html>
 <html>
@@ -28,17 +33,36 @@
         <meta charset="UTF-8" />
         <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
         <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0">
-        <script type="text/javascript" src="$request.getContextPath()/js/webauthn/webauthn-support.js"></script>
+        <script type="text/javascript" src="$request.getContextPath()/js/webauthn/webauthn-support.js" #if ($nonce)nonce="$nonce"#end></script>
         <link rel="stylesheet" type="text/css" href="$request.getContextPath()#springMessageText("idp.css", "/css/placeholder.css" )">
         <link rel="stylesheet" type="text/css" href="$request.getContextPath()/css/webauthn.css">
         
-        <script type="module">
+        <script type="module" #if ($nonce)nonce="$nonce"#end>        
             import {
                 get,
                 parseRequestOptionsFromJSON,
                 supported,
             } from "$request.getContextPath()/js/webauthn/webauthn-json.browser-ponyfill.js";
             
+            
+            window.addEventListener("load", () => {
+                try {
+                    var isSupported = supported();
+                    if (!isSupported) {
+                        document.getElementById('supportedDiv').classList.add('hidden')
+                        document.getElementById("supportedDiv").disabled = true;
+                        document.getElementById("authenticate").disabled = true;
+                        document.getElementById("authenticator_assertion_form").disabled = true;
+                        document.getElementById("unsupportedDiv").disabled = false;
+                        document.getElementById('unsupportedDiv').classList.remove('hidden')
+                    } else {
+                        document.getElementById("authenticate").onclick = authenticate;
+                    }
+                } catch (e) {
+                    console.error(e);
+                }
+            });
+            
             async function authenticate() {
                 // Some UI changes
                 try {               
@@ -49,10 +73,6 @@
                 }            
                 var pkCredRequestOptions = $webAuthnEncoder.serializePublicKeyCredentialRequestOptionsAsJSON($webauthnContext.publicKeyCredentialRequestOptions)
                 var parsedRequestOptions = parseRequestOptionsFromJSON(pkCredRequestOptions);
-                #if($debug == "true")
-                    console.log("Raw request options", pkCredRequestOptions);
-                    console.log("Parsed request options", parsedRequestOptions);
-                #end
                 await get(parsedRequestOptions)
                     .then(function (assertion) {
                         document.getElementById("publicKeyAssertion").value = JSON.stringify(assertion);
@@ -62,25 +82,7 @@
                         document.getElementById('authenticate').textContent='#springMessageText("idp.webauthn.authn.authenticate.retry",
                                         "Login failed, retry")'          
                     });    
-            }    
-            window.addEventListener("load", () => {
-                try {
-                    var isSupported = supported();
-                    if (!isSupported) {
-                        document.getElementById('supportedDiv').classList.add('hidden')
-                        document.getElementById("supportedDiv").disabled = true;
-                        document.getElementById("authenticate").disabled = true;
-                        document.getElementById("authenticator_assertion_form").disabled = true;
-                        document.getElementById("unsupportedDiv").disabled = false;
-                        document.getElementById('unsupportedDiv').classList.remove('hidden')
-                    } else {
-                        document.getElementById("authenticate").onclick = authenticate;
-                    }    
-                } catch (e) {
-                    console.error(e);
-                }
-            });
-            
+            }
         </script>
     </head>
     <body>
@@ -130,7 +132,7 @@
                     
                     #if($debug == "true")
                         <hr />
-                        <button type="button" class="collapsible">#springMessageText("idp.webauthn.debug.title","Debugging")</button>    
+                        <button type="button" class="collapsible-debug">#springMessageText("idp.webauthn.debug.title","Debugging")</button>    
                         <div class="debug" id="debug-div">
                             <label for="publicKeyCredentialCreation">#springMessageText("idp.webauthn.debug.request",
                             "Request Options")</label>
diff --git a/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-end.vm b/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-end.vm
index 45110d0..2f864c7 100644
--- a/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-end.vm
+++ b/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-end.vm
@@ -20,6 +20,10 @@
 ##
 #set ($debug = $environment.getProperty("idp.authn.webauthn.ui.debug", "false"))
 #set ($rpContext = $profileRequestContext.getSubcontext('net.shibboleth.profile.context.RelyingPartyContext'))
+
+## Add CSP directives
+$response.addHeader("Content-Security-Policy", "default-src 'none'; style-src 'self'; img-src 'self';")
+
 ##
 <!DOCTYPE html>
 <html>
diff --git a/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-management-search.vm b/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-management-search.vm
index 90e752f..33aa561 100644
--- a/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-management-search.vm
+++ b/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-management-search.vm
@@ -16,7 +16,10 @@
 ## environment - Spring Environment object for property resolution
 ## custom - arbitrary object injected by deployer
 ##
-#set ($debug = $environment.getProperty("idp.authn.webauthn.ui.debug", "false"))
+
+## Add CSP directives
+$response.addHeader("Content-Security-Policy", "default-src 'none'; style-src 'self'; img-src 'self';")
+
 ##
 <!DOCTYPE html>
 <html>
@@ -25,7 +28,6 @@
       <meta charset="UTF-8" />
       <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
       <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0">
-      <script type="text/javascript" src="$request.getContextPath()/js/webauthn/webauthn-support.js"></script>
       <link rel="stylesheet" type="text/css" href="$request.getContextPath()#springMessageText("idp.css", "/css/placeholder.css" )">
       <link rel="stylesheet" type="text/css" href="$request.getContextPath()/css/webauthn.css">
          
diff --git a/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-management.vm b/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-management.vm
index bd2ace1..4dd1f5a 100644
--- a/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-management.vm
+++ b/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-management.vm
@@ -15,9 +15,12 @@
 ## response - HttpServletResponse
 ## environment - Spring Environment object for property resolution
 ## custom - arbitrary object injected by deployer
-##
-#set ($debug = $environment.getProperty("idp.authn.webauthn.ui.debug", "false"))
-##
+
+## Add CSP directives
+#set ($areYouSure =  "return confirm('#springMessageText('idp.webauthn.register.credential.remove.confirm', 'Are you sure')');")
+#set ($nonce = $cspNonce.generateIdentifier())
+$response.addHeader("Content-Security-Policy", "default-src 'none'; style-src 'self'; img-src 'self'; script-src-elem 'nonce-$nonce'; script-src-attr 'unsafe-hashes' 'sha256-$cspDigester.apply($areYouSure)'")
+
 <!DOCTYPE html>
 <html>
    <head>
@@ -25,8 +28,7 @@
       <meta charset="UTF-8" />
       <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
       <meta http-equiv="refresh" content="300;url=$flowExecutionUrl&_eventId=finish#parse("csrf/csrf-qparam.vm")">
-      <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0">
-      <script type="text/javascript" src="$request.getContextPath()/js/webauthn/webauthn-support.js"></script>
+      <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0">>
       <link rel="stylesheet" type="text/css" href="$request.getContextPath()#springMessageText("idp.css", "/css/placeholder.css" )">
       <link rel="stylesheet" type="text/css" href="$request.getContextPath()/css/webauthn.css">
          
@@ -81,7 +83,7 @@
                                       <form id="delete_key_form" action="$flowExecutionUrl" method="post">
                                          #parse("csrf/csrf.vm")
                                          <input type="hidden" name="credentialId" value="$cred.credentialIdBase64Url"/>
-                                         <button class="webauthn-table-button" onclick="return confirm('#springMessageText("idp.webauthn.admin.credential.remove.confirm", "Are you sure")');" id="removeButton" type="submit" name="_eventId_deleteKey">
+                                         <button class="webauthn-table-button" onclick="$areYouSure" id="removeButton" type="submit" name="_eventId_deleteKey">
                                         #springMessageText("idp.webauthn.admin.credential.remove", "Remove")</button>
                                       </form>
                                    </td>
@@ -101,12 +103,8 @@
                             <button id="searchButton" type="submit" name="_eventId_again">#springMessageText("idp.webauthn.admin.search.again", "Search again")</button>
                              <button id="finish_button" type="submit" name="_eventId_finish">#springMessageText("idp.webauthn.admin.finish", "Finish")</button>
                         </div> 
-                      </div>                        
-                      
+                      </div>                     
                     </form>
-
-
-                     
                   </div>
          
                </div>
diff --git a/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-register-username.vm b/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-register-username.vm
index 5eed5f1..2445cbc 100644
--- a/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-register-username.vm
+++ b/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-register-username.vm
@@ -19,13 +19,9 @@
 #if ($eventCtx)
 #set ($eventId = $eventCtx.getEvent())
 #end
-#set ($nonce = $cspNonce.generateIdentifier())
-
-### TODO ADD THIS BACK
-$response.addHeader("Content-Security-Policy", "script-src-elem 'nonce-$nonce'")
-#set ($onClick = "document.forms.password.j_username.value = document.forms.passwordless.j_username.value")
-###$response.addHeader("Content-Security-Policy", "script-src-attr 'unsafe-hashes' 'sha256-$cspDigester.apply($onClick)'")
 
+## Add CSP directives
+$response.addHeader("Content-Security-Policy", "default-src 'none'; style-src 'self'; img-src 'self'; default-src 'none'; style-src 'self'; img-src 'self'")
 
 <!DOCTYPE html>
 <html>
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 7cdd875..62cb905 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
@@ -17,6 +17,12 @@
 ## custom - arbitrary object injected by deployer
 ##
 #set ($debug = $environment.getProperty("idp.authn.webauthn.ui.debug", "false"))
+
+## Add CSP directives
+#set ($areYouSure =  "return confirm('#springMessageText('idp.webauthn.register.credential.remove.confirm', 'Are you sure')');")
+#set ($nonce = $cspNonce.generateIdentifier())
+$response.addHeader("Content-Security-Policy", "default-src 'none'; style-src 'self'; img-src 'self'; script-src-elem 'nonce-$nonce'; script-src-attr 'unsafe-hashes' 'sha256-$cspDigester.apply($areYouSure)'")
+
 ##
 <!DOCTYPE html>
 <html>
@@ -26,10 +32,11 @@
       <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
       <meta http-equiv="refresh" content="300;url=$flowExecutionUrl&_eventId=finish#parse("csrf/csrf-qparam.vm")">      
       <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0">
-      <script type="text/javascript" src="$request.getContextPath()/js/webauthn/webauthn-support.js"></script>
+      <script type="text/javascript" src="$request.getContextPath()/js/webauthn/webauthn-support.js" #if ($nonce)nonce="$nonce"#end></script>
       <link rel="stylesheet" type="text/css" href="$request.getContextPath()#springMessageText("idp.css", "/css/placeholder.css" )">
       <link rel="stylesheet" type="text/css" href="$request.getContextPath()/css/webauthn.css">
-      <script type="module">
+      
+      <script type="module" #if ($nonce)nonce="$nonce"#end>
          import {
            parseCreationOptionsFromJSON,
            create,
@@ -39,11 +46,7 @@
          async function register() {  
              clearMessages();            
              var pkCredOptions = $webAuthnEncoder.serializePublicKeyCredentialOptionsAsJSON($webauthnRegContext.publicKeyCredentialCreationOptions); 
-             var pkCredOptionsParsed = parseCreationOptionsFromJSON(pkCredOptions); 
-             #if($debug == "true")
-                 console.log("Raw creation options", pkCredOptions);
-                 console.log("Parsed creation options", pkCredOptionsParsed);
-             #end             
+             var pkCredOptionsParsed = parseCreationOptionsFromJSON(pkCredOptions);         
              await create(pkCredOptionsParsed)
                      .then(function (attestation){
                          var nickname = prompt('#springMessageText("idp.webauthn.register.credential.nickanme", "Credential Nickname")');
@@ -51,14 +54,10 @@
                          document.getElementById("authenticatorAttestation").value = JSON.stringify(attestation);    
                          document.getElementById("registrationSubmit").click();
                      }).catch(function (err){
-                         #if($debug == "true")
-                            console.error(err);
-                         #end                           
+                         console.error(err);                        
                          document.getElementById("error_div").classList.remove('hidden')
                          document.getElementById("error_message").innerHTML = err.message;                         
-                     });    
-   
-         
+                     });   
           };
           
           function clearMessages(){
@@ -91,13 +90,13 @@
                      document.getElementById("unsupportedDiv").disabled = false;
                      document.getElementById('unsupportedDiv').classList.remove('hidden')
                    } else{
-                       initButton();
+                     initButton();
                    }     
                  
                  } catch (e) {
                  console.error(e);
                  }
-             });    
+          });    
       </script>      
    </head>
    <body>
@@ -148,7 +147,7 @@
                                   <form id="delete_key_form" action="$flowExecutionUrl" method="post">
                                      #parse("csrf/csrf.vm")
                                      <input type="hidden" name="credentialId" value="$cred.credentialIdBase64Url"/>
-                                     <button class="webauthn-table-button" onclick="return confirm('#springMessageText("idp.webauthn.register.credential.remove.confirm", "Are you sure")');" id="removeButton" type="submit" name="_eventId_deleteKey">
+                                     <button class="webauthn-table-button" onclick="$areYouSure" id="removeButton" type="submit" name="_eventId_deleteKey">
                                     #springMessageText("idp.webauthn.register.credential.remove", "Remove")</button>
                                   </form>
                                </td>
@@ -179,7 +178,7 @@
                   </div>
                   #if($debug == "true")
                       <hr/>
-                      <button type="button" class="collapsible">#springMessageText("idp.webauthn.register.debug.title", "Debugging")</button> 
+                      <button type="button" class="collapsible-debug">#springMessageText("idp.webauthn.register.debug.title", "Debugging")</button> 
                       <div class="debug" id="debug-div">
                          <label for="publicKeyCredentialCreation">#springMessageText("idp.webauthn.register.debug.registration", "Registration Options")</label>
                          <textarea id="publicKeyCredentialCreation" name="publicKeyCredentialCreation" rows="20" cols="50">

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


More information about the commits mailing list