Documentation menu

Providers

Google OAuth

Uses the Ahena CLI (beta). Install it with npm install -g @ahena/cli, or prefix commands with npx @ahena/cli. See Installation. The dashboard covers projects, connections, Doctor, the Stack Graph, plans and approvals without it.

Overview

For apps that already have their own accounts and sign-in (a WordPress site, a Rails or Node app with its own user table) and add "Continue with Google" to them. Ahena keeps track of the Google OAuth client each environment uses, checks with Google that the client exists and that your exact redirect URIs are registered, checks that the client secret is stored, and lists the Google Cloud work only you can do, with the exact values. Your app talks to Google directly (Authorization Code flow, in your code); Ahena is never in the sign-in path.

This is not a hosted auth provider, and declaring it never means moving your users anywhere. If your app uses Supabase Auth or Firebase Authentication for sign-in, configure Google there instead.

Package: @ahena/provider-google-oauth · Category: oauth · Config section: oauth Capabilities: oauth-client (manual), redirect-uri-verification (read-only)

Status: Live verified (read-only, 2026-10-07): Google's discovery document, and Google's answers for a known client with a registered and an unregistered redirect URI and for an unknown client, using Google's public OAuth Playground client. Not live verified with a customer's own client yet. This covers the capabilities and test scope listed here; it doesn't mean every Google sign-in scenario has been tested, and Ahena doesn't call it production-ready. See status definitions.

Connection

Three things, kept apart (the roles in ADR 0003):

Role What Where it lives today
Management credential None. Google has no API for OAuth web clients; Ahena checks only through Google's public endpoints. —
Runtime credential The client secret, GOOGLE_OAUTH_CLIENT_SECRET (name configurable). Your app uses it to exchange sign-in codes. Stored in Ahena with ahena env set until ADR 0003's credential model is built. Giving it to your app is manual.
Runtime configuration (not secret) The client ID, and the redirect URIs per environment. The client ID in the connection (GOOGLE_OAUTH_CLIENT_ID, it's in every Google sign-in URL); redirect URIs in ahena.config.ts.

Connecting records the client ID for one environment, and Ahena asks Google's public sign-in endpoint whether the client exists.

ahena connect google-oauth -e staging --set GOOGLE_OAUTH_CLIENT_ID=1234-abc.apps.googleusercontent.com
ahena env set staging GOOGLE_OAUTH_CLIENT_SECRET     # the client secret: hidden prompt or stdin

Use a separate OAuth client per environment. Doctor warns when production and another environment share one (ahena.separation.shared_oauth_client), and when they share the same secret value.

Permissions

None: there's nothing to grant. Every check uses Google's public endpoints (accounts.google.com): the OpenID discovery document, and a GET to the authorization endpoint that isn't followed. Nobody signs in, nothing is created, and no consent screen is shown to anyone. permissionCheck is authentication-only because there is no credential whose permissions could be read.

Capabilities

export default {
  organization: "acme",
  project: "leo",
  framework: "wordpress",            // shapes the instructions for giving the secret to your app
  oauth: {
    provider: "google-oauth",
    clientId: { staging: "1234-stg.apps.googleusercontent.com", production: "1234-prd.apps.googleusercontent.com" },
    redirectUris: {
      staging: ["https://staging.leo.app/wp-json/myapp/v1/google/callback"],
      production: ["https://leo.app/wp-json/myapp/v1/google/callback"],
    },
    clientSecret: "GOOGLE_OAUTH_CLIENT_SECRET",    // its name in Ahena's secret store (this is the default)
    runtimeSecret: "MYAPP_GOOGLE_CLIENT_SECRET",   // optional: the name your app reads it as
  },
};
  • Setup steps before connecting. While oauth is declared but not connected in an environment, Doctor's coverage finding (and ahena plan) lists what to do in Google Cloud for that environment: create a "Web application" client, add exactly these redirect URIs, set up the consent screen, store the secret with ahena env set, give your app its copy, then connect.
  • Client check. Google knows the connected client (or answered invalid_client), and it's the one ahena.config.ts declares for the environment.
  • Redirect URI check. Each declared URI is checked for shape first (https; no localhost outside local and development; no fragment, wildcard, user info or path traversal), then Google is asked whether it's an authorized redirect URI of the client. A refused URI comes with the exact fix.
  • Runtime secret stored. Doctor checks that the client secret is stored in Ahena for the environment (google-oauth.secret.<name>), by name only. That's all it shows: stored in Ahena is not the same as used by your app, which Doctor reports separately as not verified.
  • Drift. ahena.lock records the client ID and which declared redirect URIs Google accepts, so a redirect URI removed in Google Cloud shows up in ahena drift.

Ahena doesn't generate sign-in code for this provider. What your server side needs is the Authorization Code flow with PKCE (S256), a single-use state bound to the browser, a nonce, the code exchanged server side, and the ID token validated against Google's published keys (iss, aud, exp, nonce, email_verified), with Google's sub as the identity and no automatic linking to an existing account by e-mail. See Google's OpenID Connect guide.

Limitations

  • Ahena can't create the OAuth client, edit its redirect URIs or set up the consent screen: Google has no public API for web clients. These stay manual, with the exact values.
  • Ahena doesn't give the client secret to your app, and can't tell whether your app uses it. It stores the runtime credential and checks it by name; you put it where your app reads it (wp-config.php, your host's environment variables). Doctor reports the app's copy as NOT VERIFIED (google-oauth.runtime_secret) and never claims otherwise. Delivery and fingerprint verification wait on ADR 0003.
  • The redirect URI check reads where Google's sign-in endpoint redirects. If Google answers in a way Ahena doesn't recognise, the check is a WARNING ("couldn't confirm"), never a pass.
  • One OAuth client per environment and provider. Other OAuth providers (GitHub, Microsoft) aren't supported yet.

Manual steps

Situation What to do
Not connected yet Follow the steps in Doctor's ahena.coverage.oauth finding: create the Web application client in Google Cloud → Credentials with the listed redirect URIs, set up the consent screen, ahena env set <env> GOOGLE_OAUTH_CLIENT_SECRET, give your app its copy, then ahena connect google-oauth -e <env> --set GOOGLE_OAUTH_CLIENT_ID=….
Redirect URI refused Open the client in Google Cloud → Credentials and add the URI exactly as shown (scheme, host, path and trailing slash must match).
Unknown client Check the client ID, or create a new client; then reconnect.
Rotating the secret Create a new secret on the client in Google Cloud, ahena env set <env> GOOGLE_OAUTH_CLIENT_SECRET, update your app's copy, then remove the old secret in Google Cloud.

Doctor checks

Id Severity Meaning
google-oauth.discovery PASS / FAIL Google's OpenID configuration is reachable, names Google as issuer and points only at Google's hosts.
google-oauth.client_id INFO / FAIL The connected client isn't the one ahena.config.ts declares (FAIL), or none is declared (INFO).
google-oauth.client PASS / WARNING / FAIL OAuth client exists: VERIFIED with Google (PASS); FAIL with the full setup steps when Google answers invalid_client; WARNING when Google's answer couldn't be read.
google-oauth.redirect_uris WARNING No redirect URIs declared for this environment.
google-oauth.redirect.<n> PASS / WARNING / FAIL Redirect URI registered: VERIFIED with Google (PASS) or not registered (FAIL in production, WARNING elsewhere); its shape is checked first.
google-oauth.secret.<name> PASS / FAIL Runtime secret stored in Ahena for this environment (name only). Not evidence that your app uses it.
google-oauth.runtime_secret INFO Runtime secret used by your app: NOT VERIFIED. Ahena has no evidence from the app; delivery is manual.
ahena.coverage.oauth FAIL Declared but not connected: lists the Google Cloud steps with this environment's exact values.
ahena.separation.shared_oauth_client WARNING Production and another environment use the same OAuth client.

Disconnect behavior

ahena disconnect google-oauth removes the connection. Ahena held no Google credential, so there's nothing to revoke; the OAuth client stays in Google Cloud and the secret stays in the environment's secret store until you remove it (ahena env unset <env> GOOGLE_OAUTH_CLIENT_SECRET). Ahena never deletes anything in Google Cloud.