server: add account creation and login
GitLab: #10
Change-Id: Iddd7ecee7210bc7b839cb2cec5d4291ac725d104
diff --git a/server/src/ws.ts b/server/src/ws.ts
index f75260a..7670695 100644
--- a/server/src/ws.ts
+++ b/server/src/ws.ts
@@ -18,32 +18,54 @@
import { IncomingMessage } from 'node:http';
import { Duplex } from 'node:stream';
+import { jwtVerify } from 'jose';
+import log from 'loglevel';
import { Service } from 'typedi';
+import { URL } from 'whatwg-url';
import { WebSocket, WebSocketServer } from 'ws';
-@Service()
-class Ws {
- async build() {
- await Promise.resolve(42);
+import { Vault } from './vault.js';
- const wss = new WebSocketServer({
- noServer: true,
- });
- wss.on('connection', (ws: WebSocket, _req: IncomingMessage, id: string) => {
- ws.on('message', (data) => {
- ws.send(
- JSON.stringify({
- id,
- data,
- })
- );
+@Service()
+export class Ws {
+ constructor(private readonly vault: Vault) {}
+
+ async build() {
+ const wss = new WebSocketServer({ noServer: true });
+ wss.on('connection', (ws: WebSocket, _req: IncomingMessage, accountId: string) => {
+ log.info('New connection', accountId);
+
+ ws.on('message', (_data) => {
+ ws.send(JSON.stringify({ accountId }));
});
});
+ const pubKey = await this.vault.pubKey();
+
return (request: IncomingMessage, socket: Duplex, head: Buffer) => {
- wss.handleUpgrade(request, socket, head, (ws) => wss.emit('connection', ws, request, '42'));
+ // Do not use parseURL because it returns a URLRecord and not a URL.
+ const url = new URL(request.url ?? '/', 'http://localhost/');
+ const accessToken = url.searchParams.get('accessToken');
+ if (!accessToken) {
+ socket.write('HTTP/1.1 400 Bad Request\r\n\r\n');
+ socket.destroy();
+ return;
+ }
+
+ jwtVerify(accessToken, pubKey, {
+ issuer: 'urn:example:issuer',
+ audience: 'urn:example:audience',
+ })
+ .then(({ payload }) => {
+ const id = payload.id as string;
+ log.info('Authentication successful', id);
+ wss.handleUpgrade(request, socket, head, (ws) => wss.emit('connection', ws, request, id));
+ })
+ .catch((reason) => {
+ log.debug('Authentication failed', reason);
+ socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
+ socket.destroy();
+ });
};
}
}
-
-export { Ws };