Sign in with Google for EvoSys Pro, off by default (#430) by MikeSimmonsAI · Pull Request #433 · MikeSimmonsAI/advisorflow-web · GitHub
Skip to content

Sign in with Google for EvoSys Pro, off by default (#430) - #433

Merged
MikeSimmonsAI merged 2 commits into
mainfrom
feature/evosys-google-signin-430
Oct 29, 2026
Merged

MikeSimmonsAI merged 2 commits into
mainfrom
feature/evosys-google-signin-430

Conversation

@MikeSimmonsAI

Copy link
Copy Markdown
Owner

Closes #430 once turned on. Separate from PR #431 (white fields / badge). Do not merge before #431. Both touch EvosysLogin.jsx, evosys-login.css and evosysLogin.test.mjs, so this branch will be rebased after #431 merges.

Status: built and tested, OFF

  • Production has no GOOGLE_SIGNIN_* variables.
  • After merge, the login page looks exactly as it does today, with no Google button.
  • Every /auth/google/* endpoint answers 404 or {"enabled": false} until the owner completes the Google Cloud setup in docs/auth/GOOGLE_SIGNIN.md.
  • Merging creates three empty tables.

Security design

  • OIDC flow. Server-side authorization code with PKCE S256, a nonce, and state bound to the starting browser by an HttpOnly SameSite=Lax cookie (stops login CSRF). Single-use transactions that expire in 10 minutes (stops replay).
  • ID token verification. Signature against Google's keys, issuer, audience = our client id, expiry, nonce, and email_verified.
  • No silent linking.
    • A Google account signs in only if a signed-in user explicitly linked it from Settings, matched on Google sub.
    • An email match never signs anyone in and never links anything.
    • Unknown, unlinked and inactive accounts all get the same message, so nothing reveals which accounts exist.
  • Session hand-off. A 2-minute single-use ticket is passed in the URL fragment. The app removes it from the address bar and redeems it by POST from the allowed origin. The session token never appears in a URL, log or Referer.
  • Same rules as the password login.
    • The account must be active.
    • It must belong to the platform (brand) it signs in on: a BookaBoost account is refused on EvoSys.
    • Routing comes from the server's /auth/my-contexts.
    • Sessions and logout work unchanged, and roles never change.
  • Restricted areas. The platform owner (god_admin) is password-only unless GOOGLE_SIGNIN_ALLOW_GOD=1. GOD Mode and the Executive Suite never appear on the login page, and an advisor signed in with Google is still denied /god and /executive.
  • Never shown or logged: secrets, tokens and codes. Audit lines use AUDIT:, and the endpoints are rate-limited.
  • No inert button. The page shows Google only when /auth/google/config says it is enabled for that origin. Any failure means no button.
  • EvoSys only. BookaBoost, Harmony Hustle and AdvisorFlow login pages are not changed.

Affected screens

  • EvoSys Pro login: the "or / Continue with Google" row appears only when enabled.
  • Settings: a "Sign in with Google" card (connect or disconnect) appears only when enabled.
  • New route /auth/google/complete.

Screenshots

These come from a local test harness: the real backend, a simulated Google account chooser, and synthetic data. They show the feature turned on.

Tests

Backend: tests/test_google_signin.py, 20/20 pass, using real RS256 ID tokens signed by a test key. Coverage:

  • off by default; origin gating;
  • linked sign-in, then session and logout; password login still works;
  • unlinked account refused even with a matching email;
  • unverified email; wrong audience, issuer or nonce; expired token; forged signature;
  • state replay and tampering; missing browser cookie;
  • Google cancel and provider error; open-redirect attempts;
  • brand isolation; inactive user;
  • link, sign in, unlink; duplicate links; link requires a session;
  • god_admin policy; no role change, with /god and /executive denied.

Full backend suite: 1402 passed, 4 failed. The same 4 fail on main (roofing mission-control, 3 worker-isolation review-request fixture tests).

Browser E2E: 13/13 pass. The harness used Chromium with the real backend and a simulated Google chooser. Checks:

  • the button appears only when enabled;
  • an unlinked account is refused even with a matching email;
  • cancel shows a message;
  • linking works from Settings;
  • Google sign-in lands in the workspace;
  • the ticket is removed from the URL;
  • no page errors;
  • god is not offered;
  • mobile layout.

Frontend: evosysLogin.test.mjs 8/8. API-contract, workspace-entry and UI static-guard tests pass.

Build

vite build passes.

Owner steps before turning it on

See docs/auth/GOOGLE_SIGNIN.md. In short:

  1. Create (or reuse) a Google OAuth Web client.
  2. Add the redirect URI https://advisorflow-backend.onrender.com/auth/google/callback.
  3. Set up the consent screen with the openid, email and profile scopes.
  4. Set GOOGLE_SIGNIN_CLIENT_ID, GOOGLE_SIGNIN_CLIENT_SECRET and GOOGLE_SIGNIN_REDIRECT_URI on advisorflow-backend.
  5. Set GOOGLE_SIGNIN_ENABLED=1 last.
  6. Do an end-to-end check with a real Google account.

It has not been tested against real Google. That needs the owner's credentials.

Shared files are coordinated via #239: Login.jsx, client.js, App.jsx, Settings.jsx, main.py, registry.py.


Generated by Claude Code

Adds "Continue with Google" to the EvoSys Pro login, behind GOOGLE_SIGNIN_ENABLED
(unset in production, so nothing changes until the owner configures Google Cloud).

- Server-side OIDC: authorization code with PKCE (S256), nonce, state bound to the
  starting browser by an HttpOnly cookie (login CSRF), single-use transactions.
- ID token verified with Google's keys: signature, issuer, audience, expiry, then
  nonce and email_verified.
- Accounts are found only by an explicit link (Google sub) made by the signed-in
  user from Settings. An email match never signs anyone in or links anything.
- Session hand-off by a 2-minute single-use ticket in the URL fragment, redeemed by
  POST from the allowed origin; the session token never appears in a URL.
- Same checks as the password login: active account, platform (brand) isolation,
  server-side routing via /auth/my-contexts, no role changes; god_admin is
  password-only unless GOOGLE_SIGNIN_ALLOW_GOD=1.
- No inert button: the login shows Google only when /auth/google/config says so.
- docs/auth/GOOGLE_SIGNIN.md: owner Google Cloud setup and env vars.
- tests/test_google_signin.py: 20 tests with real RS256 tokens.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QVM51EcDqHYqkghjpEmfBt
@vercel

vercel Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

@MikeSimmonsAI
MikeSimmonsAI marked this pull request as ready for review October 29, 2026 06:13
@MikeSimmonsAI
MikeSimmonsAI merged commit 14259aa into main Oct 29, 2026
4 checks passed

Copy link
Copy Markdown
Owner Author

This branch was successfully deployed

1 active deployment
Preview — 485621c4 Deployed Oct 29, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

EvoSys Pro login — implement secure Google Sign-In for existing accounts

2 participants