handle enter keypress register/login

This commit is contained in:
Sam Hadow 2025-02-15 16:11:50 +01:00
parent 24600a4f8b
commit 2073b81bbe
5 changed files with 116 additions and 91 deletions

View File

@ -21,6 +21,9 @@ const mainController = {
}, },
chat : (req, res) => { chat : (req, res) => {
res.sendFile(path.resolve(__dirname + '/../public/chat.js')); res.sendFile(path.resolve(__dirname + '/../public/chat.js'));
},
register : (req, res) => {
res.sendFile(path.resolve(__dirname + '/../public/register.js'));
} }
}; };

View File

@ -1,14 +1,19 @@
const currentUrl = window.location.href; import { loginConfirm, registerConfirm } from "./register.js";
import { ab2str, exportedKeyToPem, pemToKey, genKey } from "./ecc.js";
// close popups with escape key // handle key presses (close/confirm)
document.addEventListener("keydown", (event) => { document.addEventListener("keydown", async function(event) {
if (event.isComposing || event.key === 'Escape') { if (event.isComposing || event.key === 'Escape') {
Array.from(document.getElementsByClassName("popup")).forEach(function(x) { Array.from(document.getElementsByClassName("popup")).forEach(function(x) {
x.style.display = 'none'; x.style.display = 'none';
}); });
document.getElementById("registerPopupText").innerText = ""; document.getElementById("registerPopupText").innerText = "";
} } else if (event.key === 'Enter') {
if (registerPopup.style.display == 'flex') {
await registerConfirm();
} else if (loginPopup.style.display == 'flex') {
await loginConfirm();
}
}
}); });
// register popup // register popup
@ -21,43 +26,8 @@ document.getElementById("registercancel").addEventListener("click", function ()
document.getElementById("registerPopupText").innerText = ""; document.getElementById("registerPopupText").innerText = "";
}); });
// confirm // confirm
document.getElementById("registerconfirm").addEventListener("click", async function () { document.getElementById("registerconfirm").addEventListener("click", async () => {
const apiUrl = `${currentUrl}account/register`; await registerConfirm();
const inputFieldSharedSecret = document.getElementById("sharedsecret");
const inputFieldPublicKey = document.getElementById("publickey");
let pubkey = null;
if (!inputFieldPublicKey.value) {
const { privateKey, publicKey } = await genKey();
pubkey = exportedKeyToPem(publicKey, "public");
document.getElementById("registerPopupText").innerText = exportedKeyToPem(privateKey, "private");
} else {
pubkey = inputFieldPublicKey.value;
}
const postData = {
sharedSecret: inputFieldSharedSecret.value,
publicKey: pubkey
};
// clear input fields
inputFieldSharedSecret.value='';
inputFieldPublicKey.value='';
const requestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(postData)
};
const response = await fetch(apiUrl, requestOptions)
.catch(error => {
console.error('Error during POST request:', error);
});
if (response.ok) {
console.log(response);
} else {
throw new Error('Error in server response');
}
}); });
//login popup //login popup
@ -69,48 +39,6 @@ document.getElementById("logincancel").addEventListener("click", function () {
loginPopup.style.display = 'none'; loginPopup.style.display = 'none';
}); });
// confirm // confirm
document.getElementById("loginconfirm").addEventListener("click", async function () { document.getElementById("loginconfirm").addEventListener("click", async () => {
const apiUrl = `${currentUrl}account/login`; await loginConfirm();
const inputFieldPrivateKey = document.getElementById("privatekey");
const response = await fetch(apiUrl, { method: 'GET' });
if (!response.ok) {
throw new Error('Failed to fetch challenge');
}
const { challenge } = await response.json();
console.log("Received challenge:", challenge);
let privKey = await pemToKey(inputFieldPrivateKey.value, "private");
const encoder = new TextEncoder();
let encodedData = encoder.encode(challenge);
// Sign the data using the private key.
const signature = await crypto.subtle.sign(
{
name: "Ed25519",
},
privKey,
encodedData,
);
let signatureString = ab2str(signature);
let signatureBase64 = window.btoa(signatureString);
const verifyApiUrl = `${currentUrl}account/verify-challenge`;
const verifyResponse = await fetch(verifyApiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
signature: signatureBase64
})
});
if (!verifyResponse.ok) {
throw new Error('Failed to verify the challenge');
} else {
const verifyResult = await verifyResponse.json();
console.log("Verification result:", verifyResult);
location.reload();
}
}); });

89
src/public/register.js Normal file
View File

@ -0,0 +1,89 @@
const currentUrl = window.location.href;
import { ab2str, exportedKeyToPem, pemToKey, genKey } from "./ecc.js";
export async function registerConfirm() {
const apiUrl = `${currentUrl}account/register`;
const inputFieldSharedSecret = document.getElementById("sharedsecret");
const inputFieldPublicKey = document.getElementById("publickey");
let pubkey = null;
if (!inputFieldPublicKey.value) {
const { privateKey, publicKey } = await genKey();
pubkey = exportedKeyToPem(publicKey, "public");
document.getElementById("registerPopupText").innerText = exportedKeyToPem(privateKey, "private");
} else {
pubkey = inputFieldPublicKey.value;
}
const postData = {
sharedSecret: inputFieldSharedSecret.value,
publicKey: pubkey
};
// clear input fields
inputFieldSharedSecret.value='';
inputFieldPublicKey.value='';
const requestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(postData)
};
const response = await fetch(apiUrl, requestOptions)
.catch(error => {
console.error('Error during POST request:', error);
});
if (response.ok) {
console.log(response);
} else {
document.getElementById("registerPopupText").innerText = "Registration failed. Please try again.";
console.error('Error in server response.', response);
}
}
export async function loginConfirm() {
const apiUrl = `${currentUrl}account/login`;
const inputFieldPrivateKey = document.getElementById("privatekey");
const response = await fetch(apiUrl, { method: 'GET' });
if (!response.ok) {
throw new Error('Failed to fetch challenge');
}
const { challenge } = await response.json();
console.log("Received challenge:", challenge);
let privKey = await pemToKey(inputFieldPrivateKey.value, "private");
const encoder = new TextEncoder();
let encodedData = encoder.encode(challenge);
// Sign the data using the private key.
const signature = await crypto.subtle.sign(
{
name: "Ed25519",
},
privKey,
encodedData,
);
let signatureString = ab2str(signature);
let signatureBase64 = window.btoa(signatureString);
const verifyApiUrl = `${currentUrl}account/verify-challenge`;
const verifyResponse = await fetch(verifyApiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
signature: signatureBase64
})
});
if (!verifyResponse.ok) {
throw new Error('Failed to verify the challenge');
} else {
const verifyResult = await verifyResponse.json();
console.log("Verification result:", verifyResult);
inputFieldPrivateKey.value = '';
location.reload();
}
}

View File

@ -26,4 +26,8 @@ router
.route("/chat.js") .route("/chat.js")
.get(mainController.chat); .get(mainController.chat);
router
.route("/register.js")
.get(mainController.register);
module.exports = router; module.exports = router;

View File

@ -12,6 +12,7 @@ html(lang="en-US")
script(src="/chat.js", defer) script(src="/chat.js", defer)
else else
script(type="module", src="/popups.js", defer) script(type="module", src="/popups.js", defer)
script(type="module", src="/register.js", defer)
link(rel="stylesheet" href="/css/bootstrap.min.css") link(rel="stylesheet" href="/css/bootstrap.min.css")
body body
#mainbody #mainbody