Thursday, June 05, 2025

Securing and validating JWT tokens

JSON Web Tokens (JWTs) are widely used for authentication and authorization in web applications. However, securely storing JWTs on the client side is critical to prevent vulnerabilities like cross-site scripting (XSS) attacks. While local storage and session storage are common choices, HttpOnly cookies offer a superior alternative for storing JWTs. 

HttpOnly cookies are browser cookies with the HttpOnly flag set, meaning they cannot be accessed by client-side JavaScript. This restriction makes them immune to XSS attacks, as malicious scripts injected into a webpage cannot read or manipulate the cookie's contents. Unlike local storage or session storage, which are fully accessible to JavaScript, HttpOnly cookies are managed by the browser and sent automatically with HTTP requests to the specified domain.

HttpOnly cookies can be configured with additional security flags like Secure and SameSite:

  • Secure: Ensures the cookie is only sent over HTTPS, preventing interception over unencrypted connections.
  • SameSite: Mitigates cross-site request forgery (CSRF) attacks by restricting when cookies are sent in cross-origin requests. For example, setting SameSite=Strict ensures the cookie is only sent for requests originating from the same site.

HttpOnly cookies allow developers to set precise expiration times, aligning with the JWT's own expiration. This ensures the token is automatically removed by the browser when it expires, reducing the risk of stale tokens lingering on the client.

To maximize the security of HttpOnly cookies for JWT storage, follow these best practices:

  • Always set the HttpOnly, Secure, and SameSite attributes.
  • Use short-lived JWTs with refresh tokens to minimize the impact of potential breaches.

Some security experts feel that CSRF tokens should be used along with cookies. 
But when using SameSite=Strict on cookies, CSRF tokens are generally not required for most scenarios because SameSite=Strict provides strong protection against cross-site request forgery (CSRF) attacks. 

Here's why:
  • How SameSite=Strict Works: The SameSite=Strict attribute ensures that the browser only sends the cookie with requests originating from the same site (i.e., the same domain as the cookie). Cross-origin requests, such as those initiated by a malicious site, will not include the cookie, effectively blocking CSRF attacks.
  • Why CSRF Tokens May Not Be Needed: Since the cookie (e.g., containing a JWT) is not sent with cross-origin requests, an attacker cannot exploit the cookie to make unauthorized requests on behalf of the user. This eliminates the primary vector for CSRF attacks, making additional CSRF tokens redundant in many cases.
If you cannot have the restriction of "SameSite=Strict", then it is best to implement CSRF tokens. Also for extremely secure mission-critical applications, having CSRF tokens will add an additional layer of security. 

Validation of JWT on server side:
Validating JWTs using signatures ensures the token's integrity and authenticity. This process relies on cryptographic signatures, which can be implemented using symmetric or asymmetric algorithms.

Symmetric key validation uses a single shared secret key for both signing and verifying the JWT. The most common algorithm is HMAC (e.g., HMAC-SHA256, denoted as HS256 in JWT). The recipient (e.g., a server) uses the same secret key to recompute the HMAC of the Header and Payload. If the computed signature matches the one in the JWT, the token is valid and untampered. Both the issuer (Identity JWT provider) and verifier (server side code) must share the same secret key securely.
So on the server-side, this entails storing the secret symmetric key securely in some place. 

Asymmetric key validation uses a pair of keys: a private key for signing and a public key for verification. Common algorithms include RS256 (RSA with SHA-256) and ES256 (ECDSA with SHA-256). The issuer (Identity JWT provider) signs the JWT using the private key. The recipient uses the corresponding public key to decrypt and verify the signature. If the decrypted hash matches the hash of the Header and Payload, the token is valid. The private key is kept secret by the issuer, while the public key can be freely distributed to verifiers.

For most modern, distributed web applications, asymmetric key validation (e.g., RS256) is preferred due to its flexibility and security, while symmetric key validation (e.g., HS256) suits simpler, internal systems.

No comments:

Post a Comment