SHA256
99 lines
3.7 KiB
JavaScript
99 lines
3.7 KiB
JavaScript
document.getElementById('registerButton').addEventListener('click', register);
|
|
document.getElementById('loginButton').addEventListener('click', login);
|
|
|
|
|
|
function showMessage(message, isError = false) {
|
|
const messageElement = document.getElementById('message');
|
|
messageElement.textContent = message;
|
|
messageElement.style.color = isError ? 'red' : 'green';
|
|
}
|
|
|
|
async function register() {
|
|
// Retrieve the username from the input field
|
|
const username = document.getElementById('username').value;
|
|
|
|
try {
|
|
// Get registration options from your server. Here, we also receive the challenge.
|
|
const response = await fetch('/api/passkey/registerStart', {
|
|
method: 'POST', headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({username: username})
|
|
});
|
|
|
|
// Check if the registration options are ok.
|
|
if (!response.ok) {
|
|
const msg = await response.json();
|
|
throw new Error('User already exists or failed to get registration options from server: ' + msg);
|
|
}
|
|
|
|
// Convert the registration options to JSON.
|
|
const options = await response.json();
|
|
|
|
// This triggers the browser to display the passkey / WebAuthn modal (e.g. Face ID, Touch ID, Windows Hello).
|
|
// A new attestation is created. This also means a new public-private-key pair is created.
|
|
const attestationResponse = await SimpleWebAuthnBrowser.startRegistration(options.publicKey);
|
|
|
|
// Send attestationResponse back to server for verification and storage.
|
|
const verificationResponse = await fetch('/api/passkey/registerFinish', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify(attestationResponse)
|
|
});
|
|
|
|
|
|
const msg = await verificationResponse.json();
|
|
console.log(msg);
|
|
if (verificationResponse.ok) {
|
|
showMessage(msg, false);
|
|
} else {
|
|
showMessage(msg, true);
|
|
}
|
|
} catch
|
|
(error) {
|
|
showMessage('Error: ' + error.message, true);
|
|
}
|
|
}
|
|
|
|
async function login() {
|
|
// Retrieve the username from the input field
|
|
const username = document.getElementById('username').value;
|
|
|
|
try {
|
|
// Get login options from your server. Here, we also receive the challenge.
|
|
const response = await fetch('/api/passkey/loginStart', {
|
|
method: 'POST', headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({username: username})
|
|
});
|
|
// Check if the login options are ok.
|
|
if (!response.ok) {
|
|
const msg = await response.json();
|
|
throw new Error('Failed to get login options from server: ' + msg);
|
|
}
|
|
// Convert the login options to JSON.
|
|
const options = await response.json();
|
|
|
|
// This triggers the browser to display the passkey / WebAuthn modal (e.g. Face ID, Touch ID, Windows Hello).
|
|
// A new assertionResponse is created. This also means that the challenge has been signed.
|
|
const assertionResponse = await SimpleWebAuthnBrowser.startAuthentication(options.publicKey);
|
|
|
|
// Send assertionResponse back to server for verification.
|
|
const verificationResponse = await fetch('/api/passkey/loginFinish', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify(assertionResponse)
|
|
});
|
|
|
|
const msg = await verificationResponse.json();
|
|
if (verificationResponse.ok) {
|
|
showMessage(msg, false);
|
|
} else {
|
|
showMessage(msg, true);
|
|
}
|
|
} catch (error) {
|
|
showMessage('Error: ' + error.message, true);
|
|
}
|
|
}
|