Files
kompress_eshop/docs/integrations/google-oauth.md
2026-06-18 18:26:40 +02:00

4.9 KiB

Google OAuth2 sign-in

"Continue with Google" on /login and /register is wired through loco-oauth2. The code is complete and compiles; this doc is the checklist to make the live flow work. Until the credentials below are set, the button reaches Google and fails at the consent screen — the rest of auth (password login, registration, verification) is unaffected.

How the flow works (for context)

  1. User clicks Continue with GoogleGET /api/oauth2/google redirects to Google's consent screen.
  2. Google redirects back to GET /api/oauth2/google/callback/cookie. loco-oauth2 exchanges the code, fetches the profile, upserts the user (OAuth2UserTrait::upsert_with_oauth), stores an o_auth2_sessions row, sets its own private session cookie, and redirects to protected_url.
  3. protected_url = GET /api/oauth2/protected (our bridge, controllers/oauth2.rs::complete). It mints our auth_token JWT cookie and redirects: admins (email == ADMIN_EMAIL) → /admin/dashboard, everyone else → /.

From there the user is a normal logged-in user (same JWT cookie as a password login; the Casbin layer and guards treat them identically).

1. Create Google OAuth credentials

  1. Go to https://console.cloud.google.com/ → create/select a project.
  2. APIs & Services → OAuth consent screen: configure it (External), add the .../auth/userinfo.email and .../auth/userinfo.profile scopes, and add your Google account as a test user while the app is in "Testing".
  3. APIs & Services → Credentials → Create Credentials → OAuth client ID:
    • Application type: Web application.
    • Authorized redirect URIs — add exactly (must match the config's redirect_url, no trailing slash):
      • dev: http://localhost:5150/api/oauth2/google/callback/cookie
      • prod: https://YOUR_DOMAIN/api/oauth2/google/callback/cookie
  4. Copy the generated Client ID and Client secret.

2. Set environment variables (.env)

Read by config/development.yamlinitializers.oauth2 (and the prod equivalent). dotenvy loads .env on boot.

# Required
OAUTH_CLIENT_ID=xxxxxxxx.apps.googleusercontent.com
OAUTH_CLIENT_SECRET=xxxxxxxx

# Required in PRODUCTION (dev has working defaults)
OAUTH_PRIVATE_KEY="comma,separated,bytes >= 64 long"   # key for loco-oauth2's private cookie jar
OAUTH_REDIRECT_URL=https://YOUR_DOMAIN/api/oauth2/google/callback/cookie
OAUTH_PROTECTED_URL=https://YOUR_DOMAIN/api/oauth2/protected

Notes:

  • dev ships defaults for everything except OAUTH_CLIENT_ID / OAUTH_CLIENT_SECRET, so locally you only need those two.
  • OAUTH_PRIVATE_KEY must be ≥ 64 bytes (the dev default is a sample key — do not reuse it in production). Generate a fresh one, e.g. python3 -c "import os;print(','.join(str(b) for b in os.urandom(64)))".
  • OAUTH_REDIRECT_URL here and the Authorized redirect URI in the Google console must be byte-for-byte identical.

3. Run / test

nix develop -c cargo loco start   # MUST be inside nix develop (OpenSSL link, see memory)
  • auto_migrate: true (dev) creates the o_auth2_sessions table on boot.
  • Open http://localhost:5150/loginContinue with Google → consent → you should land back on / logged in (cart/nav reflect the session).

4. Production checklist

  • Separate OAuth client (or at least the prod redirect URI) in Google.
  • OAuth consent screen published (not just "Testing"), or real users get blocked.
  • OAUTH_PRIVATE_KEY set to a fresh ≥64-byte key (not the dev sample).
  • OAUTH_REDIRECT_URL / OAUTH_PROTECTED_URL use the real https:// origin.
  • server.host / public origin correct so cookies + redirects resolve.

Troubleshooting

Symptom Cause / fix
redirect_uri_mismatch at Google Authorized redirect URI ≠ OAUTH_REDIRECT_URL. Make them identical (scheme, host, port, path, no trailing slash).
403 / "access blocked: app not verified" Add your account as a test user, or publish the consent screen.
openssl-sys ... Could not find directory at build You ran cargo outside the dev shell. Use nix develop -c cargo ....
Callback 500 / "could not create oauth2 store" initializers.oauth2 missing/invalid, or OAUTH_PRIVATE_KEY < 64 bytes.
Logged into Google but not into the app The bridge (/api/oauth2/protected) didn't run — check protected_url (OAUTH_PROTECTED_URL) points at it.

Where things live

  • Config: config/development.yaml / config/production.yamlinitializers.oauth2
  • Client store + session initializers: src/initializers/oauth2.rs, src/initializers/oauth2_session.rs
  • Routes + bridge handler: src/controllers/oauth2.rs
  • User upsert (random password per advisory LOC-2025-04): src/models/users.rs (OAuth2UserTrait)
  • Session table: src/models/o_auth2_sessions.rs + migration/.../m20260618_000001_o_auth2_sessions.rs