/login and /register.
Prerequisites
- A GitHub account.
- Your production domain decided.
- Five minutes — GitHub’s OAuth flow is the simplest of the three majors.
Step-by-step setup
-
Open Developer settings. github.com/settings/developers
→ OAuth Apps → New OAuth App. (For an org-owned app, use
github.com/organizations/<org>/settings/applicationsinstead.) -
Fill in the form:
No trailing slash on the callback URL. Add a second OAuth App for local dev pointing at
Field Value Application name Your product name (users see this on the consent screen). Homepage URL https://your-domain.comAuthorization callback URL https://your-domain.com/api/auth/callback/githubhttp://localhost:3000/api/auth/callback/github, or register both URLs by creating dev + prod apps separately. - Generate a client secret. Click Generate a new client secret on the OAuth App page. Copy it now — GitHub only shows it once.
-
Drop into
.env.local: -
Enable the button. In
src/config/site.ts: -
Restart
pnpm dev. Env vars are read at startup.
Scopes
Better Auth requestsread:user and user:email by default — enough to populate
user.name, user.email, and user.image. You don’t need to ask for repo or
anything else unless your product actually uses the GitHub API on the user’s
behalf. Asking for more scopes than necessary tanks signup conversion.
If you later need a wider scope (say, to read a user’s repos), pass scopes in
the provider config in src/lib/auth.ts:
Verify it works
- Visit
/login— the “Continue with GitHub” button should be visible. - Click it. You bounce to GitHub’s consent page, hit Authorize, land back on
/dashboard. - Inspect the
accounttable — a row withproviderId = 'github'should be linked to youruserrow. - Sign up with email first, then sign in with GitHub using the same email — they
merge into a single
user(account-linking is on for trusted providers).
Common pitfalls
- Trailing slash on the callback URL. GitHub matches it character-for-character.
…/callback/github/(with slash) ≠…/callback/github(without). Use the version without the trailing slash. - Single OAuth App for dev + prod. GitHub’s free OAuth Apps only allow one
callback URL. Make two apps —
MyProduct (dev)andMyProduct (prod)— with separate client IDs. - Email permission not granted. Some users have all their GitHub emails set to
private. Better Auth still works — it falls back to the
noreplyemail. If you rely on hitting their primary inbox, surface a “please complete your profile” flow on first sign-in. - Org-restricted accounts. If a user’s GitHub org enforces SSO, your OAuth App needs to be approved by an org admin before the user can authorize it.
- Client secret leaked once shown. GitHub does not show secrets twice. If you lost it, regenerate — invalidates the old one immediately.
Official docs
- Creating an OAuth App — docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app
- Authorizing OAuth Apps — docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps
- Scopes for OAuth Apps — docs.github.com/en/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps
- Better Auth GitHub provider — better-auth.com/docs/authentication/github