Files

68 lines
2.5 KiB
JavaScript

#!/usr/bin/env node
/**
* Mint a login-link token and print a URL that logs you in as a given user.
*
* For support/debugging only. The session it creates is stamped
* `impersonatedBy: 'login-link'` so it's auditable.
*
* Config (env or edit the constants below):
* BETTER_AUTH_SECRET HS256 signing secret for the target environment
* APP_URL Base URL of the app, e.g. https://app.example.com
*
* Usage:
* BETTER_AUTH_SECRET=... APP_URL=https://app.example.com \
* node scripts/impersonate.mjs <user-uuid> <user-email> [redirect-path] [ttl]
*
* Examples:
* node scripts/impersonate.mjs 3f2a... [email protected]
* node scripts/impersonate.mjs 3f2a... [email protected] /courses 30m
*/
import { SignJWT } from 'jose';
// Load a .env file if present. Override the path with ENV_FILE=... if needed.
// Existing process.env values are NOT overwritten by the file.
try {
process.loadEnvFile(process.env.ENV_FILE ?? new URL('../.env', import.meta.url));
} catch {
// no .env found — fall back to real env vars / the constants below
}
// --- config (env wins; otherwise fill these in) -----------------------------
const BETTER_AUTH_SECRET = process.env.BETTER_AUTH_SECRET ?? '';
const APP_URL = process.env.APP_URL ?? 'https://app.classroomio.com';
// ----------------------------------------------------------------------------
const [userId, email, redirect = '/', ttl = '10m'] = process.argv.slice(2);
function fail(message) {
console.error(`\n ✗ ${message}\n`);
process.exit(1);
}
if (!BETTER_AUTH_SECRET) fail('Set BETTER_AUTH_SECRET (env var or the constant in this file).');
if (!APP_URL) fail('Set APP_URL (env var or the constant in this file), e.g. https://app.example.com');
if (!userId || !email) {
fail('Usage: node scripts/impersonate.mjs <user-uuid> <user-email> [redirect-path] [ttl]');
}
if (!redirect.startsWith('/')) fail('redirect-path must start with "/" (same-site only).');
const secret = new TextEncoder().encode(BETTER_AUTH_SECRET.trim());
const token = await new SignJWT({
sub: userId,
email: email.toLowerCase().trim(),
type: 'login-link'
})
.setProtectedHeader({ alg: 'HS256' })
.setIssuedAt()
.setExpirationTime(ttl)
.sign(secret);
const base = APP_URL.replace(/\/+$/, '');
const url = `${base}/api/auth/login-link?token=${encodeURIComponent(token)}&redirect=${encodeURIComponent(redirect)}`;
console.log(`\n Login as: ${email} (${userId})`);
console.log(` Expires in: ${ttl}\n`);
console.log(url);
console.log('\n Open this URL in a fresh/incognito window to start the session.\n');