{"id":17678,"library":"hmac-auth-express","title":"Express HMAC Authentication Middleware","description":"HMAC Auth Express provides middleware for Express applications to implement HMAC (Hash-based Message Authentication Code) authentication. It is currently at version 9.0.0 and demonstrates an active development cadence with regular updates. Key differentiators include zero runtime dependencies (only Express as a peer dependency), timing-safe comparisons, 100% code coverage, support for all standard hash algorithms, and built-in replay attack prevention. The library also features flexible secret management, allowing for static secrets or dynamic resolution via an async function. It ships with full TypeScript type definitions, enhancing developer experience and ensuring type safety in modern JavaScript projects.","status":"active","version":"9.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/connorjburton/hmac-auth-express","tags":["javascript","nodejs","middleware","express","node","authentication","express-middleware","auth","typescript"],"install":[{"cmd":"npm install hmac-auth-express","lang":"bash","label":"npm"},{"cmd":"yarn add hmac-auth-express","lang":"bash","label":"yarn"},{"cmd":"pnpm add hmac-auth-express","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Required as a peer dependency for the middleware to function within an Express application.","package":"express","optional":false}],"imports":[{"note":"While the package supports both CommonJS and ESM, prefer ESM for new projects. The CommonJS example shown is `const { HMAC } = require('hmac-auth-express');`","wrong":"const { HMAC } = require('hmac-auth-express');","symbol":"HMAC","correct":"import { HMAC } from 'hmac-auth-express';"},{"note":"Used for robust error handling in Express middleware chains. The CommonJS equivalent is `const { AuthError } = require('hmac-auth-express');`","wrong":"const AuthError = require('hmac-auth-express').AuthError;","symbol":"AuthError","correct":"import { AuthError } from 'hmac-auth-express';"},{"note":"Import the `Options` interface for type-checking the configuration object passed to the HMAC middleware factory.","symbol":"Options","correct":"import type { Options } from 'hmac-auth-express';"}],"quickstart":{"code":"import express from 'express';\nimport { HMAC } from 'hmac-auth-express';\n\nconst app = express();\nconst port = process.env.PORT ?? 3000;\n\n// IMPORTANT: express.json() MUST be registered BEFORE HMAC middleware\n// if your routes process request bodies.\napp.use(express.json());\n\n// Basic middleware registration with a static secret\napp.use('/api/v1', HMAC('my-super-secret-key'));\n\n// Example route for a GET request\napp.get('/api/v1/hello', (req, res) => {\n  res.send('Hello, HMAC authenticated world!');\n});\n\n// Example route for a POST request that requires body parsing\napp.post('/api/v1/data', (req, res) => {\n  console.log('Received data:', req.body);\n  res.json({ message: 'Data received and authenticated.', data: req.body });\n});\n\n// Error handling middleware for HMAC specific errors\napp.use((error, req, res, next) => {\n  if (error && error.code === 'ERR_HMAC_AUTH_INVALID') {\n    return res.status(401).json({\n      error: 'Authentication Failed',\n      message: error.message\n    });\n  }\n  next(error); // Pass other errors to the next handler\n});\n\napp.listen(port, () => {\n  console.log(`Server listening at http://localhost:${port}`);\n});","lang":"typescript","description":"This quickstart demonstrates basic HMAC middleware registration, proper ordering with `express.json()`, and a custom error handler for authentication failures."},"warnings":[{"fix":"Review how HMAC signatures are generated on the client-side, especially if request bodies or query parameters contain arrays. Ensure consistent array serialization/ordering between client and server for HMAC generation.","message":"The `order` function, used internally for HMAC calculation, was fixed to correctly order array values. This change could lead to non-deterministic ordering if previous versions were used with arrays in a way that produced inconsistent HMACs. Consumers upgrading should re-verify HMAC generation if arrays are part of the signed payload.","severity":"breaking","affected_versions":">=9.0.0"},{"fix":"Ensure `app.use(express.json());` (or similar body parsers) is declared before `app.use(HMAC(...));` in your Express application setup.","message":"When authenticating routes that process request bodies (e.g., POST, PUT), the `hmac-auth-express` middleware MUST be registered *after* any body parsing middleware like `express.json()`. If `express.json()` is placed after `HMAC`, the middleware will not have access to the parsed `req.body`, leading to incorrect HMAC validation.","severity":"gotcha","affected_versions":">=6.6.0"},{"fix":"Verify client-side HMAC header construction matches the expected format outlined in the documentation, including the identifier, UNIX timestamp, and the calculated hash signature separated by a colon.","message":"The HMAC header (default `Authorization`) must be structured specifically as `Identifier Timestamp:Signature`. For example, `Authorization: HMAC 1573504737300:76251c63...`. Missing the identifier (default `HMAC`), incorrect timestamp format, or malformed signature will result in authentication failure.","severity":"gotcha","affected_versions":">=6.6.0"},{"fix":"Implement custom error handling middleware in Express to catch `AuthError` instances or errors with the code `ERR_HMAC_AUTH_INVALID` and return appropriate HTTP status codes (e.g., 401 Unauthorized) and messages.","message":"Error handling for authentication failures can be done by checking `instanceof AuthError` or by inspecting the error code `error.code === 'ERR_HMAC_AUTH_INVALID'`. Failing to implement a specific error handler for these errors will result in Express's default error handling, which might not provide user-friendly responses.","severity":"gotcha","affected_versions":">=6.6.0"}],"env_vars":null,"last_verified":"2026-04-23T00:00:00.000Z","next_check":"2026-07-22T00:00:00.000Z","problems":[{"fix":"Provide a string literal for your secret (e.g., `HMAC('your-secret')`) or a function that returns the secret (e.g., `HMAC((req) => process.env.HMAC_SECRET_KEY)`).","cause":"The first parameter passed to the `HMAC` middleware factory is not a string (for a static secret) or a function (for a dynamic secret).","error":"TypeError: 'secret' must be a string or a function."},{"fix":"Ensure the client-generated timestamp is a valid UNIX epoch timestamp (milliseconds) and that it is within the acceptable time window configured in the `HMAC` options (`maxInterval`, `minInterval`). Adjust client's system clock or server's options if time skew is the issue.","cause":"The timestamp provided in the HMAC header (e.g., `Authorization: HMAC 12345:signature`) is either not a valid UNIX timestamp or falls outside the `maxInterval` / `minInterval` configured for replay attack prevention.","error":"Error: Invalid request, invalid timestamp."},{"fix":"Verify that the client is generating the HMAC signature correctly, using the same secret, algorithm, and canonicalization rules (e.g., body parsing, array ordering) as the server. Common causes include mismatched secrets, incorrect body serialization, or differences in the `algorithm` option.","cause":"The calculated HMAC signature on the server-side, based on the request content and secret, does not match the signature provided in the `Authorization` header by the client.","error":"Error: Invalid request, invalid signature."}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}