Blog | G5 Cyber Security

JWT Authentication: Best Practices

TL;DR

Yes, there are standard ways to use JWTs (JSON Web Tokens) for user authentication. This guide covers the most important protocols and techniques to keep your system secure. We’ll focus on OAuth 2.0, OpenID Connect, and best practices like token storage, refresh tokens, and revocation.

1. Understanding the Basics

JWTs aren’t authentication *protocols* themselves; they are a method of representing claims securely. You need a protocol to handle the initial login and token exchange. The most common choices are:

2. Using OAuth 2.0 with JWTs

OAuth 2.0 defines several ‘grant types’ for obtaining tokens. Here’s how it works with JWTs:

  1. Authorisation Code Grant: The most secure flow, especially for web applications.
    • User is redirected to the Authorisation Server (e.g., Google, Facebook).
    • User authenticates with the server and grants permission.
    • The server redirects back to your application with an authorisation code.
    • Your application exchanges this code for access tokens (often JWTs) and refresh tokens.
  2. Implicit Grant: Less secure, generally discouraged due to security concerns. It directly returns the token in the redirect URL.
  3. Client Credentials Grant: For machine-to-machine authentication (e.g., services accessing other services).

Example of exchanging an authorisation code for a JWT:

POST /token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code={AUTHORISATION_CODE}&redirect_uri={YOUR_REDIRECT_URI}&client_id={YOUR_CLIENT_ID}&client_secret={YOUR_CLIENT_SECRET}

3. OpenID Connect (OIDC) – The Preferred Approach

OIDC adds an identity layer to OAuth 2.0. It provides a standard way to get user profile information.

OIDC simplifies authentication and provides better security features than using OAuth 2.0 alone.

4. JWT Storage Best Practices

  1. Never store JWTs in LocalStorage: Vulnerable to XSS attacks.
  2. Use HttpOnly Cookies (with SameSite attribute): The most secure option for web applications. Set HttpOnly to prevent JavaScript access and SameSite=Strict or SameSite=Lax to mitigate CSRF risks.
    Set-Cookie: jwt_token=YOUR_JWT; HttpOnly; SameSite=Strict; Secure
  3. In-Memory Storage (for short-lived tokens): Suitable for single-page applications, but requires careful handling of token persistence.
  4. Secure Enclaves/Keychains: For mobile apps, use platform-specific secure storage mechanisms.

5. Refresh Tokens

JWTs have a limited lifespan. Use refresh tokens to obtain new access tokens without requiring the user to re-authenticate.

6. JWT Revocation

Sometimes you need to invalidate tokens before they expire (e.g., user logs out, password change).

7. JWT Validation

  1. Verify Signature: Ensure the token hasn’t been tampered with using your secret key or public key (depending on the signing algorithm).
  2. Check Expiration Time (exp claim): Reject expired tokens.
  3. Validate Issuer (iss claim) and Audience (aud claim): Confirm the token is intended for your application.

Example validation using a library:

// Example with a hypothetical JWT library
try {
  const decoded = jwtLibrary.verify(token, secretKey);
  if (decoded && decoded.exp > Date.now() / 1000) {
    // Token is valid
  } else {
    // Invalid token
  }
} catch (error) {
  // Validation failed
}

8. Security Considerations

Exit mobile version