TL;DR
This guide shows how to create a basic JWT authentication system using only the signature part of a standard JWT, for scenarios where minimal data transfer is required. This approach significantly reduces token size but requires careful handling of shared secrets.
Prerequisites
- A server-side environment (e.g., Node.js, Python, PHP).
- A library capable of generating and verifying HMAC signatures (e.g.,
cryptoin Node.js,hmacin Python).
Steps
- Choose a Secret Key: This is crucial. The security of your system depends on keeping this key secret and strong. Use a long, random string.
const secretKey = 'your-very-secret-key'; - Generate the Signature: Instead of creating a full JWT with header and payload, we’ll only generate the signature based on some identifier (e.g., user ID).
The process involves hashing the identifier using your secret key.
const crypto = require('crypto'); function generateSignature(identifier) { const hash = crypto.createHmac('sha256', secretKey).update(identifier).digest('hex'); return hash; } // Example: const userId = '12345'; const signature = generateSignature(userId); console.log(signature); - Send the Signature to the Client: Transmit this signature (e.g., in a cookie or as part of an API response). Avoid sending any sensitive user data.
For example, you might set it as an HTTP-only cookie.
- Verify the Signature on Subsequent Requests: On each request, recalculate the signature based on the identifier and compare it to the received signature.
function verifySignature(identifier, receivedSignature) { const calculatedSignature = generateSignature(identifier); return crypto.timingSafeEqual(Buffer.from(calculatedSignature), Buffer.from(receivedSignature)); } // Example: const userIdFromRequest = '12345'; // Get this from the request (e.g., user ID in session) const receivedSignatureFromCookie = req.cookies.signature; if (verifySignature(userIdFromRequest, receivedSignatureFromCookie)) { // Signature is valid - allow access. console.log('Signature verified!'); } else { // Signature is invalid - reject request. console.log('Invalid signature!'); } - Important Security Considerations:
- Shared Secret Management: Protect the secret key at all costs. Do not hardcode it directly into your application code. Use environment variables or a secure configuration management system.
- Identifier Uniqueness: Ensure that the identifier used to generate the signature is unique for each user and cannot be easily guessed or manipulated.
- HTTPS Only: Always transmit signatures over HTTPS to prevent interception.
- Limited Scope: This method provides minimal security compared to full JWT authentication. It’s suitable only for scenarios where you trust the client environment and require very small token sizes.
- No Payload: Because there is no payload, you cannot store any user information in the token itself. All user data must be retrieved from a server-side database or session storage.

