Bug report
A returning Google Calendar-connected user can complete Google OAuth reauthorization, land back in Compass, and still remain on a temporary account. The app then shows the generic toast Google authorization could not be completed. Please try again. even though the Google consent flow was successful.
This blocks returning users whose Compass session is no longer active from getting back to their existing account through the Google Calendar reauth path.
Where it happened
Route/screen: /auth/google/callback returning to the calendar day view.
Account state from reporter: returning user successfully reauthenticates with Google Calendar auth, but after redirect the sidebar still shows Temporary account / Sign up.
Screenshot evidence: the app is on the day view, the planner sidebar says Temporary account, and the bottom-left toast says Google authorization could not be completed. Please try again.
Workflow
- Start from a returning user/browser that previously used Google Calendar auth but is currently shown as a temporary account.
- Initiate Google Calendar reauthentication/authorization.
- Complete Google OAuth successfully and return to Compass through
/auth/google/callback.
- The app navigates back to the calendar but shows the generic Google authorization failure toast and still treats the user as temporary.
Expected outcome
A successful returning-user Google authorization should restore the user's existing Compass session/account, refresh user metadata, and leave the sidebar showing the authenticated user rather than Temporary account.
If the Compass session is expired and Google OAuth cannot restore it through the current flow, the app should route the user through the proper sign-in/session recovery path instead of attempting the authenticated Google connect endpoint and showing a generic authorization failure.
Screenshot
[screenshot]
Diagnosis
Reproduction status: not locally reproduced because this requires a live Google OAuth/backend setup and the reporter's returning-user/session-expired account state. Diagnosis confidence is medium-high from code inspection and the supplied screenshot.
Strongest evidence:
packages/web/src/views/GoogleAuthCallback/GoogleAuthCallback.tsx calls completeGoogleAuthorization(), shows showErrorToast(result.message) on failure, then navigates to the saved return path.
packages/web/src/auth/google/authorization/complete-google-authorization.ts chooses behavior only from the saved sessionStorage intent. For connectCalendar, it calls authApi.connectGoogle(payload), then refreshes metadata. Any unparsed error becomes the generic Google authorization could not be completed. Please try again. message.
packages/web/src/common/apis/auth.api.ts maps connectGoogle() to POST /api/auth/google/connect.
packages/backend/src/auth/auth.routes.config.ts protects /api/auth/google/connect with verifySession(). If the returning user's Compass session is absent/expired, this endpoint cannot complete even after Google OAuth succeeds.
packages/web/src/components/PlannerSidebar/PlannerAccountSummary/PlannerAccountSummary.tsx renders Temporary account when useUser() has no email, matching the screenshot after the callback failure.
- Acceptance docs say returning/authenticated connect-later flows should keep the existing Compass session and use
POST /api/auth/google/connect; they do not cover a session-expired returning user who is already temporary at callback time.
Related issue: #1479 describes the broader expired-session/Google-connected-user recovery problem. This report captures the concrete OAuth callback failure and temporary-account symptom.
Likely fix
Start with the Google authorization intent/callback boundary:
- In
useStartGoogleAuthorization / completeGoogleAuthorization, distinguish connectCalendar from returning-user sign-in/reauth when there is no active Compass session.
- Before calling
POST /api/auth/google/connect, verify the Compass session is active or make the backend return a typed/session-expired error that the callback can handle intentionally.
- For expired/no-session returning users, complete Google auth through the sign-in/session restoration path (
loginOrSignup / SuperTokens flow) or redirect to the auth modal with a specific message, rather than treating it as an in-session Google Calendar connect.
- Preserve the existing in-session connect behavior for password-authenticated users connecting Google for the first time, including email mismatch and already-connected safeguards in
connectGoogleToCurrentUser().
Likely affected files/modules:
packages/web/src/auth/google/authorization/complete-google-authorization.ts
packages/web/src/auth/google/authorization/useStartGoogleAuthorization.ts
packages/web/src/views/GoogleAuthCallback/GoogleAuthCallback.tsx
packages/web/src/common/apis/auth.api.ts
packages/backend/src/auth/auth.routes.config.ts
packages/backend/src/auth/controllers/auth.controller.ts
packages/backend/src/auth/services/google/google.auth.service.ts
Verification
Shortest practical verification:
- Use a Google-connected returning user whose Compass session is expired or otherwise absent, so the sidebar shows
Temporary account.
- Start Google Calendar reauth and complete OAuth successfully.
- Confirm the callback does not show the generic Google authorization failure toast.
- Confirm the sidebar shows the restored authenticated user and Google metadata/import state refreshes.
- Also verify the existing authenticated connect-later path still calls
POST /api/auth/google/connect and keeps pre-existing Compass data.
Focused automated coverage to add:
- Web unit test for
completeGoogleAuthorization() covering a connectCalendar intent when authApi.connectGoogle() returns/throws an unauthorized session error, asserting the user sees a specific recovery behavior instead of the generic Google authorization failure.
- Existing
connectCalendar success test should continue asserting metadata refresh and event refetch.
- Backend/controller test can assert
/api/auth/google/connect remains session-protected and returns a typed response/error that the callback can distinguish.
Bug report
A returning Google Calendar-connected user can complete Google OAuth reauthorization, land back in Compass, and still remain on a temporary account. The app then shows the generic toast
Google authorization could not be completed. Please try again.even though the Google consent flow was successful.This blocks returning users whose Compass session is no longer active from getting back to their existing account through the Google Calendar reauth path.
Where it happened
Route/screen:
/auth/google/callbackreturning to the calendar day view.Account state from reporter: returning user successfully reauthenticates with Google Calendar auth, but after redirect the sidebar still shows
Temporary account/Sign up.Screenshot evidence: the app is on the day view, the planner sidebar says
Temporary account, and the bottom-left toast saysGoogle authorization could not be completed. Please try again.Workflow
/auth/google/callback.Expected outcome
A successful returning-user Google authorization should restore the user's existing Compass session/account, refresh user metadata, and leave the sidebar showing the authenticated user rather than
Temporary account.If the Compass session is expired and Google OAuth cannot restore it through the current flow, the app should route the user through the proper sign-in/session recovery path instead of attempting the authenticated Google connect endpoint and showing a generic authorization failure.
Screenshot
[screenshot]
Diagnosis
Reproduction status: not locally reproduced because this requires a live Google OAuth/backend setup and the reporter's returning-user/session-expired account state. Diagnosis confidence is medium-high from code inspection and the supplied screenshot.
Strongest evidence:
packages/web/src/views/GoogleAuthCallback/GoogleAuthCallback.tsxcallscompleteGoogleAuthorization(), showsshowErrorToast(result.message)on failure, then navigates to the saved return path.packages/web/src/auth/google/authorization/complete-google-authorization.tschooses behavior only from the savedsessionStorageintent. ForconnectCalendar, it callsauthApi.connectGoogle(payload), then refreshes metadata. Any unparsed error becomes the genericGoogle authorization could not be completed. Please try again.message.packages/web/src/common/apis/auth.api.tsmapsconnectGoogle()toPOST /api/auth/google/connect.packages/backend/src/auth/auth.routes.config.tsprotects/api/auth/google/connectwithverifySession(). If the returning user's Compass session is absent/expired, this endpoint cannot complete even after Google OAuth succeeds.packages/web/src/components/PlannerSidebar/PlannerAccountSummary/PlannerAccountSummary.tsxrendersTemporary accountwhenuseUser()has no email, matching the screenshot after the callback failure.POST /api/auth/google/connect; they do not cover a session-expired returning user who is already temporary at callback time.Related issue: #1479 describes the broader expired-session/Google-connected-user recovery problem. This report captures the concrete OAuth callback failure and temporary-account symptom.
Likely fix
Start with the Google authorization intent/callback boundary:
useStartGoogleAuthorization/completeGoogleAuthorization, distinguishconnectCalendarfrom returning-user sign-in/reauth when there is no active Compass session.POST /api/auth/google/connect, verify the Compass session is active or make the backend return a typed/session-expired error that the callback can handle intentionally.loginOrSignup/ SuperTokens flow) or redirect to the auth modal with a specific message, rather than treating it as an in-session Google Calendar connect.connectGoogleToCurrentUser().Likely affected files/modules:
packages/web/src/auth/google/authorization/complete-google-authorization.tspackages/web/src/auth/google/authorization/useStartGoogleAuthorization.tspackages/web/src/views/GoogleAuthCallback/GoogleAuthCallback.tsxpackages/web/src/common/apis/auth.api.tspackages/backend/src/auth/auth.routes.config.tspackages/backend/src/auth/controllers/auth.controller.tspackages/backend/src/auth/services/google/google.auth.service.tsVerification
Shortest practical verification:
Temporary account.POST /api/auth/google/connectand keeps pre-existing Compass data.Focused automated coverage to add:
completeGoogleAuthorization()covering aconnectCalendarintent whenauthApi.connectGoogle()returns/throws an unauthorized session error, asserting the user sees a specific recovery behavior instead of the generic Google authorization failure.connectCalendarsuccess test should continue asserting metadata refresh and event refetch./api/auth/google/connectremains session-protected and returns a typed response/error that the callback can distinguish.