GitHub OAuth Setup
GitHub OAuth Setup
Sign-in with GitHub uses src/server/auth.ts's github social provider (better-auth). Each
deployed domain (and localhost) needs its own GitHub OAuth App, because the callback URL is
matched exactly, an app registered for https://example.com/api/auth/callback/github will not
accept a login started from http://localhost:3000.
Why this needs a wizard, not a CLI flag
GitHub has no REST API or gh CLI command to create an OAuth App, only GitHub Apps support
the scriptable manifest-based creation flow; OAuth Apps are web-UI-only to register. gh api
can't reach an endpoint that doesn't exist.
make github.oauth.setup automates everything around that one manual step:
- Builds a pre-filled
https://github.com/settings/applications/newURL (name, homepage, callback URL all filled in fromconfig.ts) and opens it in your browser. - You click "Register application", then "Generate a new client secret", GitHub's UI, no way around it.
- Paste the Client ID and secret back into the terminal prompt.
- The script writes
GITHUB_CLIENT_ID/GITHUB_CLIENT_SECRET/VITE_GITHUB_CLIENT_IDinto the right env file.
Usage
make github.oauth.setup ENV=local # -> .env, callback http://localhost:3000/api/auth/callback/github
make github.oauth.setup ENV=prod # -> .env.production, callback https://<config.domainName>/api/auth/callback/github
ENV defaults to local if omitted. Run both once per domain you deploy to, a fresh clone
scaffolded to a new domain needs its own pair of apps, not a reused one.
After ENV=prod: the change only lands in the local .env.production file. Ship it with
make deploy.env and restart the app service so auth.ts picks up the new credentials.
Why per-domain, not one shared app
A single OAuth App's callback URL list can technically hold multiple URLs, but keeping prod and local as separate apps means a leaked/rotated local dev secret never touches the production app, and GitHub's "third-party access" screen for users shows the real app name/domain instead of a shared one covering unrelated environments.
Scopes
auth.ts requests user:email (login identity) and repo (deploy/git-integration features that
read the user's repos). If a downstream project doesn't need repo access, drop repo from the
scope array in auth.ts before running the wizard, GitHub shows requested scopes on the
consent screen but doesn't let you change them per-login after the app is registered.