Complete signup path failure with zero error feedback. OAuth flow completes on Google's side, but Qoruz's backend rejects the request silently. Every user who clicks "Sign up with Google" hits a dead end.
Google OAuth signup on Qoruz is completely non-functional. The OAuth flow completes successfully on Google's side (consent granted, popup closes), but Qoruz's frontend sends the resulting JWT to /api/register without the required gReCaptchaToken field. The backend returns a 422 Unprocessable Entity, the frontend silently swallows the error, and the user sees no feedback whatsoever. The page simply stays on the signup form as if nothing happened.
This is not a client-side or browser-specific issue. It is a server-side validation misconfiguration combined with a frontend error-handling gap.
100% of users who attempt Google OAuth signup will fail silently. No error is shown, no lead data is captured, and no recovery path is offered.
The bug was reproduced across every reasonable combination of browser mode, Google account type, OAuth method, and session timing. The failure is deterministic and account-agnostic.
| Variable | Values Tested |
|---|---|
| Browser | Google Chrome (Mac) |
| Modes | Normal browsing, Incognito |
| Google Accounts | knewsiq@gmail.com (personal Gmail), kulki@knewsiq.com (Google Workspace) |
| OAuth Methods | "Sign up with Google" button, FedCM / One Tap ("Sign in as Ankur") |
| Sessions | Two separate sessions, hours apart (12:11 AM and 4:29 AM IST) |
Identical failure in every combination. The result is 100% reproducible.
https://qoruz.com (landing page).https://app.qoruz.com/signup in a new tab.On subsequent visits, Google's FedCM surfaces a "Sign in as [Name]" pill at the bottom of the form (confirming prior OAuth authorization was stored). Clicking this triggers the same flow with the same silent failure, except the "Sign Up" button briefly shows a spinner before reverting.
The POST /api/register request sent by the frontend after Google OAuth completion contains the following payload:
{
"oauthResponse": "<Google JWT>",
"is_google_login": true,
"utm_source": "SEO",
"utm_medium": "organic search",
"lead_source": "Inbound - SEO",
"lead_page": "signup"
}
The backend returns:
{
"ok": false,
"error": "validation_failed",
"validation_errors": {
"gReCaptchaToken": [
"The g re captcha token field is required."
]
},
"stuff": "The given data was invalid."
}
The backend requires gReCaptchaToken as a mandatory field on every /api/register call. The manual signup form includes a reCAPTCHA widget that generates and attaches this token. The Google OAuth signup path bypasses the reCAPTCHA widget entirely and never includes the token in its payload. The backend does not differentiate between OAuth and manual signups in its validation rules.
When the /api/register call returns a 422, the frontend does not surface any error to the user. No modal, no toast, no inline error message, no console-visible user-facing error. The user is left staring at an unchanged signup form with no indication that something went wrong. The only evidence is in the browser's Network tab (the failed register request) and Console (a POST 422 error line buried under hundreds of carousel warnings).
The browser console logs the following during the OAuth callback:
Cross-Origin-Opener-Policy policy would block the window.postMessage call.
This indicates that the Cross-Origin-Opener-Policy headers on app.qoruz.com are interfering with the communication channel between the Google OAuth popup and the parent page. While the OAuth token does eventually reach the parent page (evidenced by the /api/register call being made), this COOP misconfiguration could cause intermittent failures or race conditions in the popup-to-parent handoff.
[GSI_LOGGER]: google.accounts.id.initialize() is called multiple times.
Google's Sign-In library is being initialized more than once, likely triggered by the testimonial carousel's continuous re-rendering (the carousel fires setState in an infinite loop due to a missing showThumbs={false} prop). This could cause unpredictable behavior in the OAuth callback registration.
| Attempt | Domain Type | Mode | Result | reCAPTCHA Token? | HTTP | |
|---|---|---|---|---|---|---|
| 1 | knewsiq@gmail.com |
Public (Gmail) | Normal | Silent failure | No | 422 |
| 2 | knewsiq@gmail.com |
Public (Gmail) | Normal (FedCM) | Spinner → silent failure | No | 422 |
| 3 | knewsiq@gmail.com |
Public (Gmail) | Incognito | Silent failure | No | 422 |
| 4 | kulki@knewsiq.com |
Workspace | Incognito | Silent failure | No | 422 |
Decoded JWT payloads confirm correct iss, aud, email, email_verified: true, valid exp timestamps, and proper hd (hosted domain) claims for Workspace accounts.
Using the same session and browser, the manual form (Name + Phone + Business Email + Sign Up button) successfully registers and progresses to email verification. This confirms the reCAPTCHA widget is present and functional on the manual path and absent on the OAuth path.
The timing profile is consistent across all attempts, confirming the server processes and rejects the request deterministically:
| Phase | Duration |
|---|---|
| Queueing | ~250–320 ms |
| DNS Lookup | ~14–18 μs |
| Initial Connection | ~127–228 ms |
| SSL | ~64–130 ms |
| Request Sent | ~0.1 ms |
| Waiting for Server Response | ~164–168 ms |
| Content Download | ~2–4 ms |
| Total | ~620–650 ms |
The server responds in under 170ms with the 422, meaning it hits the validation layer immediately and never reaches account creation logic.
Even if the reCAPTCHA issue were fixed, Google OAuth signup using public email domains (Gmail, Yahoo, etc.) would hit a second wall. Qoruz requires a "work email" for registration. The manual form surfaces a clear modal for this restriction. The Google OAuth path has no equivalent handling. It would receive the Gmail address from the JWT, attempt to register, and presumably fail at the email domain validation stage (which currently never fires because the reCAPTCHA validation fails first).
The testimonial carousel on the signup page fires renderThumbs errors in an infinite loop. Each cycle triggers a setState call, causing continuous re-renders. The console accumulates hundreds of warnings within seconds. The fix: set showThumbs={false} on the Carousel component.
The page loads an asset over HTTP from an HTTPS page (http://terareach.s3.ap-southeast-1.amazonaws.com/...). Chrome auto-upgrades this, but it indicates the S3 bucket references haven't been updated to use HTTPS URLs.
Option A (Backend, recommended): Make gReCaptchaToken conditionally required. When is_google_login is true and a valid Google JWT is present, skip the reCAPTCHA validation. The OAuth flow itself provides equivalent bot-protection assurance.
Option B (Frontend): Execute an invisible reCAPTCHA (grecaptcha.execute()) during the OAuth callback, before sending the /api/register request. This requires no backend changes but adds latency.
The frontend must handle non-2xx responses from /api/register and display meaningful feedback. At minimum, show a toast or modal with a generic "Something went wrong" message. Ideally, parse the error response and display actionable guidance.
For Google OAuth signups where the returned email is a public domain, either prompt the user for a work email after OAuth completes (pre-filling their name from the JWT) or display the same "Work email required" modal shown on the manual form path.
Review the Cross-Origin-Opener-Policy response headers. The current policy blocks window.postMessage calls from the Google OAuth popup. Adjust to same-origin-allow-popups to permit the OAuth callback communication.
Ensure google.accounts.id.initialize() is called exactly once, outside of any component render cycle.
Add showThumbs={false} to the react-responsive-carousel Carousel component on the signup page, or provide actual image elements for the thumbnail renderer.
Replace http://terareach.s3.ap-southeast-1.amazonaws.com/... references with https:// equivalents to eliminate mixed content warnings.
Both JWTs are correctly signed, contain valid expiry timestamps, and match Qoruz's registered OAuth client ID. The issue is entirely on Qoruz's side.
| Claim | Value |
|---|---|
iss | https://accounts.google.com |
email | knewsiq@gmail.com |
email_verified | true |
name | Ankur |
given_name | Ankur |
aud | 438643001379-bgclgoktqqg67shp9f867mts4o3lgo6m.apps.googleusercontent.com |
| Claim | Value |
|---|---|
iss | https://accounts.google.com |
hd | knewsiq.com |
email | kulki@knewsiq.com |
email_verified | true |
name | Ankur Kulkarni |
given_name | Ankur |
family_name | Kulkarni |
aud | 438643001379-bgclgoktqqg67shp9f867mts4o3lgo6m.apps.googleusercontent.com |