feat: add JWT auth, usage/quota tracking, and frontend auth flow (issue #4)#21
feat: add JWT auth, usage/quota tracking, and frontend auth flow (issue #4)#21zjy4fun wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ce8dff3b04
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const legacyUserId = (req.body?.user_id ?? req.query?.user_id) as string | undefined; | ||
| if (legacyUserId) { | ||
| const user = getUserById(db, legacyUserId); | ||
| if (!user || !user.active) { |
There was a problem hiding this comment.
Remove unauthenticated user_id fallback in auth middleware
The requireAuth middleware accepts req.body.user_id/req.query.user_id when no Bearer token is present and treats that as authenticated identity. This reopens all protected routes (/chat, /chat/stream, /conversations, /usage) to unauthenticated impersonation by anyone who can guess a valid user id (the seeded ids are predictable), which defeats the JWT gate introduced in this change.
Useful? React with 👍 / 👎.
| } | ||
|
|
||
| function verifyToken(rawToken: string, secret: string): JWTPayload { | ||
| const parsed = jwt.verify(rawToken, secret, { issuer: 'llm-chat' }) as JWTPayload; |
There was a problem hiding this comment.
Normalize JWT verification failures to 401
verifyToken directly propagates errors from jwt.verify, but those errors do not carry status/code. In this app there is no custom error-mapping middleware, so invalid or expired tokens can surface as generic 500 responses instead of an authentication failure, which breaks client refresh/re-login flow and misclassifies auth errors as server faults.
Useful? React with 👍 / 👎.
| const user = createUser(db, { | ||
| email: input.email, | ||
| passwordHash, | ||
| plan: input.plan |
There was a problem hiding this comment.
Reject client-controlled plan on registration
The registration path forwards input.plan from the public request body straight into createUser. That lets any caller self-register as pro and immediately receive higher quota/entitlements without any privileged check, which is a direct authorization and billing-control bypass.
Useful? React with 👍 / 👎.
Motivation
Description
server/src/core/auth.tswithissueAuthTokens,authenticateAccessToken,rotateRefreshToken, password hashing (bcryptjs), andrequireAuthmiddleware that includes a legacyuser_idfallback for compatibility.server/src/routes/auth.ts(/auth/register,/auth/login,/auth/refresh) and a/usage/meendpoint inserver/src/routes/usage.ts.server/src/core/db.tsto SQLite tables forusers,refresh_tokens, andusage_events, plus helper functionsrecordUsage,getUsageSummary, andassertDailyQuotaAvailable; seeded demo users for development.req.auth, check daily quotas, apply rate limits, and record token usage (recordUsage) instead of the prior mock balance flow; adjusted types and request schemas accordingly.web/src/api.tsandweb/src/App.tsxto support in-memory access/refresh tokens, automaticAuthorizationheader injection with a 401->refresh retry, newlogin/registerflows, usage display, and updated API calls (no client-sideuser_idfields).server/src/types/express.d.ts, updatedweb/src/types.ts, and included new runtime dependencies (bcryptjs,jsonwebtoken) and dev types.Testing
pnpm --filter llm-chat-server testand the server test suite passed (26 passedafter changes).pnpm --filter llm-chat-server buildandpnpm --filter llm-chat-web build, both completed successfully.pnpm --filter llm-chat-web testwhich currently fail because the test fixtures expect the previous unauthenticated conversation UI; the app now requires login before the full conversation workspace, so those assertions need to be updated (web tests: failing).Codex Task