diff --git a/docs/oauth_manual_testing.md b/docs/oauth_manual_testing.md new file mode 100644 --- /dev/null +++ b/docs/oauth_manual_testing.md @@ -0,0 +1,99 @@ +# Manually testing the OAuth login flow + +This guide walks through a real browser-based OAuth login for GhostOff without disturbing your existing app-password session. + +## 1. Create a dedicated OAuth environment file + +Copy your existing `.env` and remove the app password: + +```bash +cp .env .env.oauth +``` + +Edit `.env.oauth` and **delete or comment out** `ATP_APP_PASSWORD`. Keep everything else, especially: + +```env +GHOST_URL=https://your-ghost-site.com +GHOST_API_KEY=your-ghost-content-api-key +ATP_IDENTIFIER=your-handle-or-did +ATPUBLICATION_AT_URI=at://did:plc:.../site.standard.publication/... +``` + +If you omit `ATP_IDENTIFIER`, the CLI will prompt you for a handle at runtime. + +## 2. Run GhostOff with OAuth-only auth + +Use isolated session/state files so your default `ghostoff-oauth-session.json` is not affected: + +```bash +env $(cat .env.oauth | xargs) npm run dev -- \ + --oauth-session-file ghostoff-oauth-session-test.json \ + --oauth-state-file ghostoff-oauth-state-test.json +``` + +You can also add `--verbose` for more detail. + +## 3. Authenticate in the browser + +The CLI starts a temporary HTTP server on `127.0.0.1:` and prints an authorization URL: + +```text +Open this URL in your browser to authenticate GhostOff: +https://selfhosted.social/oauth/...?request_uri=...&client_id=http%3A%2F%2Flocalhost%2F%3F... +``` + +The CLI also tries to open the URL automatically. If it doesn't, copy and paste it into your browser. + +Log in to your PDS and approve GhostOff. Because this is a local-development OAuth client, the `client_id` defaults to `http://localhost/?redirect_uri=...` and the callback lands on `http://127.0.0.1:/callback`. + +## 4. Wait for the redirect + +After you approve, the PDS redirects to the local callback server. You should see: + +```text +Authentication successful. You can close this tab and return to the terminal. +``` + +In the terminal you should see something like: + +```text +authenticated as did:plc:... +session ready: your-handle.example.com (did:plc:...) +``` + +The migration then proceeds normally. + +## 5. Verify it uploaded + +Once the run finishes, check your Offprint publication to confirm the posts appeared. + +## If the PDS rejects the default `client_id` + +The atproto local-development exception expects the `client_id` origin to be `http://localhost` and the callback to be `127.0.0.1`. If your PDS insists on `http://127.0.0.1` as the `client_id` origin, override it: + +```bash +env $(cat .env.oauth | xargs) npm run dev -- \ + --oauth-client-id "http://127.0.0.1/?redirect_uri=http%3A%2F%2F127.0.0.1%2Fcallback&scope=atproto%20transition%3Ageneric" \ + --oauth-session-file ghostoff-oauth-session-test.json \ + --oauth-state-file ghostoff-oauth-state-test.json +``` + +## Re-testing the full flow + +To force a fresh login, delete the test session file and run again: + +```bash +rm ghostoff-oauth-session-test.json +env $(cat .env.oauth | xargs) npm run dev -- \ + --oauth-session-file ghostoff-oauth-session-test.json \ + --oauth-state-file ghostoff-oauth-state-test.json +``` + +To test session restore instead, leave the session file in place and run the same command a second time. It should skip the browser step and use the cached OAuth session. + +## Troubleshooting + +- **Browser doesn't open:** copy the printed URL manually. +- **"OAuth state mismatch" or callback errors:** make sure you didn't start a second GhostOff process while the first is still waiting for the callback; the loopback server only handles one callback. +- **Callback never reaches the terminal:** ensure your browser is running on the same machine as the CLI, because the callback server binds to `127.0.0.1` only. +- **Migration prompts for a handle instead of using `ATP_IDENTIFIER`:** `ATP_IDENTIFIER` was empty; the prompt is the intended fallback.