{"id":43518163,"url":"https://github.com/jerzyadamowski/aws4-express","last_synced_at":"2026-02-03T14:06:34.189Z","repository":{"id":65868160,"uuid":"595563259","full_name":"jerzyadamowski/aws4-express","owner":"jerzyadamowski","description":"Express middleware handlers for validation AWS Signature V4. Your web app can mimic AWS services, and you can use benefit from already well-defined standard to securing web API.","archived":false,"fork":false,"pushed_at":"2025-09-10T09:28:26.000Z","size":238,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-11T21:07:35.328Z","etag":null,"topics":["aws4","express","secure-api","signature"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jerzyadamowski.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-01-31T10:45:42.000Z","updated_at":"2025-09-10T09:13:08.000Z","dependencies_parsed_at":"2024-12-11T13:34:01.304Z","dependency_job_id":"79726d92-5d20-4245-851d-a614caec2163","html_url":"https://github.com/jerzyadamowski/aws4-express","commit_stats":{"total_commits":29,"total_committers":2,"mean_commits":14.5,"dds":"0.48275862068965514","last_synced_commit":"5f45a658840c755e81b4df4c7eeb6a6d8eeb8d3a"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/jerzyadamowski/aws4-express","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jerzyadamowski%2Faws4-express","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jerzyadamowski%2Faws4-express/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jerzyadamowski%2Faws4-express/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jerzyadamowski%2Faws4-express/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jerzyadamowski","download_url":"https://codeload.github.com/jerzyadamowski/aws4-express/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jerzyadamowski%2Faws4-express/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29047107,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-03T10:09:22.136Z","status":"ssl_error","status_checked_at":"2026-02-03T10:09:16.814Z","response_time":96,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws4","express","secure-api","signature"],"created_at":"2026-02-03T14:04:06.485Z","updated_at":"2026-02-03T14:06:29.249Z","avatar_url":"https://github.com/jerzyadamowski.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# aws4-express\nThis library is about to create on security layer of your API using well defined comunication standard known as AWS Signature V4.\n\nWe provide Express middleware handler `awsVerify` for validation your `AWS Signature V4` with your access and secret pair of key. So, your web app can mimic AWS services, and you can use benefits from already well-defined standard to securing your web API.\n\nAt this moment, library is based on general version of aws4 signature:\n[Authenticating Requests (AWS Signature Version 4)](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html)\n\n### Beta stage\nUntil we hit \u003e=1.x.x, there could be possible breaking changes on minor changes.\nUse at least 0.8.0 version.\n\n## Requirements\n- Node.js \u003e= 20.x\n\n## Install\n\n\n```shell\nnpm install aws4-express\n```\n\n## Use\n\nThere are prepared helpers to handle the original body with any changes, because if you change a single character, your request won't be valid anymore.\n\nIf you use express parsers like `express.raw()` or `express.json()` or `express.urlencoded` you can attach with handler `rawBodyFromVerify`. You can also write own stream parser or use our `rawBodyFromStream` as long as you attach `rawBody: string | Buffer` to request object.\n\n```typescript\n  import express from 'express';\n  import { awsVerify, rawBodyFromVerify, rawBodyFromStream } from 'aws4-express';\n\n  const app = express();\n  // whenever you may need to get original body string and you case\n  // when json parser u may use like this\n  app.use(\n    express.json({\n      type: '*/*',\n      verify: rawBodyFromVerify,\n    }),\n  );\n\n  // or when json parser u may use like this\n  app.use(\n    express.raw({\n      type: '*/*',\n      verify: rawBodyFromVerify,\n    })\n  );\n\n  // or when url encoded body u may use like this\n  app.use(\n    express.urlencoded({\n      extended: true,\n      type: '*/*',\n      verify: rawBodyFromVerify,\n    }),\n  );\n\n  // or events on when json parser u may use like this\n  app.use(rawBodyFromStream);\n\n  // main handler to authorization incomming requests:\n  app.use(awsVerify({\n    secretKey: (message, req, res, next) =\u003e {\n      // fetch secret key from your storage key/secret pairs (sql, nosql, memory)\n      // you have to provide your own secret provider here.\n      // retrun string | undefined\n\n      return getMySecretByKey(message.accessKey),\n    }\n  }));\n\n  // your routers ...\n  app.all('*', ...);\n  app.get('/get', ...);\n  app.post('/post', ...);\n\n  return app;\n```\n\n## Example:\n\n- [simpleIntegration.ts](/src/examples/simpleIntegration.ts)\n\n## Features:\n\n- [x] General implementation standard: aws4 signature.\n- [x] Fully customized.\n- [x] No strict rules on services, regions you can name it as you want as long your signing client support this.\n- [x] Single chunk request\n- [x] Tests with client: [aws4](https://www.npmjs.com/package/aws4)\n- [ ] Query headers x-amz-*,\n- [ ] Multiple chunks (no x-amz-decoded-content-length)\n\n## Supported headers:\n\n- `authorization` - [required] must have in proper format: **Authorization: AWS4-HMAC-SHA256\nCredential=`ACCESS_KEY`/`DATE`/`REGION`/`SERVICE`/`TYPE_REQUEST`,\nSignedHeaders=\u003c SIGNED_HEADERS\u003e,\nSignature=`SIGNATURE`** :\n  * `ACCESS_KEY` - any text without whitespaces and slashes (/) - Only have to do is handle distribution of access_key, secret_key and these keys have to be accessible on the server side.\n  * `DATE` - is part of X-AMZ-DATE: in format YYYYMMDD.\n  * `REGION` - any thing you need in this place or use something from [amz regions](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.RegionsAndAvailabilityZones.html).\n  * `SERVICE` - any thing you need in this place or 'execute-api' for sake of simplicity.\n  * `TYPE_REQUEST` - you can use your variations instead  of standard 'aws4_request'.\n  * `SIGNED_HEADERS` - all signed headers - more headers mean harder to temper request. Required headers at this moment: *host:x-amz-date*\n  * `SIGNATURE` - calculated signature based on [Authenticating Requests (AWS Signature Version 4)](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html)\n- `x-amz-date` - [required] must have in request to valid request signature\n- `x-amz-content-sha256` - [optional] you can attach precalculated hash. When X-Amz-Content-Sha256 is sent we skip calculating hash from body. This way is less secure and recommended use at least with `X-Amz-Expires`.\n  * There can provide your validation whenever you want handle this header `onBeforeParse` or `onAfterParse`.\n  * You can also send `UNSIGNED-PAYLOAD` instead of sha-256 signature - this cloud speed up your bigger request, but signature will be same as long as headers remain same.\n  * You can put your signature (most client don't include these headers) - should be calculated in this way:\n    ```\n    crypto.createHash('sha256').update(data, 'utf8').digest('hex')\n    ```\n- `x-amz-expires` - [optional] - format: `YYYY-mm-ddTHH:MM:SS`. If you want valid your request for a period of time and don't want to reuse signature when time is up.\n\nPull Requests are welcome.\n\n## Documentation\n\n# awsVerify Function Documentation\n\n## Overview\n\nThe `awsVerify` function is an Express.js middleware that verifies AWS signatures in incoming requests.\n\n## Usage\n\n```javascript\nimport { awsVerify } from 'aws4-express';\n\napp.use(awsVerify(options));\n```\n\n## Parameters\n\n- `options`: An object of type `AwsVerifyOptions`\n\n## Return Value\n\nReturns an Express.js middleware function.\n\n## Configuration: AwsVerifyOptions\n\nThe `AwsVerifyOptions` object can contain the following fields:\n\n### secretKey (required)\n\n- Type: `(message: AwsIncomingMessage, req: Request, res: Response, next: NextFunction) =\u003e Promise\u003cstring | undefined\u003e | string | undefined`\n- Description: Callback for retrieving the secret key. Should return the secret key based on incoming parameters or `undefined` if the key is not available.\n\n### headers (optional)\n\n- Type: `(headers: Dictionary) =\u003e Promise\u003cDictionary\u003e | Dictionary`\n- Description: Callback for modifying incoming headers before the parsing process.\n\n### enabled (optional)\n\n- Type: `(req: Request) =\u003e Promise\u003cboolean\u003e | boolean`\n- Description: Function determining whether AWS signature validation should be performed. If it returns `false`, validation will be skipped.\n\n### onMissingHeaders (optional)\n\n- Type: `(req: Request, res: Response, next: NextFunction) =\u003e Promise\u003cvoid\u003e | void`\n- Description: Custom response when required headers are missing.\n- Default: Sends a 400 status with the message \"Required headers are missing\".\n\n### onSignatureMismatch (optional)\n\n- Type: `(req: Request, res: Response, next: NextFunction) =\u003e Promise\u003cvoid\u003e | void`\n- Description: Custom response when the signature doesn't match.\n- Default: Sends a 401 status with the message \"The signature does not match\".\n\n### onExpired (optional)\n\n- Type: `(req: Request, res: Response, next: NextFunction) =\u003e Promise\u003cvoid\u003e | void`\n- Description: Custom response when the signature has expired.\n- Default: Sends a 401 status with the message \"Request is expired\".\n\n### onBeforeParse (optional)\n\n- Type: `(req: Request, res: Response, next: NextFunction) =\u003e Promise\u003cboolean\u003e | boolean`\n- Description: Callback invoked before the standard parser. If it returns `false`, validation will be stopped.\n- Default: Always returns `true`.\n\n### onAfterParse (optional)\n\n- Type: `(message: AwsIncomingMessage, req: Request, res: Response, next: NextFunction) =\u003e Promise\u003cboolean\u003e | boolean`\n- Description: Callback invoked after the standard parser completes. If it returns `false`, validation will be stopped.\n- Default: Always returns `true`.\n\n### onSuccess (optional)\n\n- Type: `(message: AwsIncomingMessage | undefined, req: Request, res: Response, next: NextFunction) =\u003e Promise\u003cvoid\u003e | void`\n- Description: Callback invoked after successful signature validation.\n- Default: Calls `next()`.\n\n## Example\n\n```javascript\nimport express from 'express';\nimport { awsVerify, rawBodyFromVerify } from 'aws4-express';\n\nconst app = express();\n\napp.use(express.json({ type: '*/*', verify: rawBodyFromVerify }));\n\napp.use(awsVerify({\n  secretKey: async (message) =\u003e {\n    // Implement secret key retrieval logic\n    return 'your_secret_key';\n  },\n  onSignatureMismatch: (req, res) =\u003e {\n    res.status(403).send('Unauthorized');\n  }\n}));\n\napp.get('/', (req, res) =\u003e {\n  res.send('Hello, AWS-verified world!');\n});\n\napp.listen(3000, () =\u003e {\n  console.log('Server is running on port 3000');\n});\n```\n\nIn this example, the `awsVerify` middleware is used to verify the AWS signature for all incoming requests. A custom `secretKey` function is used to provide the secret key, and `onSignatureMismatch` defines a custom response for signature mismatch cases.\n\n### awsVerify:\n\n#### Complete options configuration for `awsVerify`:\n```typescript\nexpress.use(awsVerify({\n  secretKey: (message: AwsIncomingMessage, req: Request, res: Response, next: NextFunction) =\u003e Promise\u003cstring | undefined\u003e | string | undefined;\n  headers?: (headers: Dictionary) =\u003e Promise\u003cDictionary\u003e | Dictionary;\n  enabled?: (req: Request) =\u003e Promise\u003cboolean\u003e | boolean;\n  onMissingHeaders?: (req: Request, res: Response, next: NextFunction) =\u003e Promise\u003cvoid\u003e | void;\n  onSignatureMismatch?: (req: Request, res: Response, next: NextFunction) =\u003e Promise\u003cvoid\u003e | void;\n  onExpired?: (req: Request, res: Response, next: NextFunction) =\u003e Promise\u003cvoid\u003e | void;\n  onBeforeParse?: (req: Request, res: Response, next: NextFunction) =\u003e Promise\u003cboolean\u003e | boolean;\n  onAfterParse?: (\n    message: AwsIncomingMessage,\n    req: Request,\n    res: Response,\n    next: NextFunction,\n  ) =\u003e Promise\u003cboolean\u003e | boolean;\n  onSuccess?: (\n    message: AwsIncomingMessage | undefined,\n    req: Request,\n    res: Response,\n    next: NextFunction,\n  ) =\u003e Promise\u003cvoid\u003e | void;\n}))\n```\n\n#### Default values for all optional configuration for `awsVerify`:\n```typescript\n  {\n      enabled: () =\u003e true,\n      headers: (req) =\u003e req.headers,\n      onExpired: (res) =\u003e {\n        res.status(401).send('Request is expired');\n      },\n      onMissingHeaders: (res) =\u003e {\n        res.status(400).send('Required headers are missing');\n      },\n      onSignatureMismatch: (res) =\u003e {\n        res.status(401).send('The signature does not match');\n      },\n      onBeforeParse: () =\u003e true,\n      onAfterParse: () =\u003e true,\n      onSuccess: () =\u003e next()\n  }\n```\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjerzyadamowski%2Faws4-express","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjerzyadamowski%2Faws4-express","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjerzyadamowski%2Faws4-express/lists"}