#!/usr/bin/env node // A throwaway OAuth client for driving the authorize flow by hand, so the // consent screen can be seen and verified. Runs a loopback client through PAR, // then fetches (and saves) the consent page and prints the authorize URL to // open in a browser. // // node scripts/oauth-probe.mjs [--scope "..."] [--login-hint ] // // Env: BASE (default http://localhost:2471). import { writeFileSync } from 'node:fs'; import { DpopClient, seedDpopNonce } from '../test/helpers/dpop.js'; const BASE = process.env.BASE || 'http://localhost:2471'; const args = process.argv.slice(2); const arg = (name, fallback) => { const i = args.indexOf(name); return i >= 0 ? args[i + 1] : fallback; }; const clientId = 'http://localhost:3000'; const redirectUri = 'http://localhost:3000/callback'; const scope = arg('--scope', 'atproto transition:generic'); const loginHint = arg('--login-hint', 'test.host.docker.internal'); const dpop = await DpopClient.create(); await seedDpopNonce(BASE); const parProof = await dpop.createProof('POST', `${BASE}/oauth/par`); const parRes = await fetch(`${BASE}/oauth/par`, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', DPoP: parProof, }, body: new URLSearchParams({ client_id: clientId, redirect_uri: redirectUri, response_type: 'code', scope, code_challenge: 'E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM', code_challenge_method: 'S256', login_hint: loginHint, }).toString(), }); if (!parRes.ok) { console.error(`PAR failed: ${parRes.status} ${await parRes.text()}`); process.exit(1); } const { request_uri } = await parRes.json(); const authorizeUrl = `${BASE}/oauth/authorize?client_id=${encodeURIComponent(clientId)}&request_uri=${encodeURIComponent(request_uri)}`; const consent = await fetch(authorizeUrl, { headers: { Accept: 'text/html' } }); const html = await consent.text(); writeFileSync('/tmp/consent.html', html); console.log(`scope: ${scope}`); console.log( `consent GET: ${consent.status} (${html.length} bytes -> /tmp/consent.html)`, ); console.log( `react mode: ${/window\.__PDS__=JSON\.parse/.test(html) ? 'yes (SPA consent)' : 'no (server-rendered)'}`, ); console.log(`\nOpen in a browser to click through:\n${authorizeUrl}`);