Sign in with Google — free, no license required. Radon handles the OAuth exchange, fetches the profile, and merges by verified email.
Google sign-in is part of the free tier (the other 50 OAuth providers are Pro). Radon builds the consent URL, exchanges the code for tokens, fetches the user's profile, and resolves them to a user by verified email.
1. Create Google credentials
In the Google Cloud Console → APIs & Services → Credentials, create an OAuth 2.0 Client ID (type: Web application).
Under Authorized redirect URIs, add your callback URL, e.g.
https://acme.com/api/auth/google/callback. This must match redirectUri
exactly.
Copy the Client ID and Client secret.
2. Enable the provider
export const auth = new Radon({
adapter: postgresAdapter(pool),
session: { secret: process.env.RADON_SECRET! },
providers: {
google: {
clientId: process.env.RADON_GOOGLE_CLIENT_ID!,
clientSecret: process.env.RADON_GOOGLE_CLIENT_SECRET!,
redirectUri: "https://acme.com/api/auth/google/callback",
},
},
});Credentials can come from the environment
If you set RADON_GOOGLE_CLIENT_ID, RADON_GOOGLE_CLIENT_SECRET, and
RADON_GOOGLE_REDIRECT_URI, you can omit them from the config entirely —
providers: { google: {} } is enough.
| Option | Type | Description |
|---|---|---|
clientId | string | Falls back to RADON_GOOGLE_CLIENT_ID. |
clientSecret | string | Falls back to RADON_GOOGLE_CLIENT_SECRET. |
redirectUri | string | Falls back to RADON_GOOGLE_REDIRECT_URI. Must match the console. |
scopes | string[] | Default ["openid", "email", "profile"]. |
3. Use it over HTTP
| Method & path | Query | Effect |
|---|---|---|
GET /google/start | ?state=… | Redirects the user to Google's consent screen |
GET /google/callback | ?code=…&state=… | Signs in → sets cookie, then redirects |
You don't fetch these — you send the user's browser to them. A "Sign in with Google" button is just a link:
<a href="/api/auth/google/start">Sign in with Google</a>Google redirects back to /api/auth/google/callback, Radon completes the
exchange, sets the radon_session cookie, and 302-redirects to your
successRedirect (default /). Configure that in the
framework handler.
4. Or call it directly in code
If you're wiring the flow yourself (no HTTP integration):
// 1. Build the consent URL and redirect the user to it.
const url = auth.google.getAuthUrl({ state: csrfToken });
// → returns a string. `redirect(url)`.
// 2. On your callback route, exchange the `code` query param:
const { user, created, profile } = await auth.google.handleCallback(code);
const { token } = auth.createSessionToken(user.id); // issue a session yourselfGoogle's getAuthUrl returns a string
auth.google.getAuthUrl(...) returns the URL as a string. (The
Pro OAuth providers return an object
{ url, codeVerifier?, state? } instead, because they support PKCE — don't mix
the two up.)
getAuthUrl options
auth.google.getAuthUrl({
state: "csrf-token", // echoed back on the callback — use it for CSRF
scopes: ["openid", "email"], // override the default scopes
accessType: "offline", // request a refresh token
prompt: "consent", // force the consent screen
loginHint: "sam@acme.com", // pre-fill the account chooser
});handleCallback(code) returns { user, created, profile }, where profile is
the raw Google userinfo (sub, email, name, picture, …) in case you want
extra fields.
How merging works
Google emails are verified, so handleCallback merges by email: if a user
with that address already exists (from any method), the Google identity is linked
to that same account. A user who used an email code last week and Google today is
one user, not two. → Merge-by-email