OAuth providers
Configure Google, GitHub, and other OAuth providers for social sign-in.
#OAuth providers
EmuView supports OAuth social login through Better Auth's OAuth plugin. Users can sign in with their existing Google or GitHub accounts instead of creating a new password.
#Supported providers
| Provider | Env vars required | Setup |
|---|---|---|
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET |
Google Cloud Console → APIs & Services → Credentials | |
| GitHub | GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET |
GitHub Developer Settings → OAuth Apps |
#Configure a provider
- Create an OAuth app in the provider's developer console
- Set the redirect URI to
https://your-domain.com/api/auth/callback/<provider> - Add the credentials to your
wrangler.tomlor.env:
[vars]
GOOGLE_CLIENT_ID = "your-client-id.apps.googleusercontent.com"
GOOGLE_CLIENT_SECRET = "your-client-secret"
- Deploy with
wrangler deploy
#OAuth across multiple workspaces
If you host more than one workspace, each one that has claimed its own hostname
completes the OAuth flow on that hostname. A user signing in at
acme.example.com is sent back to
https://acme.example.com/api/auth/callback/google, not to the deployment's own
domain — so their session is created in the workspace they started from.
This means every hosted hostname needs its own entry in the provider's authorised redirect URIs list. One OAuth app covers all of them; add a line per workspace:
https://example.com/api/auth/callback/google
https://acme.example.com/api/auth/callback/google
https://beta.example.com/api/auth/callback/google
Providers do not accept wildcards here, so this is a step when a workspace claims a hostname. Miss it and the provider refuses the sign-in with a redirect-URI mismatch — visible immediately, and fixed by adding the line. Nothing silently signs the user into the wrong workspace.
Client IDs are resolved per workspace (oauth.google_client_id in Settings), so
a workspace may name its own OAuth app; the client secret is read from the
deployment environment and is shared, so a workspace-specific app needs its
secret deployed alongside.
#Giving a workspace its own OAuth app
The alternative to listing every hostname on one app: a workspace registers its own app with the provider and stores both halves here.
curl -X PUT -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{"clientId":"...","clientSecret":"..."}' "https://your-instance/api/v1/system/oauth-apps/google"
The workspace's own app is used whenever it is configured; otherwise the
deployment's app is. GET /api/v1/system/oauth-apps lists what a workspace has
configured and which providers the deployment can offer unaided, and DELETE
removes an app so the workspace falls back to the deployment's.
Both halves are required together, and always come from the same app. The client id alone will not save. This is not fussiness: the client id has been a per-workspace setting for some time while the secret came from the deployment's environment, so it was previously possible to set a workspace's client id and have it paired with a different app's secret. Every sign-in would fail at the token exchange, and nothing in the console would look wrong. A provider without a complete, matching pair is now simply not offered.
The secret is never readable back. It is encrypted at rest and no endpoint returns it — not the settings API, and not even the response to the request that set it. To change it, save a new pair.
If you rotate BETTER_AUTH_SECRET, stored OAuth secrets can no longer be
decrypted (the same is true of stored storage-connection keys and TOTP secrets).
Affected workspaces fall back to the deployment's app and log a warning naming
the workspace; re-save their OAuth app to restore it.
#Sign in with OAuth (SDK)
const { redirectUrl } = await sdk.auth.oAuthSignIn({
provider: 'google',
callbackUrl: 'https://your-app.com/auth/callback'
});
window.location.href = redirectUrl;
After the provider redirects back, the SDK automatically exchanges the code and stores the session.
#What you learned
- OAuth providers are configured via environment variables
- Google and GitHub are supported out of the box
- The SDK handles the full OAuth flow with
oAuthSignIn()
#Next steps
- Two-factor authentication for an extra layer of security
- API keys for server-side access
- SDK authentication for the full SDK auth API