Skip to main content
This lesson summarizes a comprehensive authentication security review of an Express.js login demo (Postgres + JWT). The review was guided by a structured audit prompt that enumerates common pitfalls, remediation guidance, and test recommendations. Below you’ll find the audit prompt used to drive the analysis, an executive summary, prioritized findings, concrete remediation snippets, recommended tests, and operational next steps.
Note: the audit focused on authentication hardening patterns relevant to most Express-based demos: password hashing, JWT handling, refresh-token rotation, session invalidation, brute-force protection, input validation, and secure cookie/CSRF practices.

Structured audit prompt (representative)

The audit prompt above guided automated analysis and subsequent manual review. The rest of this article summarizes key findings, rationale, and minimal remediation snippets produced during the review.
This article focuses on actionable fixes for Express.js authentication flows: secure password storage, robust JWT handling, refresh-token rotation, brute-force defenses, safe cookie/CSRF configuration, and input validation. Use the snippets below as minimal drop-in improvements and adapt them to your project structure.

Executive summary (high level)

  • Primary focus: authentication flow hardening for an Express demo with PostgreSQL and JWTs.
  • Main risks found (representative):
    • Hard-coded or weak JWT secret — Critical
    • Plaintext password storage or missing hashing — Critical
    • Missing brute-force/rate-limiting on login/reset — High
    • Long-lived access tokens / no refresh-token rotation — High
    • Insufficient input validation / potential account enumeration — Medium-High
  • Recommended priorities:
    1. Replace weak/hard-coded secrets; use environment or secret manager and rotate keys.
    2. Ensure passwords are hashed (bcrypt with async salts ≥12) before persistence.
    3. Implement RT rotation + reuse detection, shorten access TTL.
    4. Add rate-limiting and consistent, generic error messaging to prevent enumeration.
    5. Harden cookies, CSRF protections, and input validation.

Key checks — what to inspect and why

Relevant references:

Example findings (representative)

  • Weak JWT Secret Management
    • Severity: Critical | CWE-798 (Hard-coded Credentials)
    • Evidence: .env included JWT_SECRET=your_jwt_secret_key_here.
    • Remediation: Replace with a cryptographically strong secret stored in environment or secret manager; rotate keys and use asymmetric keys (RS256/ES256) if feasible.
  • No password hashing on registration
    • Severity: Critical
    • Evidence: Registration flow persisted plaintext password.
    • Remediation: Use bcrypt.hash() (async) with salt rounds ≥ 12 before persisting.
  • Missing brute force protection on login
    • Severity: High
    • Evidence: No rate limiting or lockouts on login/reset endpoints.
    • Remediation: Add express-rate-limit with Redis backing; block after threshold and present generic error messages.
  • Excessive token lifetimes / no RT rotation
    • Severity: High
    • Evidence: Long-lived access tokens; refresh tokens not rotated.
    • Remediation: Shorten access TTL, implement RT rotation with reuse detection and per-device tracking.

Concrete remediation snippets

Place these snippets into appropriate files (e.g., routes/auth.js, middleware/, or a config file). They are minimal and intended to be adapted to your project style and error handling.

1) Register with bcrypt hashing (async)

2) Rate limit login attempts (express-rate-limit + Redis)

3) HTTPS redirect middleware (enforce TLS in production)

4) Generic server-side error logging and client response

5) Strong JWT verification (explicit algorithms and claim checks)

6) Password validation rules (express-validator)

Immediate actions (next 48 hours): replace weak/hard-coded JWT secrets, ensure passwords are hashed before persistence, add login rate-limiting, shorten access token TTL, and implement refresh-token rotation. These address the highest-impact findings.

Test recommendations (examples)

  • Refresh token reuse detection (pseudo-test)
  • Brute force protection test
  • Password reset flow test
    • Create a short-TTL reset token, assert it’s hashed at rest, use once, and verify it’s invalid afterwards.

Report generation & operational checklist

The audit output should be committed as a structured markdown report (example filename: audits/AUTHENTICATION_FLOW_REPORT.md) and include:
  • Executive summary and risk score
  • Critical & high severity findings with CWE references
  • Evidence (file/line references where available)
  • Minimal remediation snippets and suggested timelines:
    • Immediate (48 hours): replace JWT secret with strong key; add bcrypt hashing on registration and updates; add brute-force protection; shorten access token TTL; add refresh-token rotation.
    • Within 1 week: implement session invalidation on password change; comprehensive input validation; JWT middleware and claim verification.
    • Within 1 month: logging redaction; monitoring/alerting for RT reuse; penetration testing and key rotation procedures.
  • Tests to validate fixes (RT reuse, invalidation after password change, bruteforce detection).
  • Checklist diff showing before/after and file-level changes.
A VS Code window displaying an "Authentication Security Audit Report" Markdown file with sections like "Compliance Impact" and "Next Steps" listing PCI DSS, OWASP, and SOC issues. The project explorer, file tree, terminal and minimap are visible in a dark-themed editor.

Where to find prompts and next steps

All prompts used for these reviews were kept in the repository for reuse and iteration. Recommended operational next steps:
  • Replace placeholder secrets with production-grade secrets (secrets manager or KMS).
  • Implement the code fixes above and run the tests suggested.
  • Add monitoring and alerting for refresh-token reuse and anomalous auth patterns.
  • Schedule a secondary audit after fixes are merged and tests pass.
A desktop screenshot showing a browser window open to a GitHub repository called "Claude-Code-Reviewing-Prompts" with a list of Markdown files and commit info. A code editor with project files is visible in the background.

Final notes

  • Not every check applies to every application. Mark items “Unable to Verify” where required context or files are missing.
  • Prioritize concrete, minimal fixes that can be validated with tests and rolled out progressively.
  • Preserve the practice of never exposing secrets or tokens in logs and enable key rotation and monitoring.

Watch Video