AJAX - CSRF Protection

1) What is CSRF?

  • CSRF = Cross-Site Request Forgery

  • It’s an attack where a malicious site tricks a logged-in user’s browser into making unwanted requests to another site where the user is authenticated.

  • Example:

    • You’re logged into your bank (https://bank.com).

    • You visit a malicious site (https://evil.com) that secretly sends an AJAX request:

      fetch("https://bank.com/transfer?amount=1000&to=evil", { method: "POST" });
      
    • Since your cookies/session are sent automatically, the bank may execute the transfer unless protection is in place.


2) Why CSRF is Dangerous in AJAX

  • AJAX requests automatically include cookies (if credentials: include is used or same-origin).

  • Without protection, attackers can forge actions like:

    • Changing passwords

    • Transferring money

    • Deleting accounts


3) How to Protect Against CSRF

Several strategies are commonly used:


a) CSRF Tokens (Most Common)

  • Server generates a unique, random token per user/session.

  • Token is sent to the client (in HTML or API response).

  • Client includes the token in each AJAX request (usually in headers or body).

  • Server verifies token matches → request allowed.

Example (AJAX with token):

fetch("/update-profile", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-CSRF-Token": document.querySelector("meta[name='csrf-token']").content
  },
  body: JSON.stringify({ name: "Alice" })
});

Server checks:

  • Token in header matches token stored in session.

  • If missing/invalid → reject.


b) SameSite Cookies

  • Modern browsers support the SameSite cookie attribute:

    • SameSite=Strict → Cookie sent only for same-site requests.

    • SameSite=Lax → Cookie sent for top-level navigation GETs, not for AJAX/POST.

    • SameSite=None; Secure → Allows cross-site requests but only over HTTPS.

Example:

Set-Cookie: session=abc123; SameSite=Strict; Secure; HttpOnly

This prevents cookies from being sent with cross-origin requests.


c) Double-Submit Cookie

  • Server sets a CSRF cookie with a token.

  • Client reads cookie and sends it back in a header.

  • Server compares cookie value vs header value → if mismatch → reject.


d) Verify Request Headers

  • Require AJAX requests to include a custom header (e.g., X-Requested-With: XMLHttpRequest).

  • Malicious sites can’t set custom headers without triggering CORS preflight.

  • Used as a lightweight protection layer.


4) Example Flow with CSRF Token

  1. User loads page → server embeds CSRF token in page (<meta> or hidden field).

  2. Client-side AJAX includes the token in request.

  3. Server checks token validity.

  4. If valid → process; if invalid → reject.


5) Best Practices

  • Always use CSRF tokens for state-changing AJAX requests.

  • Use SameSite cookies where possible for extra safety.

  • Do not rely only on headers like Referer (can be spoofed or stripped).

  • Combine CSRF protection with authentication and CORS for strong security.


Summary

  • CSRF tricks a user’s browser into making unauthorized requests.

  • AJAX is vulnerable because cookies auto-attach.

  • Defenses include:

    1. CSRF tokens (most common & reliable).

    2. SameSite cookies.

    3. Double-submit cookies.

    4. Custom headers.

  • Best practice: Use CSRF tokens + SameSite cookies together.