Tech debt: callApi's blanket 403 handler conflates "session expired" with "no access to this resource" #154
Labels
No labels
priority/could
priority/must
priority/should
priority/wont
status/blocked
status/claimed
status/done-migrated
type/bug
type/feature
type/infra
type/tech-debt
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
robert/todo#154
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Story: distinguish session-expiry 403s from resource-authorization 403s in
callApiAs a user whose session is still valid,
I want to never get force-logged-out just because one specific request 403'd for an
authorization reason unrelated to my session,
so that an unrelated access error never looks like "you got logged out".
Background
Found during #151 ("deleted list on direct URL shows login screen instead of redirect").
ReactUi/src/api/api.tsx'scallApiforce-clearsuserId(logs the whole app out) on any403 response that isn't marked
skipErrorToast:The backend returns 403 for two genuinely different reasons that this code treats identically:
AuthorizeTodoListAccessQueryHandler(and its Shopping/Pantry/MasterPacking equivalents)throwing
UnauthorizedAccessExceptionbecause the requested resource doesn't exist or theuser has no access to it - e.g. a deleted/foreign list id - which also maps to 403 via
ExceptionHandler.cs.#151 fixed the direct-navigation symptom with a client-side guard in
Application.tsx(redirectto the overview before any list-scoped call can fire for an id not in the loaded list), but that
guard only covers the one route-level entry point it was added to. It does not fix the
underlying conflation, so the same force-logout can still be reproduced by:
CsvExportDialog.tsx/InvitePanel.tsxpattern of callingcallApiwith a raw list id and noexistence check) that fires before #151's guard has resolved.
at the exact moment a list is deleted live - the dialog's in-flight/queued call still resolves
against the now-deleted resource and 403s.
Acceptance criteria:
distinct error code/body field, or a different status code such as 404 for "resource
doesn't exist/no access" vs 401/403 reserved for "no valid session").
callApionly force-clearsuserIdfor the genuine session-expiry case.list id) does not clear
userIdor show the login screen while the session is otherwisevalid.
Out of scope for this story:
this fix.
frontend uses to detect it.
Resolved as part of #151 itself, not as a separate follow-up: commit
b6a6d55807(a concurrent session working the same issue) already did exactly what this issue asked for - swapped the "not logged in" branch of all 15 Authorize*QueryHandler.cs files from UnauthorizedAccessException (403) to AuthenticationException (401), and simplified callApi's frontend handling to a plain 401 check. This issue was drafted before that commit was discovered (two sessions worked #151 concurrently without realizing it). Closing as a duplicate-in-effect rather than leaving it open.