Skip to content
BoringStack
Star

OAuth provider setup

3 min read

Set up OAuth with Google, GitHub, and/or LinkedIn so users can sign in with their existing accounts. This runbook walks through each provider console.

Before creating OAuth apps, decide your domain and set these env vars:

Terminal window
FRONTEND_URL=https://example.com
PUBLIC_API_URL=https://example.com/api

All three providers will ask for redirect URIs. The pattern is:

https://example.com/api/v1/auth/oauth/{provider}/callback

Where {provider} is google, github, or linkedin.

During development, Traefik runs on localhost:7331. Register these additional redirect URIs in each provider console:

http://localhost:7331/api/v1/auth/oauth/google/callback
http://localhost:7331/api/v1/auth/oauth/github/callback
http://localhost:7331/api/v1/auth/oauth/linkedin/callback

Credentials go in infra/compose/compose/.env with the same variable names as production.

OAuth buttons render on the login page only when the API has credentials for a provider. The UI reads GET /api/v1/capabilities/ to determine which buttons to show. No UI-side OAuth client IDs are needed.

After changing env, restart the API:

Terminal window
./dev.sh restart api
  1. Google Cloud Console → APIs & Services → Credentials.

  2. Create OAuth client ID → Web application.

  3. Authorized redirect URIs: add:

https://example.com/api/v1/auth/oauth/google/callback
  1. Note the Client ID and Client secret.

  2. Add to compose/.env:

Terminal window
echo 'GOOGLE_OAUTH_CLIENT_ID=your-client-id.apps.googleusercontent.com' >> compose/.env
echo 'GOOGLE_OAUTH_CLIENT_SECRET=your-secret' >> compose/.env
  1. Restart the API.

Google requests scopes openid, email, and profile automatically. BoringStack handles the flow.

  1. GitHub → Settings → Developer settings → OAuth Apps → New OAuth App.

  2. Homepage URL: https://example.com

  3. Authorization callback URL:

https://example.com/api/v1/auth/oauth/github/callback
  1. Generate a Client secret.

  2. Add to compose/.env:

Terminal window
echo 'GITHUB_OAUTH_CLIENT_ID=your-github-client-id' >> compose/.env
echo 'GITHUB_OAUTH_CLIENT_SECRET=your-secret' >> compose/.env
  1. Restart the API.

BoringStack requests read:user and user:email scopes.

  1. LinkedIn Developer Portal → Create app.

  2. Under Auth → OAuth 2.0 settings → Authorized redirect URLs:

https://example.com/api/v1/auth/oauth/linkedin/callback
  1. Request the Sign In with LinkedIn using OpenID Connect product (required for the openid scope).

  2. Add credentials to compose/.env:

Terminal window
echo 'LINKEDIN_OAUTH_CLIENT_ID=your-linkedin-client-id' >> compose/.env
echo 'LINKEDIN_OAUTH_CLIENT_SECRET=your-secret' >> compose/.env
  1. Restart the API.

BoringStack requests openid, profile, and email scopes.

  1. Ensure Valkey is running (OAuth state storage).
  2. Hit GET /api/v1/capabilities/ and check that oauth.providers lists your configured providers.
  3. Open the login page. OAuth buttons appear only for providers with valid credentials.
  4. Try logging in. Successful flow: redirects to OAuth provider → redirects back → redirects to /dashboard.

If you’re using Provisioning with OpenTofu, add the same credentials to terraform.tfvars:

google_oauth_client_id = "op://Production/Google-OAuth/client_id"
google_oauth_client_secret = "op://Production/Google-OAuth/client_secret"
github_oauth_client_id = "op://Production/GitHub-OAuth/client_id"
github_oauth_client_secret = "op://Production/GitHub-OAuth/client_secret"
linkedin_oauth_client_id = "op://Production/LinkedIn-OAuth/client_id"
linkedin_oauth_client_secret = "op://Production/LinkedIn-OAuth/client_secret"

See terraform.tfvars.example for the complete example.