OAuth Setup
Configure Google and GitHub OAuth providers for your Minnesota Toy Library application.
Minnesota Toy Library includes Google and GitHub OAuth via Better Auth, with support for additional providers.
Features
- Email/password authentication
- Google OAuth ("Continue with Google")
- GitHub OAuth ("Continue with GitHub")
- Automatic account linking (same email = linked accounts)
- Automatic user creation on first OAuth sign-in
- Session management via Better Auth (httpOnly cookies)
- Two-factor authentication (TOTP + backup codes)
- Proxy-safe (works behind Caddy/Nginx)
Google OAuth
- Go to Google Cloud Console
- Create OAuth client ID (Web application)
- Add redirect URI:
https://yourdomain.com/api/auth/callback/google - Copy Client ID and Client Secret
- Add to your
.env.local:
GOOGLE_CLIENT_ID=your-client-id
GOOGLE_CLIENT_SECRET=your-client-secretGitHub OAuth
- Go to GitHub Developer Settings
- Create new OAuth App
- Homepage URL:
https://yourdomain.com - Authorization callback URL:
https://yourdomain.com/api/auth/callback/github - Copy Client ID and Client Secret
- Add to your
.env.local:
GITHUB_CLIENT_ID=your-client-id
GITHUB_CLIENT_SECRET=your-client-secretRequired URLs
Make sure these are set correctly:
APP_URL=https://yourdomain.com
BETTER_AUTH_URL=https://yourdomain.comHow the auth flow works
- User clicks "Continue with Google" or "Continue with GitHub"
- Better Auth redirects to the OAuth provider
- User authorizes the app
- Provider redirects back to
/api/auth/callback/{provider} - Better Auth checks if the user exists (by email), creates or links the account, and creates a session
- User is redirected to
/app
Database tables
Better Auth manages these tables:
| Table | Purpose |
|---|---|
user | User profiles with custom fields (plan, stripeCustomerId, etc.) |
account | OAuth provider accounts linked to users |
session | Active sessions |
verification | Email verification and password reset tokens |
twoFactor | TOTP secrets and backup codes |
Adding more providers
Better Auth supports many OAuth providers. To add one:
- Add the provider to
socialProvidersinlib/auth.ts:
socialProviders: {
// ... existing providers
microsoft: {
clientId: process.env.MICROSOFT_CLIENT_ID || "",
clientSecret: process.env.MICROSOFT_CLIENT_SECRET || "",
},
}- Add a button to
app/auth/page.tsx:
await authClient.signIn.social({ provider: "microsoft", callbackURL: "/app" });- Set up the OAuth app with the provider and add credentials to
.env.local
Troubleshooting
redirect_uri_mismatch
The redirect URI in your OAuth app settings must exactly match:
https://yourdomain.com/api/auth/callback/{provider}No trailing slashes.
Session not persisting
Check that BETTER_AUTH_URL and APP_URL environment variables are set correctly.
No email from GitHub
Better Auth requests the user:email scope from GitHub automatically.
Security notes
- Never commit OAuth credentials to git
- Use environment variables for all secrets
BETTER_AUTH_SECRETshould be a random 32+ character string- In production, cookies are automatically set to
secure: true - Security headers are configured in
next.config.ts