Skip to content

fix(portal): /portal/login forwards an already-authenticated user (bd-2569) - #200

Merged
hatafatif merged 1 commit into
developfrom
bd-2569-01815
Aug 13, 2026
Merged

fix(portal): /portal/login forwards an already-authenticated user (bd-2569)#200
hatafatif merged 1 commit into
developfrom
bd-2569-01815

Conversation

@hatafatif

Copy link
Copy Markdown
Collaborator

Teachers reported the app "logging out" whenever it was swiped from the task manager and reopened.

The session was never at fault

The cookie is persistent (7-day Max-Age, Secure, httpOnly) and MainActivity.onPause() flushes the WebView cookie jar to disk, so it survives the process kill.

What broke is where the app lands. The OTA build boots straight to /portal/login — that path is compiled into the APK — which bypasses / (PortalRoot), the one route that reads the session and forwards an authenticated user onward. A valid session met a login form on every cold start, and the only reasonable reading of that is "it logged me out".

PortalRoot.tsx already documents this exact failure for the / case. This gives PortalLogin the same treatment, so the page is correct however the user reaches it.

Why not just change the OTA url?

  • It's compiled into the APK → needs a Play release (the one-way door)
  • It depends on server redirect behaviour, which already differs between staging and prod
  • It leaves the hole open for anyone reaching /portal/login by any other route

This ships over OTA — next app launch, no Play release.

Behaviour

authenticated teacher -> /portal/dashboard
authenticated leader  -> /portal/leader   (PortalRoot parity)
session still loading -> render nothing (no form flash)
genuinely no session  -> the form, unchanged

Red-first: 4 failing → 15 files / 81 tests green. The 5th test (ordinary login) passed throughout and still does. Build verified — that's the check for the sessionLoading alias colliding with the existing submit-button loading state.

Closes: bd-2569

🤖 Generated with Claude Code

…-2569)

Teachers reported the app "logging out" whenever it was swiped from the
task manager and reopened. The session was never at fault: the cookie is
persistent (7-day Max-Age, Secure, httpOnly) and MainActivity.onPause()
flushes the WebView cookie jar to disk, so it survives the process kill.

What broke is WHERE the app lands. The OTA build boots straight to
/portal/login — that path is compiled into the APK — which bypasses "/"
(PortalRoot), the one route that reads the session and forwards an
authenticated user onward. So a valid session met a login form on every
cold start, and the only reasonable reading of that is "it logged me out".

PortalRoot already documents this exact failure for the "/" case. This
gives PortalLogin the same treatment, so the page is correct no matter how
the user reaches it.

Fixing the OTA url instead would need a Play release (it ships inside the
APK) and would leave the hole open for anyone arriving at /portal/login by
any other route. This ships over OTA — next app launch, no Play release.

  authenticated teacher -> /portal/dashboard
  authenticated leader  -> /portal/leader   (PortalRoot parity)
  session still loading -> render nothing (no form flash)
  genuinely no session  -> the form, unchanged

`sessionLoading` is aliased deliberately: the component already had a
`loading` state for the submit button, and the two mean different things.

Tests red-first: 4 failing before (the 5th, ordinary login, passed
throughout and still does), 15 files / 81 tests green after. Build clean —
which is the check that would have caught the loading-rename colliding
with the submit state.
@hatafatif
hatafatif merged commit fd06f7f into develop Aug 13, 2026
1 of 2 checks passed
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.

1 participant