[java-idp-plugin-webauthn] branch main updated: Fix view HTML structure
Phil Smart
philip.smart at jisc.ac.uk
Fri Feb 16 14:06:48 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=54567dac111af5e7a846887c67405b6fcb505633
The following commit(s) were added to refs/heads/main by this push:
new 54567da Fix view HTML structure
54567da is described below
commit 54567dac111af5e7a846887c67405b6fcb505633
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Fri Feb 16 14:06:45 2024 +0000
Fix view HTML structure
---
.../webauthn-registration-flow.xml | 4 +-
.../idp/flows/authn/WebAuthn/webauthn-flow.xml | 7 -
.../plugin/authn/webauthn/views/webauthn-authn.vm | 146 ++++++------
.../authn/webauthn/views/webauthn-register.vm | 248 ++++++++++-----------
.../authn/webauthn/views/webauthn-registered.vm | 4 +-
5 files changed, 199 insertions(+), 210 deletions(-)
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 d484692..410cff8 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
@@ -72,6 +72,7 @@
<evaluate expression="flowRequestContext.getExternalContext().getNativeResponse()" result="viewScope.response" />
</on-render>
+ <transition on="finish" to="RegistrationComplete" />
<transition on="addKey" to="AddKey" />
<transition on="deleteKey" to="DeleteKey" />
@@ -115,7 +116,8 @@
<evaluate expression="flowRequestContext.getExternalContext().getNativeRequest()" result="viewScope.request" />
<evaluate expression="flowRequestContext.getExternalContext().getNativeResponse()" result="viewScope.response" />
</on-render>
-
+
+ <transition on="registerAnother" to="GeneratePublicKeyCredentialCreationOptions" />
<transition on="proceed" to="RegistrationComplete" />
</view-state>
diff --git a/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/WebAuthn/webauthn-flow.xml b/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/WebAuthn/webauthn-flow.xml
index 2fb53a0..add3992 100644
--- a/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/WebAuthn/webauthn-flow.xml
+++ b/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/WebAuthn/webauthn-flow.xml
@@ -78,13 +78,6 @@
<transition on="proceed" to="GenerateAuthenticationCeremonyOptions" />
</action-state>
- <!-- Test if we are operating as a first (and possibly only) factor -->
- <!-- <decision-state id="DetermineUsernamelessOrPasswordlessLogin">
- <if test="IsDiscoverableCredentialRequired.test(opensamlProfileRequestContext)"
- then="UsernamelessLogin"
- else="PasswordlessLogin" />
- </decision-state> -->
-
<!--
Second Factor login. If we are running after a first factor, perform 2FA only. Needs existing username.
-->
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 05c002a..5fef529 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
@@ -22,7 +22,6 @@
##
<!DOCTYPE html>
<html>
-
<head>
<title>#springMessageText("idp.title", "Web Login Service")</title>
<meta charset="UTF-8" />
@@ -30,16 +29,15 @@
<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" )">
+ idp.css", "/css/placeholder.css" )">
<link rel="stylesheet" type="text/css" href="$request.getContextPath()/css/webauthn.css">
<script type="module">
-
import {
get,
parseRequestOptionsFromJSON,
supported,
} from "$request.getContextPath()/js/webauthn/webauthn-json.browser-ponyfill.js";
-
+
async function authenticate() {
// Some UI changes
try {
@@ -82,83 +80,77 @@
console.error(e);
}
});
-
+
</script>
</head>
<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" )" />
-
- #set ($serviceName = $rpUIContext.serviceName)
- #if ($serviceName && !$rpContext.getRelyingPartyId().contains($serviceName))
- <h1>#springMessageText("idp.login.loginTo", "Login to") $encoder.encodeForHTML($serviceName)</h1>
- #end
- </header>
-
- <section>
- #*
- //
- // SP Description & Logo (optional)
- // These idpui lines will display added information (if available
- // in the metadata) about the Service Provider (SP) that requested
- // authentication. These idpui lines are "active" in this example
- // (not commented out) - this extra SP info will be displayed.
- // Remove or comment out these lines to stop the display of the
- // added SP information.
- //
- *#
- #set ($logo = $rpUIContext.getLogo())
- #if ($logo)
- <img class="service-logo" src="$encoder.encodeForHTMLAttribute($logo)"
- alt="$encoder.encodeForHTMLAttribute($serviceName)">
- #end
- #set ($desc = $rpUIContext.getServiceDescription())
- #if ($desc)
- <p>$encoder.encodeForHTML($desc)</p>
- #end
- <div id="supportedDiv">
- <div class="content">
- <div class="column one">
- <form id="authenticatorAssertionForm" action="$flowExecutionUrl" method="post">
- #parse("csrf/csrf.vm")
- <input type="hidden" id="publicKeyAssertion" name="publicKeyAssertion" />
- <button class="hidden" id="authenticationSubmit" type="submit"
- name="_eventId_proceed">#springMessageText("idp.webauthn.authn.submit", "Submit
- Authentication")</button>
- </form>
- <div class="centre">
- <button id="authenticate"
- class="form-element form-button">#springMessageText("idp.webauthn.authn.authenticate",
- "Login with passkey or security key")</button>
- </div>
- #if($debug == "true")
- <hr />
- <button type="button" class="collapsible">#springMessageText("idp.webauthn.debug.title",
- "Debugging")</button>
- <div class="debug" id="debug-div">
- <label for="publicKeyCredentialCreation">#springMessageText("idp.webauthn.debug.request",
- "Request Options")</label>
- <textarea id="publicKeyCredentialRequestOptions" name="publicKeyCredentialRequestOptions"
- rows="20" cols="50">
- $webauthnContext.publicKeyCredentialRequestOptionsJSON</textarea>
- </div>
- #end
- </div>
+ <header>
+ <img class="main-logo" src="$request.getContextPath()#springMessageText("
+ idp.logo", "/images/placeholder-logo.png" )" alt="#springMessageText(" idp.logo.alt-text", "logo" )" />
+ #set ($serviceName = $rpUIContext.serviceName)
+ #if ($serviceName && !$rpContext.getRelyingPartyId().contains($serviceName))
+ <h1>#springMessageText("idp.login.loginTo", "Login to") $encoder.encodeForHTML($serviceName)</h1>
+ #end
+ </header>
+ <section>
+ #*
+ //
+ // SP Description & Logo (optional)
+ // These idpui lines will display added information (if available
+ // in the metadata) about the Service Provider (SP) that requested
+ // authentication. These idpui lines are "active" in this example
+ // (not commented out) - this extra SP info will be displayed.
+ // Remove or comment out these lines to stop the display of the
+ // added SP information.
+ //
+ *#
+ #set ($logo = $rpUIContext.getLogo())
+ #if ($logo)
+ <img class="service-logo" src="$encoder.encodeForHTMLAttribute($logo)"
+ alt="$encoder.encodeForHTMLAttribute($serviceName)">
+ #end
+ #set ($desc = $rpUIContext.getServiceDescription())
+ #if ($desc)
+ <p>$encoder.encodeForHTML($desc)</p>
+ #end
+ <div id="supportedDiv">
+ <div class="content">
+ <form id="authenticatorAssertionForm" action="$flowExecutionUrl" method="post">
+ #parse("csrf/csrf.vm")
+ <input type="hidden" id="publicKeyAssertion" name="publicKeyAssertion" />
+ <button class="hidden" id="authenticationSubmit" type="submit"
+ name="_eventId_proceed">#springMessageText("idp.webauthn.authn.submit", "Submit
+ Authentication")</button>
+ </form>
+ <div class="centre">
+ <button id="authenticate"
+ class="form-element form-button">#springMessageText("idp.webauthn.authn.authenticate",
+ "Login with passkey or security key")</button>
</div>
+ #if($debug == "true")
+ <hr />
+ <button type="button" class="collapsible">#springMessageText("idp.webauthn.debug.title",
+ "Debugging")</button>
+ <div class="debug" id="debug-div">
+ <label for="publicKeyCredentialCreation">#springMessageText("idp.webauthn.debug.request",
+ "Request Options")</label>
+ <textarea id="publicKeyCredentialRequestOptions" name="publicKeyCredentialRequestOptions"
+ rows="20" cols="50">
+ $webauthnContext.publicKeyCredentialRequestOptionsJSON</textarea>
+ </div>
+ #end
</div>
- </div>
- <div id="unsupportedDiv" class="hidden">
- #springMessageText("idp.webauthn.authn.unsupported", "Your browser is not WebAuthn compatible")
- </div>
- </section>
-
- <footer>
- <div class="container container-footer">
- <p class="footer-text">#springMessageText("idp.footer", "Insert your footer text here.")</p>
- </div>
- </footer>
- </div>
+ </div>
+ <div id="unsupportedDiv" class="hidden">
+ #springMessageText("idp.webauthn.authn.unsupported", "Your browser is not WebAuthn compatible")
+ </div>
+ </section>
+ <footer>
+ <div class="container container-footer">
+ <p class="footer-text">#springMessageText("idp.footer", "Insert your footer text here.")</p>
+ </div>
+ </footer>
+ </div>
</body>
-</html>
+</html>
\ No newline at end of file
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 bc8f980..339e6cd 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
@@ -20,8 +20,7 @@
##
<!DOCTYPE html>
<html>
-
- <head>
+ <head>
<title>#springMessageText("idp.title", "Web Login Service")</title>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
@@ -30,133 +29,134 @@
<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">
-
- import {
- parseCreationOptionsFromJSON,
- create,
- supported,
- } from "$request.getContextPath()/js/webauthn/webauthn-json.browser-ponyfill.js";
+ import {
+ parseCreationOptionsFromJSON,
+ create,
+ supported,
+ } from "$request.getContextPath()/js/webauthn/webauthn-json.browser-ponyfill.js";
+
+ async function register() {
+ var pkCredOptions = $webauthnRegContext.publicKeyCredentialCreationOptionsJSON;
+ var pkCredOptionsParsed = parseCreationOptionsFromJSON({ publicKey: pkCredOptions });
+ #if($debug == "true")
+ console.log("Raw creation options", pkCredOptions);
+ console.log("Parsed creation options", pkCredOptionsParsed);
+ #end
+ await create(pkCredOptionsParsed)
+ .then(function (attestation){
+ var nickname = prompt("Credential Nickname");
+ document.getElementById("credentialNickname").value = nickname;
+ document.getElementById("authenticatorAttestation").value = JSON.stringify(attestation);
+ document.getElementById("registrationSubmit").click();
+ }).catch(function (err){
+ console.error(err)
+ });
+
+ };
+
+ function initButton() {
+ document.getElementById("registerButton").onclick = register;
+ return false;
+ }
- async function register() {
- var pkCredOptions = $webauthnRegContext.publicKeyCredentialCreationOptionsJSON;
- var pkCredOptionsParsed = parseCreationOptionsFromJSON({ publicKey: pkCredOptions });
- #if($debug == "true")
- console.log("Raw creation options", pkCredOptions);
- console.log("Parsed creation options", pkCredOptionsParsed);
- #end
- await create(pkCredOptionsParsed)
- .then(function (attestation){
- var nickname = prompt("Credential Nickname");
- document.getElementById("credentialNickname").value = nickname;
- document.getElementById("authenticatorAttestation").value = JSON.stringify(attestation);
- document.getElementById("registrationSubmit").click();
- }).catch(function (err){
- console.error(err)
- });
-
- };
-
- function initButton() {
- document.getElementById("registerButton").onclick = register;
- return false;
- }
+ window.addEventListener("load", () => {
+ try {
+ var isSupported = supported();
+ if (!isSupported){
+ document.getElementById('supportedDiv').classList.add('hidden')
+ document.getElementById("supportedDiv").disabled = true;
+ document.getElementById("authenticatorAttestationForm").disabled = true;
+ document.getElementById("registrationSubmit").disabled = true;
- window.addEventListener("load", () => {
- try {
- var isSupported = supported();
- if (!isSupported){
- document.getElementById('supportedDiv').classList.add('hidden')
- document.getElementById("supportedDiv").disabled = true;
- document.getElementById("authenticatorAttestationForm").disabled = true;
- document.getElementById("registrationSubmit").disabled = true;
-
- document.getElementById("unsupportedDiv").disabled = false;
- document.getElementById('unsupportedDiv').classList.remove('hidden')
- } else{
- initButton();
- }
-
- } catch (e) {
- console.error(e);
- }
- });
- </script>
- </head>
- <body>
- <main class="main">
- <header>
+ document.getElementById("unsupportedDiv").disabled = false;
+ document.getElementById('unsupportedDiv').classList.remove('hidden')
+ } else{
+ initButton();
+ }
+
+ } catch (e) {
+ console.error(e);
+ }
+ });
+ </script>
+ </head>
+ <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" )" />
-
- </header>
- <section>
+ </header>
+ <section>
<div id="supportedDiv">
- <div class="content">
- <div class="column one centre">
- <div>
- <h1>Registered Keys</h1>
- #if ($webauthnRegContext.existingCredentials)
- <table>
- <tr>
- <th>#springMessageText("idp.webauthn.register.table.keyName", "Key Name")</th>
- <th>#springMessageText("idp.webauthn.register.table.transports", "Transports")</th>
- <th>#springMessageText("idp.webauthn.register.table.passkey", "Passkey?")</th>
- <th>#springMessageText("idp.webauthn.register.table.registrationTime", "Registration Time")</th>
- <th>#springMessageText("idp.webauthn.register.table.action", "Action")</th>
- </tr>
- #foreach($cred in $webauthnRegContext.existingCredentials)
- <tr>
- <td>$encoder.encodeForHTML($cred.nickname)</td>
- <td>$encoder.encodeForHTML($webAuthnEncoder.formatTransports($cred.transports))</td>
- <td>$encoder.encodeForHTML($webAuthnEncoder.formatDiscoverable($cred.isDiscoverable()))</td>
- <td>$encoder.encodeForHTML($webAuthnEncoder.formatInstant($cred.registrationTime))</td>
- <td>
- <form id="deleteKeyForm" 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">#springMessageText("idp.webauthn.register.credential.remove", "Remove")</button>
- </form>
- </td>
- </tr>
- #end
- </table>
- #else
- <div><span>#springMessageText("idp.webauthn.register.registered.noKeys", "You have no registered keys")</span></div>
- #end
- <br/>
- <div>
- <button class="form-element form-button" id="registerButton">#springMessageText("idp.webauthn.register.addKey", "Add New Security Key")</button>
- </div>
-
- <form id="authenticatorAttestationForm" action="$flowExecutionUrl" method="post">
- #parse("csrf/csrf.vm")
- <input type="hidden" id="credentialNickname" name="credentialNickname"/>
- <input type="hidden" id="authenticatorAttestation" name="authenticatorAttestation"/>
- <button class="hidden" id="registrationSubmit" type="submit" name="_eventId_addKey">#springMessageText("idp.webauthn.register.submit", "Submit Registration")</button>
- </form>
- </div>
- #if($debug == "true")
- <hr/>
- <button type="button" class="collapsible">#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">
- $webauthnRegContext.publicKeyCredentialCreationOptionsJSON</textarea>
- </div>
- #end
+ <div class="centre">
+ <div>
+ <h1>Registered Keys</h1>
+ #if ($webauthnRegContext.existingCredentials)
+ <table>
+ <tr>
+ <th>#springMessageText("idp.webauthn.register.table.keyName", "Key Name")</th>
+ <th>#springMessageText("idp.webauthn.register.table.transports", "Transports")</th>
+ <th>#springMessageText("idp.webauthn.register.table.passkey", "Passkey?")</th>
+ <th>#springMessageText("idp.webauthn.register.table.registrationTime", "Registration Time")</th>
+ <th>#springMessageText("idp.webauthn.register.table.action", "Action")</th>
+ </tr>
+ #foreach($cred in $webauthnRegContext.existingCredentials)
+ <tr>
+ <td>$encoder.encodeForHTML($cred.nickname)</td>
+ <td>$encoder.encodeForHTML($webAuthnEncoder.formatTransports($cred.transports))</td>
+ <td>$encoder.encodeForHTML($webAuthnEncoder.formatDiscoverable($cred.isDiscoverable()))</td>
+ <td>$encoder.encodeForHTML($webAuthnEncoder.formatInstant($cred.registrationTime))</td>
+ <td>
+ <form id="deleteKeyForm" 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">#springMessageText("idp.webauthn.register.credential.remove", "Remove")</button>
+ </form>
+ </td>
+ </tr>
+ #end
+ </table>
+ #else
+ <div><span>#springMessageText("idp.webauthn.register.registered.noKeys", "You have no registered keys")</span></div>
+ #end
+ <br/>
+ <div>
+ <button class="form-element form-button" id="registerButton">#springMessageText("idp.webauthn.register.addKey", "Add New Security Key")</button>
+ </div>
+ <br />
+ <div>
+ <form id="finish_button_form" action="$flowExecutionUrl" method="post">
+ #parse("csrf/csrf.vm")
+ <button id="finish_button" type="submit" name="_eventId_finish">#springMessageText("idp.webauthn.register.finish", "Finish")</button>
+ </form>
+ </div>
+ <form id="authenticatorAttestationForm" action="$flowExecutionUrl" method="post">
+ #parse("csrf/csrf.vm")
+ <input type="hidden" id="credentialNickname" name="credentialNickname"/>
+ <input type="hidden" id="authenticatorAttestation" name="authenticatorAttestation"/>
+ <button class="hidden" id="registrationSubmit" type="submit" name="_eventId_addKey">#springMessageText("idp.webauthn.register.submit", "Submit Registration")</button>
+ </form>
</div>
- </div>
+ #if($debug == "true")
+ <hr/>
+ <button type="button" class="collapsible">#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">
+ $webauthnRegContext.publicKeyCredentialCreationOptionsJSON</textarea>
+ </div>
+ #end
+ </div>
<div id="unsupportedDiv" class="hidden">
- #springMessageText("idp.webauthn.register.unsupported", "Your browser is not WebAuthn compatible")
- </div>
- </div>
- </section>
- </main>
- <footer>
- <div class="cc">
- <p class="footer-text">#springMessageText("idp.footer", "Insert your footer text here.")</p>
+ #springMessageText("idp.webauthn.register.unsupported", "Your browser is not WebAuthn compatible")
+ </div>
</div>
- </footer>
+ </section>
+ </main>
+ <footer>
+ <div class="cc">
+ <p class="footer-text">#springMessageText("idp.footer", "Insert your footer text here.")</p>
+ </div>
+ </footer>
</div>
- </body>
-</html>
+ </body>
+</html>
\ No newline at end of file
diff --git a/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-registered.vm b/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-registered.vm
index 419012e..c7c7a4b 100644
--- a/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-registered.vm
+++ b/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-registered.vm
@@ -74,7 +74,9 @@
<br />
<form id="finish_button_form" action="$flowExecutionUrl" method="post">
#parse("csrf/csrf.vm")
- <button id="finish_button" type="submit" name="_eventId_proceed">#springMessageText("idp.webauthn.register.finish", "Done")</button>
+ <button id="register_another_button" type="submit" name="_eventId_registerAnother">#springMessageText("idp.webauthn.register.another", "Register Another")</button>
+
+ <button id="finish_button" type="submit" name="_eventId_proceed">#springMessageText("idp.webauthn.register.finish", "Finish")</button>
</form>
</div>
</section>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list