Skip to content

feat: OAuth login flow with stored credentials#4

Open
timgl wants to merge 1 commit into
mainfrom
posthog-code/oauth-login
Open

feat: OAuth login flow with stored credentials#4
timgl wants to merge 1 commit into
mainfrom
posthog-code/oauth-login

Conversation

@timgl
Copy link
Copy Markdown
Contributor

@timgl timgl commented May 14, 2026

Summary

  • Add posthog-definitions login / logout commands. Login opens a browser, runs PKCE OAuth against the chosen host (US/EU/custom), prompts for a project, and saves the result to $XDG_CONFIG_HOME/posthog-definitions/config.json with mode 0600.
  • Use the CIMD (Client ID Metadata Document) pattern — same as posthog/wizard. No DB row needs to be created up-front; the OAuth server fetches the metadata doc on first authorize.
  • HTTP client now resolves the Authorization header per request through an AuthHandler, auto-refreshes tokens nearing expiry, and retries once on 401 after a refresh.
  • POSTHOG_PERSONAL_API_KEY env var still wins over the stored token so CI/automation keep working unchanged. Resolution: CLI flag > env var > store > default.

Test plan

  • pnpm typecheck passes
  • pnpm lint clean
  • pnpm test — all 119 unit tests pass
  • posthog-definitions login against https://us.posthog.com, pick a project, then apply --dry-run works without POSTHOG_* env vars
  • posthog-definitions login --switch-project reuses the existing token
  • posthog-definitions logout clears the file
  • Setting POSTHOG_PERSONAL_API_KEY overrides the stored OAuth token
  • Expired access token triggers a silent refresh on the next apply/pull

Created with PostHog Code

Introduces `posthog-definitions login` / `logout` commands. Login opens
a browser, completes PKCE OAuth against the chosen PostHog host using
the CIMD (Client ID Metadata Document) pattern, prompts for a project,
and persists credentials to $XDG_CONFIG_HOME/posthog-definitions/config.json
with mode 0600.

Auth precedence in loadConfig: CLI flag > env var > stored config.
POSTHOG_PERSONAL_API_KEY still wins so CI keeps working unchanged. The
HTTP client now resolves the Authorization header per request via an
AuthHandler, auto-refreshes OAuth tokens nearing expiry, and retries
once on 401 after asking the handler to refresh.

Generated-By: PostHog Code
Task-Id: 23898cd3-e63c-40ac-a759-a4d69db06be9
Comment thread src/cli/login.ts
tokens = await performOAuthFlow({ host, clientId });
} catch (err) {
if (err instanceof OAuthError) {
console.error(`error: ${err.message}`);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants