150 lines
4.2 KiB
JavaScript
150 lines
4.2 KiB
JavaScript
import { render, html } from '/uhtml.js';
|
|
|
|
function rand() {
|
|
let str = '';
|
|
const lookups =
|
|
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'.split('');
|
|
while (str.length < 16) {
|
|
const n = Math.random() * lookups.length;
|
|
str += lookups[Math.floor(n)];
|
|
}
|
|
return str;
|
|
}
|
|
|
|
async function auth() {
|
|
window.session = rand();
|
|
|
|
window.emit = (event, data, callback) =>
|
|
window.socket.emit(event, {
|
|
...data,
|
|
__session: window.session,
|
|
}, callback);
|
|
|
|
window.signedMessage = await openpgp.sign({
|
|
message: new openpgp.CleartextMessage('vybe_auth ' + window.session, ''),
|
|
signingKeys: window.keys.priv
|
|
});
|
|
|
|
window.socket.emit('authenticate', {
|
|
name: window.name,
|
|
id: `${window.id || ''}@${location.host}`,
|
|
message: signedMessage,
|
|
pubkey: window.keys.armored.publicKey
|
|
},
|
|
async msg => {
|
|
if (!msg.success) {
|
|
console.log('authenticate failed:', msg.message);
|
|
if (document.getElementById('app'))
|
|
location.reload();
|
|
document.getElementById('result').innerText = msg.message;
|
|
return;
|
|
}
|
|
localStorage.setItem('keys', JSON.stringify(window.keys.armored));
|
|
localStorage.setItem('name', window.name = msg.name);
|
|
localStorage.setItem('id', window.id = msg.id);
|
|
window.displayname = msg.displayname;
|
|
if (window.instancelist) {
|
|
if (window.instancelist[0].url !== location.host
|
|
|| window.instancelist[0].id !== msg.instance.id) {
|
|
console.log('instance url or id changed ??');
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
localStorage.setItem('instances', JSON.stringify(window.instancelist = [
|
|
{
|
|
id: msg.instance.id,
|
|
url: location.host
|
|
}
|
|
]));
|
|
}
|
|
instancelist[0].socket = window.socket;
|
|
instancelist[0].emit = window.emit;
|
|
window.instances = Object.fromEntries(instancelist.map(i => [i.url, i]));
|
|
document.getElementById('register')?.remove();
|
|
const { authRequest } = await import('/app.js');
|
|
msg.authrequests.forEach(authRequest);
|
|
document.getElementById('profilepublic').checked = msg.public;
|
|
});
|
|
}
|
|
|
|
async function submit(event) {
|
|
event.preventDefault();
|
|
const name = document.getElementById('name').value;
|
|
if (!name)
|
|
return;
|
|
const keys = await openpgp.generateKey({
|
|
userIDs: [{ name }]
|
|
});
|
|
const priv = await openpgp.readKey({ armoredKey: keys.privateKey });
|
|
const pub = await openpgp.readKey({ armoredKey: keys.publicKey });
|
|
window.keys = { priv, pub, armored: keys };
|
|
window.name = name;
|
|
if (this.id === 'registerform') {
|
|
window.socket.emit('create_user',
|
|
{ name, pubkey: keys.publicKey },
|
|
(msg) => {
|
|
if (!msg.success) {
|
|
document.getElementById('result').innerText = msg.message;
|
|
return;
|
|
}
|
|
auth();
|
|
}
|
|
);
|
|
}
|
|
else {
|
|
await auth();
|
|
document.getElementById('result').innerHTML =
|
|
`now open your profile on your other device to approve this authentication.
|
|
this session's ID is <strong>${pub.getFingerprint().slice(0,8)}</strong>`;
|
|
}
|
|
}
|
|
|
|
render(document.body, html`
|
|
<div id='register' class='hidden'>
|
|
<h1>welcome to vybe</h1>
|
|
<h3>a communication network (beta)</h3>
|
|
<p>
|
|
to get started, you'll need an account. we use public key cryptography
|
|
for security, rather than passwords. your keys are stored in your
|
|
browser storage only, so do this on a browser you can access again.
|
|
</p>
|
|
<p>
|
|
if you already have an account, enter your username here,
|
|
and you can authenticate using your other device.
|
|
</p>
|
|
<form onsubmit=${submit} id='registerform'>
|
|
<label for='name'>username: </label>
|
|
<input id='name' type='text' />
|
|
<button id='submit' type='submit'>register</button>
|
|
<button onclick=${submit}>authenticate</button>
|
|
</form>
|
|
<p id='result'></p>
|
|
</div>
|
|
`);
|
|
|
|
window.onload = async () => {
|
|
window.socket = io();
|
|
|
|
let keys = localStorage.getItem('keys');
|
|
if (keys) {
|
|
window.name = localStorage.getItem('name');
|
|
window.id = localStorage.getItem('id');
|
|
window.instancelist = JSON.parse(localStorage.getItem('instances'));
|
|
keys = JSON.parse(keys);
|
|
window.keys = {
|
|
priv: await openpgp.readKey({ armoredKey: keys.privateKey }),
|
|
pub: await openpgp.readKey({ armoredKey: keys.publicKey }),
|
|
armored: keys
|
|
};
|
|
await auth();
|
|
}
|
|
else
|
|
document.getElementById('register').classList.remove('hidden');
|
|
|
|
window.socket.io.on('reconnect', async attempt => {
|
|
if (window.keys)
|
|
await auth();
|
|
});
|
|
};
|