Tuesday, October 7, 2025

🧠 How to Upgrade Your Spring Boot Login for Full OWASP Protection (XSS, CSRF, HttpOnly JWT)

 Modern web apps often use localStorage for JWTs — but that’s risky.

localStorage is accessible to JavaScript, so an XSS attack can easily steal your token.
The proper way: use HttpOnly cookies + CSRF tokens.



Here’s how to transform your existing /login endpoint securely without breaking Kafka, Redis caching, or rate limiting.


πŸͺœ Step-by-Step Migration Plan

Step 1: Switch from LocalStorage to HttpOnly Secure Cookie

  • Instead of returning the JWT in the response body, set it as an HttpOnly, Secure, SameSite=Strict (or Lax) cookie.

  • These cookies can’t be accessed by JavaScript — protecting against XSS.

  • No change is needed in your Kafka or Redis logic — they’ll continue working because you’re just changing how the token is delivered, not the backend authentication logic.

πŸ’‘ Kafka login notifications and Redis login limiters will remain unaffected, since they trigger before token issuance.


 


Step 2: Introduce a CSRF Token

  • When a user logs in, generate a CSRF token (a random UUID).

  • Store this token:

    • Option 1: in Redis (recommended if you already use Redis)

    • Option 2: in an SQL table (csrf_tokens)

  • Send this token as a non-HttpOnly cookie or via a header (so frontend can read it).

  • Frontend includes this token in every state-changing request header:

X-CSRF-TOKEN: <token>

πŸ›‘️ The backend will reject any POST/PUT/DELETE without a valid CSRF token that matches the user’s session or Redis entry.


Step 3: Secure Cookie Configuration

Update your application.properties:

server.servlet.session.cookie.http-only=true

server.servlet.session.cookie.secure=true

server.servlet.session.cookie.same-site=Strict

If your frontend and backend are on different domains:

server.servlet.session.cookie.domain=.yourdomain.com

Step 4: CORS Configuration (Critical)

When using cookies for auth:

  • You must enable credentials and disable wildcards (*).

Step 5: Frontend Adjustments

  • Remove localStorage usage for JWTs.

  • ✅ Use fetch or axios

  • Store only the CSRF token in memory or sessionStorage.

  • For POST/PUT/DELETE requests

  • Handle 403 (CSRF error) responses gracefully — show a message like “Session expired, please refresh or re-login.”

Step 6: Optional — Add Session Mapping (for Admin Panels or Token Revocation)

If you want to track or revoke tokens:

  • Add a session_id column in DB or Redis mapping:

session_id -> jwt_id
  • On logout or admin disable, revoke by session ID.


Step 7: Test OWASP Protections

Verify:

  • No JWT in localStorage or sessionStorage

  • ✅ Cookies have HttpOnly, Secure, and SameSite flags

  • ✅ CSRF token mismatch returns 403

  • ✅ XSS payloads can’t read cookies

  • ✅ Rate limiter still blocks excessive login attempts

  • ✅ Kafka still receives login notifications


⚙️ Additional Considerations

πŸ—„️ Database Changes

  • Optional: Add csrf_tokens table or store in Redis (csrf:{sessionId} → token).

πŸ”§ Config Updates

  • Add cookie + CORS settings to application.properties.

  • Ensure backend sends cookies via ResponseCookie.from() in Spring.

πŸ’» Frontend

  • Remove token storage logic.

  • Add withCredentials: true in requests.

  • Always attach X-CSRF-TOKEN header on write requests.


✅ Summary

Protection Mechanism Mitigates
HttpOnly cookie     JWT in secure cookie         XSS
CSRF token     Separate token validation         CSRF
Input sanitization (already using Jsoup)     Clean username/password         Injection
Rate limiting (already in place)     IP-based limiter         Brute force
Kafka login events     Audit trail         Security monitoring

No comments:

Post a Comment

🧠 How to Upgrade Your Spring Boot Login for Full OWASP Protection (XSS, CSRF, HttpOnly JWT)

 Modern web apps often use localStorage for JWTs — but that’s risky. localStorage is accessible to JavaScript , so an XSS attack can easi...