#!/usr/bin/env node // Generiert ANON_KEY und SERVICE_ROLE_KEY (JWTs, HS256) aus dem JWT_SECRET // in der .env. Ohne diese Keys können GoTrue und PostgREST nicht reden. // (Gespiegelt von RAPPORT-SERVER — generisch, nicht app-spezifisch.) // // Aufruf: // node scripts/generate-keys.mjs # liest JWT_SECRET aus .env // node scripts/generate-keys.mjs # explizit übergeben import crypto from "node:crypto"; import fs from "node:fs"; function base64url(input) { return Buffer.from(input).toString("base64") .replace(/=+$/, "").replace(/\+/g, "-").replace(/\//g, "_"); } function signJwt(payload, secret) { const header = base64url(JSON.stringify({ alg: "HS256", typ: "JWT" })); const body = base64url(JSON.stringify(payload)); const sig = base64url(crypto.createHmac("sha256", secret).update(`${header}.${body}`).digest()); return `${header}.${body}.${sig}`; } let secret = process.argv[2]; if (!secret) { try { const env = fs.readFileSync(".env", "utf8"); const m = env.match(/^JWT_SECRET=(.+)$/m); if (m) secret = m[1].trim().replace(/^["']|["']$/g, ""); } catch {} } if (!secret || secret.length < 32 || secret.includes("CHANGE-ME")) { console.error("✗ Kein gültiges JWT_SECRET gefunden (mind. 32 Zeichen, nicht der Placeholder)."); console.error(" Setze JWT_SECRET in .env oder gib es als Argument:"); console.error(" node scripts/generate-keys.mjs $(openssl rand -hex 32)"); process.exit(1); } const now = Math.floor(Date.now() / 1000); const tenYears = now + 10 * 365 * 24 * 3600; const anonKey = signJwt({ role: "anon", iss: "supabase", iat: now, exp: tenYears }, secret); const serviceKey = signJwt({ role: "service_role", iss: "supabase", iat: now, exp: tenYears }, secret); console.log("ANON_KEY=" + anonKey); console.log("SERVICE_ROLE_KEY=" + serviceKey); console.error(""); console.error("→ Werte in .env eintragen (überschreibt CHANGE-ME-Placeholder).");