bug: event.locals.accessToken always null — secureCookie mismatch in getToken() #20
Labels
No labels
domain:backend
domain:devops
domain:frontend
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
forgejo_admin/westside-app#20
Loading…
Add table
Add a link
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?
Lineage
plan-2026-03-08-tryout-prep→ Phase 10b (Frontend — Admin draft board + coach filtered roster)Follow-up from Issue #18. PR #19 correctly passes the token, but the token itself is always null.
Repo
forgejo_admin/westside-appUser Story
As an admin or coach
I want my Keycloak access token available server-side
So that server-side API calls to basketball-api team endpoints succeed with authentication
Context
PR #19 fixed the team page load functions to pass
event.locals.accessTokento basketball-api fetch calls. However, Playwright revalidation shows the team endpoints still return 401 "Not authenticated" — the token is null.Root cause analysis of
src/hooks.server.js:The site runs on HTTPS (Tailscale funnel). Auth.js sets cookies with the
__Secure-prefix on HTTPS connections. ButgetToken()is called withsecureCookie: false, which tells it to look for the NON-secure cookie name (authjs.session-token). It never finds the cookie, sotokenis null, andevent.locals.accessTokenis always null.This was never caught because no existing page depended on the access token:
/adminuses public/api/roster/{tenant}(no auth needed)/admin/usersgets its own Keycloak admin token viaKEYCLOAK_ADMIN_PASSWORD/coachcallsfetchMyTeam(accessToken)but silently falls back to full roster on failure/playermatches by email from the public rosterThe team pages (PR #17, Issue #16) are the first routes that REQUIRE
event.locals.accessTokento be non-null.Secondary concern: Even if the cookie lookup is fixed, the Keycloak access token stored at sign-in time will expire (default 5 minutes). Auth.js does not auto-refresh tokens. A token rotation callback may be needed for long-lived sessions.
File Targets
Files the agent should modify:
src/hooks.server.js— fixgetToken()call. Either removesecureCookie: false(let it auto-detect), or setsecureCookie: trueto match HTTPS. Also verify the cookie name matches what Auth.js actually sets. Consider adding console logging temporarily to debug the token value.Files the agent should investigate:
src/auth.js— check ifjwtcallback correctly persistsaccessTokenon subsequent calls (not just initial sign-in). May need token rotation logic for expired Keycloak tokens.browser_evaluateor cookie inspection)Files the agent should NOT touch:
src/lib/server/api.js— the token passing from PR #19 is correctsrc/routes/admin/teams/+page.server.js— the token wiring from PR #19 is correctAcceptance Criteria
event.locals.accessTokencontains a valid Keycloak JWT (not null) after sign-in/admin/teamsloads team data (no more "Basketball API not reachable")/teamsloads team data for authenticated usersTest Expectations
/admin/teams→ team data loadsgetToken()expectsConstraints
AUTH_TRUST_HOST=true)getToken()API and cookie name conventionsChecklist
Related
project-westside-basketball— blocks team management UI (Phase 10b)