POST /auth/refresh drops the role claim, breaking role-gated endpoints like POST /post after token refresh
Nobody has claimed this yet.
Assessment
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Newbie friendliness
- 74/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- node.js, typescript
- Domain
- api, authentication, backend
Research direction
Start in src/server/routes/auth.ts and src/server/routes/post.routes.ts, then inspect src/server/plugins/jwt.ts and grep for other request.user.role reads. Trace the refresh-token flow and the role checks on POST /post and POST /post/:id/reply. Done means role-gated requests continue to work after token refresh and all equivalent role reads are covered.
Written by the indexing model from the issue text.
Description
Bug
Coordinators (and agents) are hitting 403 Only agents and coordinators can create posts. on POST /post in production, even though their account role is correct in the DB.
Repro (from user report, prod):
POST https://app.need4deed.org/api/post→403 Forbidden- Response body:
Only agents and coordinators can create posts. - Confirmed via browser network tab + console on
app.need4deed.org/de/dashboard/posts.
Root cause
src/server/routes/auth.ts:
- Login (line 85) signs the access token with the full payload including role:
const userPayload = { id: user.id, email: user.email, role: user.role }; POST /auth/refresh(line 196) mints a new access token with role omitted entirely:const userPayload = { id: user.id, email: user.email };
Access tokens are short-lived (15 min per CLAUDE.md), so POST /auth/refresh fires automatically throughout any normal session. Once it fires once, every subsequent access token for that session has no role claim.
src/server/routes/post.routes.ts's POST /post and POST /post/:id/reply handlers read the role straight off the raw JWT payload:
const { role } = request.user;
if (role !== UserRole.AGENT && role !== UserRole.COORDINATOR) {
throw new UnauthorizedError("Only agents and coordinators can create posts.");
}
With role now undefined post-refresh, this check fails for every role, not just coordinators — it just happens to be most visible for the roles that are supposed to be allowed to post.
Note the same handler pulls personId from request.authUser?.personId (the DB-authoritative user object the JWT plugin loads fresh on every request — see src/server/plugins/jwt.ts's own comment: "Expose the already-loaded user (carries personId + DB-authoritative role) for downstream hooks") rather than from request.user. So the fix belongs at the call site, not necessarily in the token itself: use request.authUser.role (already loaded, already correct) instead of request.user.role.
Suggested fix
Either (or both, in order of increasing scope):
- In
post.routes.ts(and grep for otherrequest.user.rolereads gated the same way), switch torequest.authUser.role— it's already fetched from the DB on every authenticated request and is never stale. - Fix
POST /auth/refreshto includerolein the reissued access token's payload, sorequest.user.roleisn't silently wrong for any other code that may rely on it.
Scope check
Worth a quick grep across the codebase for other handlers reading request.user.role (as opposed to request.authUser.role) — those would have the identical latent bug, just less visible than posting.
- Dominant language
- TypeScript
- Stars
- 3
- Forks
- 12
- Avg merge
- 15h 57m
- Merged PRs (30d)
- 58
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from need4deed-org/be
-
enhancement Help out
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
need4deed-org/be#1016 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
need4deed-org/be#975 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
need4deed-org/be#908 ·
-
need4deed-org/be#1023 · 1 assignee ·
-
Difficulty 4/5 3-5 days Newbie friendliness 70/100
need4deed-org/be#1019 ·
All issues in need4deed-org/be
Similar issues
-
clawsweeper:fix-shape-clear clawsweeper:queueable-fix clawsweeper:source-repro impact:ux-friction issue-rating: 🦞 diamond lobster no-stale P3
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Difficulty 1/5 Under an hour Newbie friendliness 76/100
-
code-quality refactoring
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
github/gh-aw-firewall#8816 ·
-
integration:quickjs org:external priority:backlog topic:code-interpreter topic:middleware type:feature
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
langchain-ai/deepagents#6450 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 88/100
vercel/react-tweet#225 ·