Official plugin — Google sign-in via OIDC discovery and JWKS-verified ID tokens.
Google is the reference OIDC provider for oauth(): discovery, ID-token
signature checks, and issuer pinning all work the textbook way. If you are
wiring your first social provider, start here.
The one rule
Register https://app.example.com/auth/oauth/callback/google (your exact origin) as an Authorized
Redirect URI, then enable it with providers.google.enabled. The comparison is byte-exact.
Quick start
Create OAuth credentials
In Google Cloud Console → APIs & Services → Credentials, create an OAuth client ID of type Web application. Add your callback URI under Authorized Redirect URIs.
Plug it
import { oke } from "okengine";
import { oauth } from "okengine/plugins";
export const app = oke({
name: "shop",
env: "dev",
gate: { auth: {} },
}).plug(
oauth({
baseUrl: "https://app.example.com",
providers: {
google: { enabled: true },
},
}),
);Set the client secret
# .env.local
OAUTH_GOOGLE_CLIENT_SECRET=GOCSPX-...Boot fails loudly if the secret is missing — the contract is declared by the plugin itself.
How identity works
The driver discovers Google's endpoints from
https://accounts.google.com/.well-known/openid-configuration and caches them.
On callback it verifies the ID token end-to-end:
| Check | Rule |
|---|---|
| Signature | RS256 / ES256 against Google's published JWKS |
| Issuer | must equal https://accounts.google.com |
| Audience | must include your client id (azp when multi-audience) |
| Expiry | rejected when stale |
| Nonce | single-use, bound to the flow row |
Email trust follows the OIDC claim: email_verified: true marks the address
verified; anything else — including string "false" — stays unverified.
Default scopes: openid, email, profile.
Options
| Option | Type | Default | Meaning |
|---|---|---|---|
enabled | boolean | false | Turn the provider on |
clientId | string | Vault/env* | \*OAUTH_GOOGLE_CLIENT_ID |
redirectUri | string | {baseUrl}…/google | Exact registered URI |
scopes | string[] | driver defaults | Extra scopes |
storeProviderTokens | boolean | false | Keep tokens in Vault |
Surfaces
| Flow | Path |
|---|---|
| Start | POST /auth/oauth/google/start |
| Callback | GET+POST /auth/oauth/callback/google |
| Link | POST /auth/oauth/google/link |
Troubleshooting
The registered URI and the sent URI differ. Byte-exact means scheme, host,
port, path, no trailing slash drift. Copy the value from
providers.google.redirectUri or baseUrl synthesis.
OAUTH_GOOGLE_CLIENT_SECRET is missing or stale. Secrets resolve through the
Vault chain — update .env.local or your Vault driver, then restart.
You are using credentials from a different Google project than the one that issued the code, or swapped client ids between environments.