OAuth Providers
This guide walks through registering OAuth 2.0 / OpenID Connect apps for the four providers Orkestra supports out of the box: Google, Apple, GitHub, and Discord. Email/password login works without any of these — OAuth is opt-in.
:::info Where credentials live
As of the auth-module ConfigService refactor (PR-C), OAuth client IDs, secrets, and redirect URLs are runtime configuration owned by the auth module. The recommended workflow:
- (Optional) Seed env vars on a fresh install — the auth module reads
OAUTH_<PROVIDER>_*on first boot and writes them intomodule_configsin MongoDB. - Manage them from then on at
/admin/modules/authin the operator console. Secrets are AES-256-GCM encrypted at rest.
Env-var names follow the convention OAUTH_<PROVIDER>_<FIELD> (e.g. OAUTH_GOOGLE_CLIENT_ID). Older docs that show GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET without the OAUTH_ prefix are stale.
See backend/internal/core/auth/CLAUDE.md for the canonical field-by-field schema.
:::
Prerequisites
- Access to the respective provider developer portals (Google Cloud Console, Apple Developer, GitHub, Discord)
- Orkestra backend running and reachable at your operator and client hosts. Set
ALLOW_LOCALHOST_REDIRECTS=trueindocker/.envfor development; do not ship that to production.
Google OAuth setup
Step 1: access Google Cloud Console
- Go to Google Cloud Console.
- Sign in with your Google account.
- Create a new project or select an existing one.
Step 2: enable required APIs
- Navigate to APIs & Services → Library.
- Search for and enable:
- Google+ API
- Google Identity Toolkit API
Step 3: configure OAuth consent screen
- Go to APIs & Services → OAuth consent screen.
- Choose External user type (unless for internal organization).
- Fill in the required information:
- App name: Orkestra
- User support email: your support email
- App logo: upload your logo (optional)
- Application home page:
https://yourdomain.com - Authorized domains: add your domain(s)
- Developer contact information: your email
- Add scopes:
openid,email,profile. - Save and continue.
Step 4: create OAuth 2.0 credentials
- Navigate to APIs & Services → Credentials.
- Click Create Credentials → OAuth client ID.
- Select Web application as the application type.
- Configure:
- Name: Orkestra Web Client
- Authorized JavaScript origins:
https://console.orkestra.com(operator, prod)https://api.orkestra.com(client, prod)http://console.localhost:8080(dev, operator)http://client.localhost:8081(dev, client)
- Authorized redirect URIs (callbacks land on the backend, not the frontend):
https://console.orkestra.com/v1/auth/oauth/google/callbackhttps://api.orkestra.com/v1/auth/oauth/google/callbackhttp://console.localhost:3000/v1/auth/oauth/google/callback(dev, operator)http://api.localhost:3000/v1/auth/oauth/google/callback(dev, client)
- Click Create.
- Save the Client ID and Client Secret — paste them into
/admin/modules/authunder the Google group (or setOAUTH_GOOGLE_CLIENT_ID/OAUTH_GOOGLE_CLIENT_SECRETas seed env vars on first boot).
Step 5: mobile app configuration (if needed)
- Create another OAuth client ID.
- Select iOS or Android as the application type.
- For iOS: enter your Bundle ID.
- For Android: enter your Package name and your SHA-1 certificate fingerprint.
- Save the configuration.
Apple Sign In setup
Step 1: access Apple Developer account
- Go to Apple Developer.
- Sign in with your Apple ID.
- Ensure you have an active Developer Program membership.
Step 2: register App ID
- Navigate to Certificates, Identifiers & Profiles.
- Click Identifiers → + button.
- Select App IDs and click Continue.
- Select App and click Continue.
- Fill in:
- Description: Orkestra
- Bundle ID: Choose Explicit and enter
com.yourdomain.orkestra
- Under Capabilities, enable Sign In with Apple.
- Click Continue and Register.
Step 3: create Service ID (for Web)
- In Identifiers, click + button.
- Select Services IDs and click Continue.
- Fill in:
- Description: Orkestra Web Service
- Identifier:
com.yourdomain.orkestra.web
- Click Continue and Register.
- Click on the created Service ID to configure.
- Enable Sign In with Apple.
- Click Configure next to Sign In with Apple.
- Set:
- Primary App ID: select your App ID from Step 2.
- Domains and Subdomains: add your operator + client hosts (e.g.
console.orkestra.com,api.orkestra.com). Apple does not acceptlocalhost; use ngrok for local development. - Return URLs (callbacks land on the backend):
https://console.orkestra.com/v1/auth/oauth/apple/callbackhttps://api.orkestra.com/v1/auth/oauth/apple/callback
- Click Next, Done, and Continue.
- Click Save.
Step 4: create private key
- Navigate to Keys → + button.
- Enter a Key Name: Orkestra Auth Key.
- Enable Sign In with Apple.
- Click Continue and Register.
- Download the private key (
.p8file).- IMPORTANT: save this file securely — you can't download it again.
- Note the Key ID shown on the page.
Step 5: gather required information
You'll need:
- Team ID: found in your Apple Developer account (top right corner).
- Service ID: the identifier created in Step 3 (e.g.
com.yourdomain.orkestra.web). - Key ID: from Step 4.
- Private Key: the
.p8file downloaded in Step 4.
GitHub OAuth setup
- Go to GitHub Developer Settings → OAuth Apps.
- Click New OAuth App and fill in:
- Application name: Orkestra
- Homepage URL:
https://console.orkestra.com(or your operator host) - Authorization callback URL:
https://console.orkestra.com/v1/auth/oauth/github/callback
- Register the app, then click Generate a new client secret.
- Save the Client ID and Client Secret — paste them into
/admin/modules/authunder the GitHub group (or useOAUTH_GITHUB_CLIENT_ID/OAUTH_GITHUB_CLIENT_SECRETas seed env vars). - To support both operator and client tiers, repeat with the client host (
https://api.orkestra.com/...) — GitHub only allows one callback per app, so you typically register two GitHub OAuth apps (one per tier) and switch credentials by audience.
Discord OAuth setup
- Go to the Discord Developer Portal and create a New Application.
- Open OAuth2 → General. Add redirects:
https://console.orkestra.com/v1/auth/oauth/discord/callbackhttps://api.orkestra.com/v1/auth/oauth/discord/callbackhttp://console.localhost:3000/v1/auth/oauth/discord/callback(dev)
- Click Reset Secret to generate a client secret.
- Save the Client ID and Client Secret — paste them into
/admin/modules/authunder the Discord group (orOAUTH_DISCORD_CLIENT_ID/OAUTH_DISCORD_CLIENT_SECRET). - Required scopes Orkestra requests:
identify email.
Environment configuration
Backend (seed env vars, optional)
These env vars are read only on first boot of a fresh install to seed module_configs. After that, manage values from /admin/modules/auth. Secrets are AES-256-GCM encrypted at rest by ConfigService.
# Google OAuth
OAUTH_GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
OAUTH_GOOGLE_CLIENT_SECRET=your-google-client-secret
OAUTH_GOOGLE_REDIRECT_URL=https://console.orkestra.com/v1/auth/oauth/google/callback
# Apple Sign In
OAUTH_APPLE_TEAM_ID=your-team-id
OAUTH_APPLE_CLIENT_ID=com.yourdomain.orkestra.web # Apple Service ID
OAUTH_APPLE_KEY_ID=your-key-id
OAUTH_APPLE_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----\n... # inline PEM (preferred)
OAUTH_APPLE_PRIVATE_KEY_PATH=/app/keys/AuthKey_XXXXXX.p8 # OR file fallback
OAUTH_APPLE_REDIRECT_URL=https://console.orkestra.com/v1/auth/oauth/apple/callback
# GitHub
OAUTH_GITHUB_CLIENT_ID=your-github-client-id
OAUTH_GITHUB_CLIENT_SECRET=your-github-client-secret
OAUTH_GITHUB_REDIRECT_URL=https://console.orkestra.com/v1/auth/oauth/github/callback
# Discord
OAUTH_DISCORD_CLIENT_ID=your-discord-client-id
OAUTH_DISCORD_CLIENT_SECRET=your-discord-client-secret
OAUTH_DISCORD_REDIRECT_URL=https://console.orkestra.com/v1/auth/oauth/discord/callback
# JWT — Orkestra uses RS256 (asymmetric), NOT a shared HMAC secret.
# `make init` generates these for you under docker/keys/ — see init.sh.
JWT_PRIVATE_KEY_PATH=/app/keys/jwt-private.pem
JWT_PUBLIC_KEY_PATH=/app/keys/jwt-public.pem
Frontend
The browser never talks to OAuth providers directly — it redirects to the backend endpoint at /v1/auth/oauth/<provider>/login, which crafts the provider authorization URL with state, scopes, and the correct redirect URL. So the frontend does not need provider client IDs.
# frontend-admin (operator console) — .env.production
VITE_API_URL=https://console.orkestra.com
# frontend-client (Tier-2 client SPA) — .env.production
VITE_API_BASE=https://api.orkestra.com
Mobile
For the Flutter mobile app, update:
iOS — ios/Runner/Info.plist:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>com.googleusercontent.apps.YOUR_GOOGLE_IOS_CLIENT_ID</string>
</array>
</dict>
</array>
Android — add the Google services configuration file to android/app/google-services.json.
Testing OAuth integration
Local development
-
Ensure your backend is running and reachable as both
http://console.localhost:3000(operator) andhttp://api.localhost:3000(client) — the host mux dispatches onHost. Add entries to/etc/hostsif needed:127.0.0.1 console.localhost api.localhost client.localhost -
Start the frontends — operator on
http://console.localhost:8080, client SPA onhttp://client.localhost:8081. -
From the operator login page, click Sign in with Google (or GitHub / Discord / Apple via ngrok). The browser is redirected to
http://console.localhost:3000/v1/auth/oauth/google/login, then to Google, then back to/v1/auth/oauth/google/callback, which sets the operator refresh cookie and redirects to the dashboard. -
Repeat from the client SPA to verify the client-tier flow lands the refresh cookie on the
api.*host withaud=clientin the JWT.
Production
- Deploy your application to your domain.
- Ensure HTTPS is properly configured.
- Test both authentication flows (operator + client).
- Verify tokens are properly generated and stored.
Security best practices
- Never commit secrets to version control.
- Use environment variables (or, better, ConfigService) for all sensitive configuration.
- Implement HTTPS for production deployments.
- Rotate keys periodically.
- Implement rate limiting on authentication endpoints (built in —
RATE_LIMIT_REQUESTS_PER_MINUTE/RATE_LIMIT_BURST). - Log authentication attempts for security monitoring (built in — see
complianceaddon). - Use secure session management with JWT tokens (built in — RS256, refresh-token rotation).
- Implement refresh token rotation (built in — see
backend/internal/core/auth/).
Troubleshooting
Common Google OAuth issues
Error: redirect_uri_mismatch
- Ensure the redirect URI in your request matches exactly with configured URIs.
- Check for trailing slashes and protocol (
httpvshttps).
Error: invalid_client
- Verify Client ID and Client Secret are correct.
- Check if the OAuth consent screen is properly configured.
Common Apple Sign In issues
Error: invalid_grant
- Ensure the authorization code is used only once.
- Verify the redirect URI matches exactly.
Error: invalid_client
- Check Team ID, Service ID, and Key ID are correct.
- Verify the private key file is accessible and valid.
JWT token issues
- Ensure the private key file has correct permissions.
- Verify the key hasn't expired.
- Check the algorithm matches (ES256 for Apple).
Support
- Google OAuth: Google Identity Platform documentation
- Apple Sign In: Sign in with Apple documentation
- Orkestra issues: open one on the monorepo
Pre-production checklist
- Google OAuth credentials created and configured (operator + client hosts)
- Apple Sign In credentials created and configured (operator + client hosts; ngrok used for local)
- GitHub OAuth app(s) created — one per tier if you need both
- Discord OAuth credentials created and configured
- Credentials stored in
/admin/modules/auth(ConfigService), not in plain.envin prod - Redirect URIs registered for production hosts (
console.orkestra.com,api.orkestra.com) - RS256 keys (
jwt-private.pem/jwt-public.pem) generated andJWT_PRIVATE_KEY_PATH/JWT_PUBLIC_KEY_PATHset - HTTPS enabled on production
- OAuth tested in development environment (both operator and client tiers)
- OAuth tested in production environment
- Security best practices implemented
- Monitoring and logging configured
- Documentation shared with team