Get a Pentest and security assessment of your IT network.

Cyber Security

JWT Authentication in WebSockets

TL;DR

This guide shows you how to secure your WebSocket connections using JWT (JSON Web Tokens). We’ll cover verifying the token on connection and handling invalid tokens. It assumes you already have a system for issuing JWTs.

Steps

  1. Server-Side Setup: Receive Token
    • When a client connects to your WebSocket server, expect the JWT as part of the connection process. This is commonly done via a query parameter in the URL or within an initial handshake message.
    • Example (Node.js with ws library):
    • const ws = new WebSocket.Server({ port: 8080 });
      
      ws.on('connection', ws => {
        const urlParams = new URLSearchParams(ws.upgradeReq.url);
        const token = urlParams.get('token');
        // ... further processing
      });
  2. Token Verification
    • Use a library appropriate for your server language to verify the JWT’s signature and claims (expiry, issuer etc.). Do not implement this yourself. Use well-maintained libraries like jsonwebtoken in Node.js or similar in other languages.
    • Example (Node.js):
    • const jwt = require('jsonwebtoken');
      
      ws.on('connection', ws => {
        const urlParams = new URLSearchParams(ws.upgradeReq.url);
        const token = urlParams.get('token');
      
        jwt.verify(token, 'your-secret-key', (err, decoded) => {
          if (err) {
            // Token is invalid
            console.error('Invalid token:', err.message);
            ws.send(JSON.stringify({ type: 'auth_failed', message: 'Invalid token' }));
            ws.terminate(); // Close the connection
            return;
          }
      
          // Token is valid, decoded contains user information
          console.log('Decoded token:', decoded);
          // ... proceed with authenticated connection
        });
      });
    • Important: Replace 'your-secret-key' with your actual secret key used to sign the JWTs. Keep this key secure!
  3. Handle Invalid Tokens
    • If token verification fails (e.g., invalid signature, expired token), close the WebSocket connection immediately.
    • Send an appropriate error message to the client indicating authentication failure. This helps with debugging and user experience.
    • Example: See code snippet in Step 2.
  4. Authenticated Connection Handling
    • If the token is valid, store the user information (from the decoded JWT) associated with that WebSocket connection. This allows you to identify and authorize actions performed by the client.
    • Example: Store in a map/dictionary keyed by the WebSocket object.
    • const connectedUsers = new Map(); // ws object -> user data
      
      ws.on('connection', ws => {
        // ... token verification...
      
        connectedUsers.set(ws, decoded);
      });
  5. Message Handling & Authorization
    • When the client sends a message, retrieve the associated user information from your storage (e.g., connectedUsers map).
    • Check if the user has permission to perform the requested action based on their role or other claims in the JWT.
    • Example:
    • ws.on('message', message => {
        const userData = connectedUsers.get(ws);
        if (!userData) {
          // User is not authenticated (connection likely lost)
          console.error('Unauthorized access');
          return;
        }
      
        // Check user permissions based on userData...
      });
  6. Connection Closure
    • When the WebSocket connection closes, remove the associated user information from your storage. This prevents memory leaks and ensures that stale data isn’t used.
    • ws.on('close', () => {
        connectedUsers.delete(ws);
      });

Security Considerations

  • HTTPS: Always use HTTPS for your WebSocket connections to prevent man-in-the-middle attacks.
  • Secret Key Security: Protect your JWT secret key carefully. Do not hardcode it directly into your code; store it securely in environment variables or a configuration file.
  • Token Expiration: Set appropriate expiration times for your JWTs to limit the impact of compromised tokens.
  • Refresh Tokens: Consider using refresh tokens to allow clients to obtain new JWTs without requiring them to re-authenticate frequently.
Related posts
Cyber Security

Zip Codes & PII: Are They Personal Data?

Cyber Security

Zero-Day Vulnerabilities: User Defence Guide

Cyber Security

Zero Knowledge Voting with Trusted Server

Cyber Security

ZeroNet: 51% Attack Risks & Mitigation