handshakes

This commit is contained in:
DecDuck
2024-10-08 18:08:34 +11:00
parent 7523e536b5
commit 2b4382d013
8 changed files with 130 additions and 13 deletions

View File

@ -17,7 +17,7 @@ Client makes request: `POST /api/v1/client/handshake` with the token recieved in
The server uses it's CA to generate a public-private key pair, the CN of the client ID. It then sends that pair, plus the CA's public key, to the client, which stores it all.
The certificate lasts for a year, and is rotated when it has 3 months or less left on it's expiry.
*The certificate lasts for a year, and is rotated when it has 3 months or less left on it's expiry.*
## 4.a Client requests one-time device endpoint
The client generates a nonce and signs it with their private key. This is then attached to any device-related request.

View File

@ -31,4 +31,26 @@ export class CertificateAuthority {
}
return new CertificateAuthority(store, root);
}
async generateClientCertificate(clientId: string, clientName: string) {
const caCertificate = await this.certificateStore.fetch("ca");
if (!caCertificate)
throw new Error("Certificate authority not initialised");
const [priv, pub, cert] = droplet.generateClientCertificate(
clientId,
clientName,
caCertificate.cert,
caCertificate.priv
);
const certBundle: CertificateBundle = {
priv,
pub,
cert,
};
return certBundle;
}
async storeClientCertificate(clientId: string, bundle: CertificateBundle) {
await this.certificateStore.store(`client:${clientId}`, bundle);
}
}

View File

@ -1,4 +1,6 @@
import { v4 as uuidv4 } from "uuid";
import { CertificateBundle } from "./ca";
import prisma from "../db/database";
export interface ClientMetadata {
name: string;
@ -29,10 +31,14 @@ export class ClientHandler {
return clientId;
}
async fetchInitiateClientMetadata(clientId: string) {
async fetchClientMetadata(clientId: string) {
return (await this.fetchClient(clientId))?.data;
}
async fetchClient(clientId: string) {
const entry = this.temporaryClientTable[clientId];
if (!entry) return undefined;
return entry.data;
return entry;
}
async attachUserId(clientId: string, userId: string) {
@ -50,6 +56,32 @@ export class ClientHandler {
return token;
}
async fetchClientMetadataByToken(token: string) {
return Object.entries(this.temporaryClientTable)
.map((e) => Object.assign(e[1], { id: e[0] }))
.find((e) => e.authToken === token);
}
async finialiseClient(id: string) {
const metadata = this.temporaryClientTable[id];
if (!metadata) throw new Error("Invalid client ID");
if (!metadata.userId) throw new Error("Un-authorized client ID");
return await prisma.client.create({
data: {
id: id,
userId: metadata.userId,
endpoint: "",
capabilities: [],
name: metadata.data.name,
platform: metadata.data.platform,
lastConnected: new Date(),
},
});
}
}
export const clientHandler = new ClientHandler();