Skip to content

Harden Authentication and Account Security Policy - #139

Merged
3m1n3nc3 merged 7 commits into
learnault:mainfrom
Theophilus131:feat/harden-auth-security-77-78-issue-136
Aug 20, 2026
Merged

Harden Authentication and Account Security Policy#139
3m1n3nc3 merged 7 commits into
learnault:mainfrom
Theophilus131:feat/harden-auth-security-77-78-issue-136

Conversation

@Theophilus131

Copy link
Copy Markdown

#132
Summary

Hardens authentication and account security across the API — closes the Phase 1 roadmap issue by enforcing verification, account status, roles, password policy, JWT handling, key rotation, and rate limits consistently, all in one coherent set of changes.

The 7 commits, in plain terms
JWT config, centralized — one place (src/config/jwt.ts) now owns signing/verification: fixed algorithm (HS256), required issuer/audience, and support for rotating signing keys via a kid header. No more silent fallback secret — the app refuses to boot without a real JWT_SECRET outside tests.
Auth middleware fixed — tokens are verified through that new config, and authorize() now checks a user's current role and account status from the database instead of trusting whatever the JWT claims. This closed a real gap: someone demoted or deactivated could previously keep employer-route access until their old token expired.
Password policy — passwords must now be 8+ chars with upper/lower/number/symbol, enforced at the schema level. Bcrypt cost factor is configurable and can be raised over time without a mass reset.
Controllers cleaned up — both auth and account controllers dropped their old hardcoded fallback JWT secret, switched to the shared hashing/signing helpers, and now transparently re-hash a user's password on login if it was stored at a weaker cost than current config.
Rate limits + verified-email gates — /register and /reset-password previously had no rate limiting at all; now they do. Reward withdrawals and all employer routes now require a verified email, not just a valid login.
Policy doc — docs/AUTH_POLICY.md lays out, in table form, exactly which account statuses can access what, which operations need email verification, and the rate-limit rules — this is the "verification evidence" the issue asked for.
Tests — new coverage for JWT rotation/rejection, persisted-role authorization (including the stale-JWT-role case), and password policy, plus updates to existing tests.
Scope and honesty notes
Explicitly not included: refresh-token rotation (blocked by issue #130, not implemented anywhere yet), a PIN policy (no PIN feature exists in the codebase), and an unrelated pre-existing stub in user.controller.ts.
Verified-email requirements (reward withdrawal, employer routes) were a judgment call since no such policy existed before — flagged for reviewers to weigh in on.
All of this has since been build-and-test verified locally (you ran npm run build and npx vitest run clean after we fixed the two follow-up bugs — the 500-vs-401 JWT issue and the stale employer.routes.test.ts), so the PR is in a mergeable state.

@Theophilus131

Copy link
Copy Markdown
Author

close #132

@3m1n3nc3
3m1n3nc3 merged commit 00e1f01 into learnault:main Aug 20, 2026
1 check 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.

2 participants