{"id":16729,"library":"koa-escher-auth","title":"Koa Escher Authentication Middleware","description":"koa-escher-auth is a Koa middleware designed to integrate Escher authentication into Node.js applications. It restricts access to routes by verifying incoming HTTP requests using Escher signatures and a configurable key pool. The package is currently stable at version 4.0.0, released in January 2023, with updates occurring on an irregular basis, typically for dependency upgrades or minor feature enhancements. Key differentiators include its tight integration with the Koa framework and its reliance on the `escher-keypool` for managing authentication credentials, ensuring secure, signed request processing. It is explicitly designed to work downstream of a body-parser middleware to correctly process request bodies for authentication. Escher itself is a stateless API authentication protocol based on AWS Signature Version 4.","status":"active","version":"4.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/emartech/koa-escher-auth","tags":["javascript"],"install":[{"cmd":"npm install koa-escher-auth","lang":"bash","label":"npm"},{"cmd":"yarn add koa-escher-auth","lang":"bash","label":"yarn"},{"cmd":"pnpm add koa-escher-auth","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency, this is a Koa middleware.","package":"koa","optional":false},{"reason":"Required upstream middleware to parse request bodies before authentication. Without it, rawBody might be undefined.","package":"koa-bodyparser","optional":false},{"reason":"Core dependency for managing and retrieving Escher authentication keys.","package":"escher-keypool","optional":false},{"reason":"Introduced in v4.0.0 as a dependency of `escher-keypool` for logging, replacing `logentries-logformat`.","package":"@emartech/json-logger","optional":false}],"imports":[{"note":"The primary export is a function `authenticator` which expects configuration. Direct `app.use(escherAuth)` would not work as `escherAuth` itself is the module, not the middleware function. The `require` pattern is common in older Koa apps, but ESM is preferred in modern Node.js environments.","wrong":"const escherAuth = require('koa-escher-auth'); app.use(escherAuth);","symbol":"authenticator","correct":"import { authenticator } from 'koa-escher-auth';"},{"note":"The module exports an object with a named export `authenticator`, not a default export. The CommonJS `require` syntax as shown in the README is the most robust import pattern for this library's typical usage.","wrong":"import escherAuth from 'koa-escher-auth';","symbol":"authenticator","correct":"const escherAuth = require('koa-escher-auth'); app.use(escherAuth.authenticator(escherConfig));"},{"note":"After successful authentication, the access key ID used for the request is attached to the Koa context for downstream middleware access. This is a property on the context object, not a direct import.","symbol":"ctx.escherAccessKeyId","correct":"app.use(function(ctx) { console.log(ctx.escherAccessKeyId); });"}],"quickstart":{"code":"import Koa from 'koa';\nimport bodyParser from 'koa-bodyparser';\nimport { authenticator } from 'koa-escher-auth';\n\n// Load Escher configuration from environment variables or provide directly\nconst escherConfig = {\n  credentialScope: process.env.SUITE_ESCHER_CREDENTIAL_SCOPE ?? 'eu/app-id/ems_request',\n  keyPool: process.env.SUITE_ESCHER_KEY_POOL ?? JSON.stringify([\n    { 'keyId': 'app-id_suite_v1', 'secret': 'app-id-secret', 'acceptOnly': 0 }\n  ])\n};\n\nconst app = new Koa();\n\n// IMPORTANT: koa-bodyparser must be used before koa-escher-auth\napp.use(bodyParser());\n\n// Apply the Escher authenticator middleware\napp.use(authenticator(escherConfig));\n\n// Define a protected route handler\napp.use(async (ctx) => {\n  // If authentication passes, the access key ID is available on ctx.escherAccessKeyId\n  ctx.body = `Hello world, ${ctx.escherAccessKeyId}! Request authenticated successfully.`;\n});\n\nconst port = process.env.PORT || 3000;\napp.listen(port, () => {\n  console.log(`Server listening on http://localhost:${port}`);\n});","lang":"typescript","description":"This quickstart demonstrates how to set up a Koa application with Escher authentication, including the necessary body parser middleware and how to access the authenticated user's access key ID from the Koa context."},"warnings":[{"fix":"Review your logging configurations and ensure compatibility with `@emartech/json-logger` if you were previously relying on `logentries-logformat` output. No direct changes to `koa-escher-auth` integration are typically needed, but downstream logging consumers might be affected.","message":"Version 4.0.0 introduced a breaking change where its internal dependency, `escher-keypool`, now uses `@emartech/json-logger` instead of `logentries-logformat` for logging. This change may require adjustments if your logging infrastructure or tests directly interacted with or expected the format of the previous logger.","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"Ensure `app.use(bodyParser());` is called *before* `app.use(escherAuth.authenticator(escherConfig));` in your Koa application setup.","message":"The `koa-escher-auth` middleware *must* be used downstream of a body-parser middleware (e.g., `koa-bodyparser`) that defines `request.rawBody`. Incorrect ordering will lead to authentication failures, especially for requests with bodies.","severity":"gotcha","affected_versions":">=3.0.0"},{"fix":"Always use `JSON.stringify()` when defining the `keyPool` object in your configuration. If using environment variables, ensure the variable's value is a properly escaped JSON string.","message":"The `keyPool` configuration parameter (whether passed directly or via environment variable `SUITE_ESCHER_KEY_POOL`) must always be a valid JSON *string*. Providing an object directly or an invalid JSON string will result in configuration errors.","severity":"gotcha","affected_versions":">=3.0.0"},{"fix":"Ensure your project's Node.js environment adheres to the specified engine requirements (`>=10.13.0 <19`). Consider using a Node Version Manager (NVM) to manage different Node.js versions.","message":"Node.js engine support was updated in v3.5.0 to `Node.js >=10.13.0 <19`. Using the package with Node.js versions outside this range (e.g., Node.js 19+) may lead to unexpected behavior or runtime errors due to dependency incompatibilities or changes in Node.js APIs.","severity":"gotcha","affected_versions":">=3.5.0"},{"fix":"Upgrade to version 3.4.0 or newer to ensure correct handling of empty POST requests and robust body validation based on `request.body`.","message":"Prior to version 3.4.0, handling of empty POST requests and body validation was based on `request.rawBody`. This could cause issues with certain request types or body parser configurations. Version 3.4.0 updated this to validate the body based on `request.body`.","severity":"gotcha","affected_versions":"<3.4.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Ensure `app.use(bodyParser())` is placed before `app.use(escherAuth.authenticator())` in your Koa middleware chain.","cause":"The `koa-bodyparser` middleware was not applied or was applied after `koa-escher-auth.authenticator`.","error":"TypeError: Cannot read properties of undefined (reading 'rawBody')"},{"fix":"Verify that your `escherConfig.keyPool` (or `SUITE_ESCHER_KEY_POOL` environment variable) contains a valid JSON string, using `JSON.stringify()` if constructing it from an object.","cause":"The `keyPool` configuration provided to the authenticator is not a valid JSON string or is malformed.","error":"Error: Invalid Escher key pool"},{"fix":"Double-check that the `credentialScope`, `keyId`, and `secret` in your `escherConfig` on the server match the client-side configuration. Ensure server and client clocks are synchronized. Validate that the client is signing the request body and headers exactly as expected by the server.","cause":"The Escher signature generated by the client does not match the signature computed by the server. This is commonly caused by incorrect `credentialScope`, `keyId`, `secret`, client-server clock skew, or discrepancies in how the request is signed (e.g., included headers, body content).","error":"Authentication Failed: Signature mismatch"}],"ecosystem":"npm"}