feat: update login UI and JS for usernameless WebAuthn authentication
This commit is contained in:
parent
32567b5484
commit
ebe5497879
3 changed files with 24 additions and 27 deletions
|
|
@ -1 +1 @@
|
|||
{"keys": [{"kty": "RSA", "use": "sig", "kid": "yecGJYHchQnJbz3K39V9KOyVLez8gS0H8rTCANPFumQ", "n": "nS_gIt--OOcboxtT5SS72quz8ajGlcPW4IYrVCMaiSTKBqYRWjf0MdaRLtq1LHlwKoyu14akwfk2x3IH0Wq76NNpXyF_gAWfd54d3F1vPuZyEMfPBihmukw-aj-YbJvqcxRcZveSy2CIYs4ThVMiGTD0KrmtpDZZxrb3vZqY-LxD1agw4JQ8Ro1kH3nvPgsOOQoDQwNY5jOKemmpNcG2P2kHX_fQGXyPt2LJjH6chOSMbdN4c6meH40ZS2IwvB8txSGGFtscxJtXeDZKvpnqMDmPhCsBEquO793atjsvF-oSs6XNoHmiyF6zK6J9iITtUqXZYX6J9BKPe2OXGQkweQ", "e": "AQAB"}, {"kty": "EC", "use": "sig", "kid": "5Z3ifjhKDHwjCW1DCx2PR8NiM6n1G3p84i10Mvtv3sU", "crv": "P-256", "x": "phDWGpA1jRpPbLNncAi0g34Of_x6dASVgB0GKrskJBk", "y": "l-qt3CJm9JToAqL5jeo512K7mJn8u-RvdzE9F28SGe8"}]}
|
||||
{"keys": [{"kty": "RSA", "use": "sig", "kid": "yecGJYHchQnJbz3K39V9KOyVLez8gS0H8rTCANPFumQ", "e": "AQAB", "n": "nS_gIt--OOcboxtT5SS72quz8ajGlcPW4IYrVCMaiSTKBqYRWjf0MdaRLtq1LHlwKoyu14akwfk2x3IH0Wq76NNpXyF_gAWfd54d3F1vPuZyEMfPBihmukw-aj-YbJvqcxRcZveSy2CIYs4ThVMiGTD0KrmtpDZZxrb3vZqY-LxD1agw4JQ8Ro1kH3nvPgsOOQoDQwNY5jOKemmpNcG2P2kHX_fQGXyPt2LJjH6chOSMbdN4c6meH40ZS2IwvB8txSGGFtscxJtXeDZKvpnqMDmPhCsBEquO793atjsvF-oSs6XNoHmiyF6zK6J9iITtUqXZYX6J9BKPe2OXGQkweQ"}, {"kty": "EC", "use": "sig", "kid": "5Z3ifjhKDHwjCW1DCx2PR8NiM6n1G3p84i10Mvtv3sU", "crv": "P-256", "x": "phDWGpA1jRpPbLNncAi0g34Of_x6dASVgB0GKrskJBk", "y": "l-qt3CJm9JToAqL5jeo512K7mJn8u-RvdzE9F28SGe8"}]}
|
||||
|
|
@ -73,20 +73,15 @@ async function beginRegistration() {
|
|||
}
|
||||
}
|
||||
|
||||
async function beginAuthentication(username) {
|
||||
async function beginAuthentication() {
|
||||
const statusEl = document.getElementById('webauthn-login-status');
|
||||
const form = new FormData();
|
||||
form.append('username', username);
|
||||
|
||||
try {
|
||||
// Step 1: Get options from server
|
||||
const beginRes = await fetch('/login/webauthn/begin', {
|
||||
method: 'POST',
|
||||
body: form,
|
||||
});
|
||||
// Step 1: Get options from server (no username needed)
|
||||
const beginRes = await fetch('/login/webauthn/begin');
|
||||
if (!beginRes.ok) {
|
||||
const text = await beginRes.text();
|
||||
if (statusEl) statusEl.innerHTML = text;
|
||||
const data = await beginRes.json();
|
||||
if (statusEl) statusEl.innerHTML = '<div role="alert">' + (data.error || 'Failed to start authentication') + '</div>';
|
||||
return;
|
||||
}
|
||||
const options = await beginRes.json();
|
||||
|
|
@ -100,7 +95,7 @@ async function beginAuthentication(username) {
|
|||
});
|
||||
}
|
||||
|
||||
// Step 3: Call browser WebAuthn API
|
||||
// Step 3: Call browser WebAuthn API — browser shows passkey picker
|
||||
const assertion = await navigator.credentials.get({ publicKey: publicKey });
|
||||
|
||||
// Step 4: Encode response for server
|
||||
|
|
@ -126,24 +121,27 @@ async function beginAuthentication(username) {
|
|||
|
||||
if (completeRes.ok) {
|
||||
const data = await completeRes.json();
|
||||
if (data.redirect) {
|
||||
window.location.href = data.redirect;
|
||||
} else {
|
||||
window.location.href = '/manage/credentials';
|
||||
}
|
||||
window.location.href = data.redirect || '/manage/credentials';
|
||||
} else {
|
||||
const text = await completeRes.text();
|
||||
if (statusEl) statusEl.innerHTML = text;
|
||||
const data = await completeRes.json().catch(function () { return {}; });
|
||||
if (statusEl) statusEl.innerHTML = '<div role="alert">' + (data.error || 'Authentication failed') + '</div>';
|
||||
}
|
||||
} catch (err) {
|
||||
if (statusEl) statusEl.innerHTML = '<div role="alert">Authentication failed: ' + err.message + '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
// Wire up the registration button
|
||||
// Wire up buttons
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const registerBtn = document.getElementById('webauthn-register-btn');
|
||||
if (registerBtn) {
|
||||
registerBtn.addEventListener('click', beginRegistration);
|
||||
}
|
||||
|
||||
const loginBtn = document.getElementById('webauthn-login-btn');
|
||||
if (loginBtn) {
|
||||
loginBtn.addEventListener('click', function () {
|
||||
beginAuthentication();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -24,12 +24,11 @@
|
|||
|
||||
<section>
|
||||
<h2>Security key</h2>
|
||||
<form id="webauthn-login-form">
|
||||
<div>
|
||||
<label for="webauthn-username">Username</label>
|
||||
<input type="text" id="webauthn-username" name="username" required autocomplete="username">
|
||||
</div>
|
||||
<button type="button" id="webauthn-login-btn">Sign in with security key</button>
|
||||
</form>
|
||||
<div id="webauthn-login-status"></div>
|
||||
<button type="button" id="webauthn-login-btn">Sign in with security key</button>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="/static/webauthn.js" defer></script>
|
||||
{% endblock %}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue