In this lesson, you will learn how to store and transmit JSON Web Tokens (JWTs) in web environments while minimizing the risk of Cross-Site Scripting (XSS) attacks.
The Storage Dilemma
When building web applications, you often have two primary choices for storing an access token: localStorage or HttpOnly cookies.
localStorage is easily accessible via JavaScript. If your site suffers from an XSS vulnerability—where a malicious script is injected into your page—the attacker can read localStorage.getItem('jwt') and exfiltrate your user's credentials instantly.
To mitigate this, the industry standard is to store tokens in an HttpOnly and Secure cookie. Because HttpOnly is a flag set by the server, the browser prevents client-side JavaScript from accessing the cookie. Even if an attacker executes malicious code on your site, they cannot "read" the token to steal it.
Implementing the Secure Pattern
When your C# backend authenticates a user, instead of sending the JWT back in the response body to be stored in JS memory, set it as a cookie:
Response.Cookies.Append("AuthToken", jwtString, new CookieOptions
{
HttpOnly = true, // Prevents JavaScript access
Secure = true, // Ensures cookie is sent over HTTPS only
SameSite = SameSiteMode.Strict, // Protects against CSRF
Expires = DateTime.UtcNow.AddMinutes(60)
});
Transmitting the Token
While this approach secures the storage, your C# backend API still needs to validate the token. Since the browser automatically includes HttpOnly cookies in requests to the domain that set them, your API can extract the token from the request header or cookie during the authentication middleware process.
Because the token is never accessible to your application's client-side JavaScript, an attacker who manages to inject a script cannot perform a "copy-paste" of the user’s session. They are limited to performing requests on behalf of the user, which can be further mitigated by SameSite cookie policies and anti-forgery tokens.
Key Takeaway: Never store JWTs in localStorage or sessionStorage because they are vulnerable to XSS; instead, use HttpOnly and Secure cookies to ensure the token remains inaccessible to client-side scripts.