OAuth login (Google)
Wire Google's OAuth 2.0 sign-in into a RustBase workspace. The recipe uses Google as the example; the same shape works for GitHub, Microsoft, or any OIDC-compliant provider.
What you'll build
A "Sign in with Google" button on your client app that, on click:
- Bounces the user to Google's consent screen.
- Returns to your client with a code.
- Your client forwards the code to RustBase.
- RustBase exchanges it for the user's email, links it to a workspace user, and issues an access + refresh token bound to that user.
1. Register a Google OAuth client
In the Google Cloud Console under APIs & Services → Credentials:
- Application type: Web application.
- Authorised JavaScript origins: your client's origin (
https://app.example.com). - Authorised redirect URIs:
https://<your-rustbase-host>/_/auth/oauth/google/callback.
Save the Client ID and Client secret. You'll paste them into the dashboard in a moment.
2. Add the provider in the dashboard
Visit /_/workspaces/acme/oauth/new. The dashboard ships Google / GitHub / Microsoft presets that prefill every URL field; pick Google.
| Field | Value |
|---|---|
| Provider slug | google |
| Client ID | from step 1 |
| Client secret | from step 1 |
| Scopes | openid email profile |
| Auth URL | https://accounts.google.com/o/oauth2/v2/auth |
| Token URL | https://oauth2.googleapis.com/token |
| Userinfo URL | https://openidconnect.googleapis.com/v1/userinfo |
| Userinfo ID field | /sub |
| Userinfo email field | /email |
The client secret is encrypted at rest under the workspace's KEK (a 256-bit key stored in system.db._secrets). The plaintext never round-trips back to the dashboard.
3. Build the consent-screen URL on your client
const params = new URLSearchParams({
client_id: '<google client id>',
redirect_uri: 'https://<your-rustbase-host>/_/auth/oauth/google/callback',
response_type: 'code',
scope: 'openid email profile',
access_type: 'offline',
state: crypto.randomUUID(),
});
window.location = `https://accounts.google.com/o/oauth2/v2/auth?${params}`;Persist state to sessionStorage before redirecting; you'll match it on the way back to defeat CSRF.
4. Receive the callback
Google redirects to https://<rustbase>/_/auth/oauth/google/callback?code=…&state=…. The dashboard's callback page:
- Validates
stateagainst the value you persisted. - Forwards the code to RustBase:
curl -s http://localhost:8080/api/workspaces/acme/auth/oauth/google/exchange \
-H "content-type: application/json" \
-d "{\"code\":\"$CODE\",\"redirect_uri\":\"https://<rustbase>/_/auth/oauth/google/callback\"}"The server:
- Posts to Google's token endpoint with the encrypted secret.
- Pulls
userinfoand reads theemail+subper the JSON pointers configured above. - Finds-or-creates a workspace user keyed by email.
- Records the linkage
(provider=google, provider_user_id=<sub>)inoauth_links. - Returns the standard auth response:
{ access_token, refresh_token, user }.
PKCE
Public clients — single-page apps, native mobile — should add PKCE. RustBase accepts the code_verifier on the exchange call:
curl -s http://localhost:8080/api/workspaces/acme/auth/oauth/google/exchange \
-H "content-type: application/json" \
-d "{
\"code\": \"$CODE\",
\"redirect_uri\": \"…\",
\"code_verifier\": \"$VERIFIER\"
}"…and the redirect URL on the way out includes:
&code_challenge=<S256(verifier)>
&code_challenge_method=S256Generate the verifier (43–128 unreserved chars) on the client, store it in sessionStorage, and send it on the exchange. The server forwards it to Google verbatim.
Variations
- GitHub — pick the GitHub preset. Note that GitHub's userinfo response uses
/id(an integer) as the stable identifier and/emailmay be empty (the user can mark their email private). Add theuser:emailscope and the server will fall back to the/user/emailsendpoint to find a verified address. - Generic OIDC — any provider that exposes
.well-known/openid-configurationworks. Pull the URLs from there and paste them into the dashboard. - Restrict to one domain — add an
email_domain_allowlistto the provider config (planned for a future release), or write aonUserBeforeRegisterhook that rejects emails outside@example.com.
Gotchas
- The redirect URI must match exactly —
https://app.example.com/callbackis NOT the same ashttps://app.example.com/callback/. Google's error in this case is a generic "redirect URI mismatch" with no further detail. - Existing email + new OAuth link — RustBase finds-by-email first. A user who registered with a password gets the OAuth link added to their existing row; the password still works alongside.
- OAuth tokens are NOT stored. RustBase reads
userinfoonce at exchange time and discards Google's access token. To call Google APIs on behalf of the user later, you need to add a hook that keeps Google's token in your own table.