Self-hosted, federated location sharing app and server that prioritizes user privacy and security
end-to-end-encryption location-sharing privacy self-hosted federated
at auth 2.5 kB view raw
1import { expect } from "bun:test"; 2 3export const URL = "http://127.0.0.1:3000"; 4 5// Generate an Ed25519 keypair and register it with the server. 6export async function generateUser(signup_key: string | undefined, should_be_admin: boolean = false): Promise<{ user_id: string; pubKey: Uint8Array; privKey: Uint8Array }> { 7 if (!signup_key) { 8 throw new Error("signup_key was not provided or captured from server output"); 9 } 10 11 // Create Ed25519 keypair 12 const keyPair = await crypto.subtle.generateKey({ name: "Ed25519" }, true, ["sign", "verify"]); 13 14 // Export raw public key 15 const pubKey = new Uint8Array(await crypto.subtle.exportKey("raw", keyPair.publicKey)); 16 const privKey = new Uint8Array(await crypto.subtle.exportKey("pkcs8", keyPair.privateKey)); 17 18 // Base64 encode the public key 19 const pub_key_b64 = btoa(String.fromCharCode(...pubKey)); 20 21 // Send signup_key and pubkey to server 22 const res = await fetch(`${URL}/create-account`, { 23 method: "POST", 24 headers: { "Content-Type": "application/json" }, 25 body: JSON.stringify({ signup_key, pub_key_b64 }), 26 }); 27 28 expect(res.status).toBe(200); 29 const json = await res.json(); 30 expect(json).toEqual({ 31 user_id: expect.any(String), 32 is_admin: should_be_admin, 33 }); 34 35 return { user_id: json.user_id, pubKey, privKey }; 36} 37 38export async function post(endpoint: string, user: { user_id: string; privKey: Uint8Array }, data: Object | string | undefined): Promise<any> { 39 let bodyBytes: Uint8Array; 40 41 if (typeof data === "object") { 42 const json = JSON.stringify(data); 43 bodyBytes = new TextEncoder().encode(json); 44 } else if (typeof data === "string") { 45 bodyBytes = new TextEncoder().encode(data); 46 } else { 47 bodyBytes = new Uint8Array(); 48 } 49 50 // Sign body using private key 51 const privateKey = await crypto.subtle.importKey("pkcs8", user.privKey.buffer, { name: "Ed25519" }, false, ["sign"]); 52 53 const signature = new Uint8Array(await crypto.subtle.sign("Ed25519", privateKey, bodyBytes)); 54 const signature_b64 = btoa(String.fromCharCode(...signature)); 55 56 const authJson = JSON.stringify({ 57 user_id: user.user_id, 58 signature: signature_b64, // changed key 59 }); 60 const authHeader = btoa(authJson); 61 62 const headers: Record<string, string> = { 63 "x-auth": authHeader, 64 "Content-Type": "application/json", 65 }; 66 67 const res = await fetch(`${URL}/${endpoint}`, { 68 method: "POST", 69 headers, 70 body: bodyBytes.length > 0 ? new TextDecoder().decode(bodyBytes) : undefined, 71 }); 72 73 expect(res.status).toBe(200); 74 return await res.text(); 75}