{"_id":"@cakemail-org/ngapi-ts-auth-middleware","_rev":"10-6ee29e850345094e56a65236c8e3a90f","name":"@cakemail-org/ngapi-ts-auth-middleware","dist-tags":{"beta":"1.0.3-beta.1765898175","latest":"1.0.3"},"versions":{"1.0.0":{"name":"@cakemail-org/ngapi-ts-auth-middleware","version":"1.0.0","keywords":["express","middleware","authentication","authorization","jwt","typescript","ngapi","cakemail","redis","bearer-token"],"author":{"name":"Cakemail"},"license":"MIT","_id":"@cakemail-org/ngapi-ts-auth-middleware@1.0.0","maintainers":[{"name":"sebgregoire","email":"greg@cakemail.com"},{"name":"joemingna","email":"jonathan@cakemail.com"},{"name":"labib-cakemail","email":"labib@cakemail.com"},{"name":"hdgatcake","email":"hdg@cakemail.com"},{"name":"zoyth","email":"f@cakemail.com"},{"name":"salar-cakemail","email":"salar@cakemail.com"}],"homepage":"https://github.com/cakemail/ngapi-ts-auth-middleware#readme","bugs":{"url":"https://github.com/cakemail/ngapi-ts-auth-middleware/issues"},"dist":{"shasum":"51ff163c4e4e3d91f441c20fc7bd8dfcf5651df9","tarball":"https://registry.npmjs.org/@cakemail-org/ngapi-ts-auth-middleware/-/ngapi-ts-auth-middleware-1.0.0.tgz","fileCount":141,"integrity":"sha512-IQwDRpB/99WKSWK53C+A7RYZImMdJ1f6lJCRavK0ZNJ7h5BznLc5oQURFs0sYLVVlX+SwkB6QE6kEtYQz5W8OA==","signatures":[{"sig":"MEQCIBFhltj3gQ1CTB/yaT7pxo9Me+zF59d1zuJmLltOa5cZAiBw3X9oGowdgRAsDs/j/nDAgB93BVo9+WnNQ1Z5To5hYg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":138704},"main":"./dist/cjs/index.js","types":"./dist/types/index.d.ts","module":"./dist/esm/index.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"dc23e97d2f70daa91906fcc88c4894751e7be56a","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run clean && npm run build:cjs && npm run build:esm && npm run build:types","clean":"rimraf dist","format":"prettier --write \"src/**/*.ts\" \"test/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\" \"test/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run lint && npm run format:check && npm run build && npm test"},"_npmUser":{"name":"sebgregoire","email":"greg@cakemail.com"},"repository":{"url":"git+https://github.com/cakemail/ngapi-ts-auth-middleware.git","type":"git"},"_npmVersion":"11.6.1","description":"Express TypeScript authentication/authorization middleware for Cakemail's API","directories":{},"_nodeVersion":"22.15.0","dependencies":{"axios":"^1.6.7","ioredis":"^5.3.2","jsonwebtoken":"^9.0.2"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","nock":"^13.5.4","eslint":"^8.57.0","rimraf":"^5.0.5","ts-jest":"^29.1.2","prettier":"^3.2.5","supertest":"^6.3.4","typescript":"^5.9.3","@types/jest":"^29.5.12","@types/node":"^20.11.24","ioredis-mock":"^8.13.1","@types/express":"^4.17.21","@types/supertest":"^6.0.2","@types/jsonwebtoken":"^9.0.6","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.3","@typescript-eslint/parser":"^7.1.0","@typescript-eslint/eslint-plugin":"^7.1.0"},"peerDependencies":{"express":"^4.18.0"},"_npmOperationalInternal":{"tmp":"tmp/ngapi-ts-auth-middleware_1.0.0_1765475888165_0.8869144565023312","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@cakemail-org/ngapi-ts-auth-middleware","version":"1.0.1","keywords":["express","middleware","authentication","authorization","jwt","typescript","ngapi","cakemail","redis","bearer-token"],"author":{"name":"Cakemail"},"license":"MIT","_id":"@cakemail-org/ngapi-ts-auth-middleware@1.0.1","maintainers":[{"name":"sebgregoire","email":"greg@cakemail.com"},{"name":"joemingna","email":"jonathan@cakemail.com"},{"name":"labib-cakemail","email":"labib@cakemail.com"},{"name":"hdgatcake","email":"hdg@cakemail.com"},{"name":"zoyth","email":"f@cakemail.com"},{"name":"salar-cakemail","email":"salar@cakemail.com"}],"homepage":"https://github.com/cakemail/ngapi-ts-auth-middleware#readme","bugs":{"url":"https://github.com/cakemail/ngapi-ts-auth-middleware/issues"},"dist":{"shasum":"36fd74404ab1187eda698c409eaf8161a97a9467","tarball":"https://registry.npmjs.org/@cakemail-org/ngapi-ts-auth-middleware/-/ngapi-ts-auth-middleware-1.0.1.tgz","fileCount":141,"integrity":"sha512-2YdTJN0/yXqeeXFL/mKg8PdM2fn2Q+qUbhEaGcjN9x//gcA9yC8FhM1ITjMiA9wr2qA+NTfJOGt6ggbeoZM3OQ==","signatures":[{"sig":"MEUCIDiWZUYpu2cuNxJX6uL3eTI11OPanphBYslmmFfggNrmAiEA2s+93CEDZYkY33TzIM3G1GDh/bLYoh/kBS91u0Kuouk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cakemail-org%2fngapi-ts-auth-middleware@1.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":138714},"main":"./dist/cjs/index.js","types":"./dist/types/index.d.ts","module":"./dist/esm/index.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"7ced9bafd37d271fe72986dd0be4611a3596602b","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run clean && npm run build:cjs && npm run build:esm && npm run build:types","clean":"rimraf dist","format":"prettier --write \"src/**/*.ts\" \"test/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\" \"test/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run lint && npm run format:check && npm run build && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:bd88fa10-b43f-4a86-bb93-10dc6fd299f9"}},"repository":{"url":"git+https://github.com/cakemail/ngapi-ts-auth-middleware.git","type":"git"},"_npmVersion":"11.7.0","description":"Express TypeScript authentication/authorization middleware for Cakemail's API","directories":{},"_nodeVersion":"22.21.1","dependencies":{"axios":"^1.6.7","ioredis":"^5.3.2","jsonwebtoken":"^9.0.2"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","nock":"^13.5.4","eslint":"^8.57.0","rimraf":"^5.0.5","ts-jest":"^29.1.2","prettier":"^3.2.5","supertest":"^6.3.4","typescript":"^5.9.3","@types/jest":"^29.5.12","@types/node":"^20.11.24","ioredis-mock":"^8.13.1","@types/express":"^4.17.21","@types/supertest":"^6.0.2","@types/jsonwebtoken":"^9.0.6","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.3","@typescript-eslint/parser":"^7.1.0","@typescript-eslint/eslint-plugin":"^7.1.0"},"peerDependencies":{"express":"^4.18.0 || ^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/ngapi-ts-auth-middleware_1.0.1_1765489794633_0.04964614936398215","host":"s3://npm-registry-packages-npm-production"}},"1.0.2-beta.1765501646":{"name":"@cakemail-org/ngapi-ts-auth-middleware","version":"1.0.2-beta.1765501646","keywords":["express","middleware","authentication","authorization","jwt","typescript","ngapi","cakemail","redis","bearer-token"],"author":{"name":"Cakemail"},"license":"MIT","_id":"@cakemail-org/ngapi-ts-auth-middleware@1.0.2-beta.1765501646","maintainers":[{"name":"sebgregoire","email":"greg@cakemail.com"},{"name":"joemingna","email":"jonathan@cakemail.com"},{"name":"labib-cakemail","email":"labib@cakemail.com"},{"name":"hdgatcake","email":"hdg@cakemail.com"},{"name":"zoyth","email":"f@cakemail.com"},{"name":"salar-cakemail","email":"salar@cakemail.com"}],"homepage":"https://github.com/cakemail/ngapi-ts-auth-middleware#readme","bugs":{"url":"https://github.com/cakemail/ngapi-ts-auth-middleware/issues"},"dist":{"shasum":"7d51e55a2ca50bc98b0f515a02e011f94189fdc0","tarball":"https://registry.npmjs.org/@cakemail-org/ngapi-ts-auth-middleware/-/ngapi-ts-auth-middleware-1.0.2-beta.1765501646.tgz","fileCount":141,"integrity":"sha512-DFAoDHcVoZy08wijJHvQeqAIOryr+E7Lyomy/UYAAcd+AouObg+SINTsXGqMZ51pEdIrdayuSIlxgyGqpxLnOA==","signatures":[{"sig":"MEYCIQCkXKhRgRst0EF4C6LqOHKsjlSK2LEZ8A4BLutcqbfaZQIhAOsCZHoxqBEeRW0KhSu9Kz4HDXaFl4M6944GHRAyOMZ5","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":138730},"main":"./dist/cjs/index.js","types":"./dist/types/index.d.ts","module":"./dist/esm/index.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"210ebdd4ed67b549c83bfe7b47ebde11a34468c5","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run clean && npm run build:cjs && npm run build:esm && npm run build:types","clean":"rimraf dist","format":"prettier --write \"src/**/*.ts\" \"test/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\" \"test/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run lint && npm run format:check && npm run build && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:bd88fa10-b43f-4a86-bb93-10dc6fd299f9"}},"repository":{"url":"git+https://github.com/cakemail/ngapi-ts-auth-middleware.git","type":"git"},"_npmVersion":"11.7.0","description":"Express TypeScript authentication/authorization middleware for Cakemail's API","directories":{},"_nodeVersion":"22.21.1","dependencies":{"axios":"^1.6.7","ioredis":"^5.3.2","jsonwebtoken":"^9.0.2"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.7.0","nock":"^13.5.4","eslint":"^8.57.0","rimraf":"^5.0.5","ts-jest":"^29.1.2","prettier":"^3.2.5","supertest":"^6.3.4","typescript":"^5.9.3","@types/jest":"^29.5.12","@types/node":"^20.11.24","ioredis-mock":"^8.13.1","@types/express":"^4.17.21","@types/supertest":"^6.0.2","@types/jsonwebtoken":"^9.0.6","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.3","@typescript-eslint/parser":"^7.1.0","@typescript-eslint/eslint-plugin":"^7.1.0"},"peerDependencies":{"express":"^4.18.0 || ^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/ngapi-ts-auth-middleware_1.0.2-beta.1765501646_1765501681260_0.7280924254119403","host":"s3://npm-registry-packages-npm-production"}},"1.0.3-beta.1765898175":{"name":"@cakemail-org/ngapi-ts-auth-middleware","version":"1.0.3-beta.1765898175","keywords":["express","middleware","authentication","authorization","jwt","typescript","ngapi","cakemail","redis","bearer-token"],"author":{"name":"Cakemail"},"license":"MIT","_id":"@cakemail-org/ngapi-ts-auth-middleware@1.0.3-beta.1765898175","maintainers":[{"name":"sebgregoire","email":"greg@cakemail.com"},{"name":"joemingna","email":"jonathan@cakemail.com"},{"name":"labib-cakemail","email":"labib@cakemail.com"},{"name":"hdgatcake","email":"hdg@cakemail.com"},{"name":"zoyth","email":"f@cakemail.com"},{"name":"salar-cakemail","email":"salar@cakemail.com"}],"homepage":"https://github.com/cakemail/ngapi-ts-auth-middleware#readme","bugs":{"url":"https://github.com/cakemail/ngapi-ts-auth-middleware/issues"},"dist":{"shasum":"90eefa5b4f9d352044592e250326846f2e9cfea9","tarball":"https://registry.npmjs.org/@cakemail-org/ngapi-ts-auth-middleware/-/ngapi-ts-auth-middleware-1.0.3-beta.1765898175.tgz","fileCount":147,"integrity":"sha512-f25Z1hFnQIRpH3coKQ25lf8Gwwmv346XUcpfiI+ucUPfgFQBm7PbS7XSbZPj93aqXUqsthHPeeR/bi9dKRk1SA==","signatures":[{"sig":"MEUCIHxJoZxSKunyWvFW/czwjLjJ5c386jrfi+0HMd8WeAXJAiEAiRtWhVBl9PgDWefQ+YIFeKkWWUQ2ycMJTXuwo6e+kKw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cakemail-org%2fngapi-ts-auth-middleware@1.0.3-beta.1765898175","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":140451},"main":"./dist/cjs/index.js","types":"./dist/types/index.d.ts","module":"./dist/esm/index.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"617eb39e2e8ba037ea02e3995c83198ed0518e4c","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run clean && npm run build:cjs && npm run build:esm && npm run build:types","clean":"rimraf dist","format":"prettier --write \"src/**/*.ts\" \"test/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\" \"test/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run lint && npm run format:check && npm run build && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:bd88fa10-b43f-4a86-bb93-10dc6fd299f9"}},"repository":{"url":"git+https://github.com/cakemail/ngapi-ts-auth-middleware.git","type":"git"},"_npmVersion":"11.7.0","description":"Express TypeScript authentication/authorization middleware for Cakemail's API","directories":{},"_nodeVersion":"22.21.1","dependencies":{"axios":"^1.6.7","ioredis":"^5.3.2","jsonwebtoken":"^9.0.2"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^29.7.0","nock":"^13.5.4","eslint":"^8.57.0","rimraf":"^5.0.5","ts-jest":"^29.1.2","prettier":"^3.2.5","supertest":"^6.3.4","typescript":"^5.9.3","@types/jest":"^29.5.12","@types/node":"^20.11.24","ioredis-mock":"^8.13.1","@types/express":"^4.17.21","@types/supertest":"^6.0.2","@types/jsonwebtoken":"^9.0.6","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.3","@typescript-eslint/parser":"^7.1.0","@typescript-eslint/eslint-plugin":"^7.1.0"},"peerDependencies":{"express":"^4.18.0 || ^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/ngapi-ts-auth-middleware_1.0.3-beta.1765898175_1765898202489_0.5383258541301599","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@cakemail-org/ngapi-ts-auth-middleware","version":"1.0.3","keywords":["express","middleware","authentication","authorization","jwt","typescript","ngapi","cakemail","redis","bearer-token"],"author":{"name":"Cakemail"},"license":"MIT","_id":"@cakemail-org/ngapi-ts-auth-middleware@1.0.3","maintainers":[{"name":"sebgregoire","email":"greg@cakemail.com"},{"name":"joemingna","email":"jonathan@cakemail.com"},{"name":"labib-cakemail","email":"labib@cakemail.com"},{"name":"hdgatcake","email":"hdg@cakemail.com"},{"name":"zoyth","email":"f@cakemail.com"},{"name":"salar-cakemail","email":"salar@cakemail.com"}],"homepage":"https://github.com/cakemail/ngapi-ts-auth-middleware#readme","bugs":{"url":"https://github.com/cakemail/ngapi-ts-auth-middleware/issues"},"dist":{"shasum":"135569fe2ebea42b70e4794bd5c0bd67a45ba2f7","tarball":"https://registry.npmjs.org/@cakemail-org/ngapi-ts-auth-middleware/-/ngapi-ts-auth-middleware-1.0.3.tgz","fileCount":147,"integrity":"sha512-xlSwVOtopA6HKvHGauBx6etTeSlWFOUKw2KbEbwFOKgsEiEu1hKF9vzkeK7LNKsBauQOBsV6pexdb6wjuwoqCw==","signatures":[{"sig":"MEYCIQDt5egkzF7zOB3nQrn1371DPiqJuHZmUfWmihjjI34NsgIhAOcBrt279X24biBK7aYOfKDawUtDNGEL2BHgPkG7fyu8","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cakemail-org%2fngapi-ts-auth-middleware@1.0.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":140435},"main":"./dist/cjs/index.js","types":"./dist/types/index.d.ts","module":"./dist/esm/index.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"617eb39e2e8ba037ea02e3995c83198ed0518e4c","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run clean && npm run build:cjs && npm run build:esm && npm run build:types","clean":"rimraf dist","format":"prettier --write \"src/**/*.ts\" \"test/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\" \"test/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run lint && npm run format:check && npm run build && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:bd88fa10-b43f-4a86-bb93-10dc6fd299f9"}},"repository":{"url":"git+https://github.com/cakemail/ngapi-ts-auth-middleware.git","type":"git"},"_npmVersion":"11.7.0","description":"Express TypeScript authentication/authorization middleware for Cakemail's API","directories":{},"_nodeVersion":"22.21.1","dependencies":{"axios":"^1.6.7","ioredis":"^5.3.2","jsonwebtoken":"^9.0.2"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","nock":"^13.5.4","eslint":"^8.57.0","rimraf":"^5.0.5","ts-jest":"^29.1.2","prettier":"^3.2.5","supertest":"^6.3.4","typescript":"^5.9.3","@types/jest":"^29.5.12","@types/node":"^20.11.24","ioredis-mock":"^8.13.1","@types/express":"^4.17.21","@types/supertest":"^6.0.2","@types/jsonwebtoken":"^9.0.6","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.3","@typescript-eslint/parser":"^7.1.0","@typescript-eslint/eslint-plugin":"^7.1.0"},"peerDependencies":{"express":"^4.18.0 || ^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/ngapi-ts-auth-middleware_1.0.3_1765898794776_0.5624404172674737","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2025-12-11T17:58:08.105Z","modified":"2026-09-28T20:08:17.161Z","1.0.0":"2025-12-11T17:58:08.336Z","1.0.1":"2025-12-11T21:49:54.782Z","1.0.2-beta.1765501646":"2025-12-12T01:08:01.445Z","1.0.3-beta.1765898175":"2025-12-16T15:16:42.658Z","1.0.3":"2025-12-16T15:26:34.914Z"},"bugs":{"url":"https://github.com/cakemail/ngapi-ts-auth-middleware/issues"},"author":{"name":"Cakemail"},"license":"MIT","homepage":"https://github.com/cakemail/ngapi-ts-auth-middleware#readme","keywords":["express","middleware","authentication","authorization","jwt","typescript","ngapi","cakemail","redis","bearer-token"],"repository":{"url":"git+https://github.com/cakemail/ngapi-ts-auth-middleware.git","type":"git"},"description":"Express TypeScript authentication/authorization middleware for Cakemail's API","maintainers":[{"email":"greg@cakemail.com","name":"sebgregoire"},{"email":"hdg@cakemail.com","name":"hdgatcake"},{"email":"f@cakemail.com","name":"zoyth"}],"readme":"# Cakemail API Express Auth Middleware\n\nExpress TypeScript authentication/authorization middleware for Cakemail's API. This middleware verifies JWT Bearer tokens, authorizes access to impersonated accounts, and provides user/account data to downstream handlers.\n\n## Features\n\n- JWT Bearer token verification using RSA public key\n- Account impersonation authorization via API calls\n- Automatic user data loading from `/users/self`\n- Redis caching to minimize API calls\n- Fail-open caching (continues without cache if Redis unavailable)\n- Full TypeScript support with strict typing\n- Non-intrusive data storage using Express `res.locals`\n- Dual package support (CommonJS + ESM)\n\n## Installation\n\n```bash\nnpm install @cakemail-org/ngapi-ts-auth-middleware\n```\n\n## Quick Start\n\n```typescript\nimport express from 'express';\nimport { createAuthMiddleware } from '@cakemail-org/ngapi-ts-auth-middleware';\n\nconst app = express();\n\n// Public key is automatically fetched from {API_BASE_URL}/token/pubkey\nconst authMiddleware = createAuthMiddleware({\n  cacheSecret: process.env.CACHE_SECRET, // Required: Secret for HMAC and encryption\n  enableCaching: true,\n  redis: {\n    host: process.env.REDIS_HOST,\n    port: parseInt(process.env.REDIS_PORT || '6379'),\n    db: parseInt(process.env.REDIS_DB || '0'),\n  },\n});\n\n// Apply to all routes\napp.use(authMiddleware);\n\n// Or apply to specific routes\napp.get('/api/resource', authMiddleware, (req, res) => {\n  res.json({\n    userId: res.locals.user.id,\n    userEmail: res.locals.user.email,\n    userAccountId: res.locals.user.account.id,\n    targetAccountId: res.locals.account.id,\n  });\n});\n\napp.listen(3000);\n```\n\n## Configuration\n\n### AuthMiddlewareConfig\n\n| Option | Type | Required | Default | Description |\n|--------|------|----------|---------|-------------|\n| `cacheSecret` | `string` | **Yes** | - | **Required secret for HMAC cache keys and Redis data encryption. Must be a strong, random value. Keep this secret secure!** |\n| `publicKey` | `string | Buffer` | No | Auto-fetched from `{API_BASE_URL}/token/pubkey` | RSA public key for JWT verification (optional, fetched automatically if not provided) |\n| `apiBaseUrl` | `string` | No | `process.env.CAKEMAILAPI_BASE_URL` or `https://api.cakemail.dev` | API base URL |\n| `enableCaching` | `boolean` | No | `true` | Enable Redis caching |\n| `redis` | `RedisConfig` | No | - | Redis connection configuration |\n| `accountIdParams` | `string[]` | No | `['accountId', 'account_id']` | Query parameter names for account ID |\n| `onError` | `(error, req) => void` | No | - | Custom error handler |\n| `jwtOptions` | `JwtOptions` | No | - | JWT verification options |\n\n### RedisConfig\n\n| Option | Type | Required | Default | Description |\n|--------|------|----------|---------|-------------|\n| `host` | `string` | No | `process.env.REDIS_HOST` or `localhost` | Redis host |\n| `port` | `number` | No | `process.env.REDIS_PORT` or `6379` | Redis port |\n| `db` | `number` | No | `process.env.REDIS_DB` or `0` | Redis database number |\n| `password` | `string` | No | `process.env.REDIS_PASSWORD` | Redis password |\n| `keyPrefix` | `string` | No | `ngapi:` | Redis key prefix |\n\n### JwtOptions\n\n| Option | Type | Required | Default | Description |\n|--------|------|----------|---------|-------------|\n| `algorithms` | `string[]` | No | `['RS256']` | Allowed JWT algorithms |\n| `issuer` | `string` | No | `urn:cakemail` | Expected JWT issuer |\n| `clockTolerance` | `number` | No | `10` | Clock tolerance in seconds |\n\n## Environment Variables\n\nThe middleware respects the following environment variables:\n\n- `CACHE_SECRET`: **Required** - Secret for HMAC and Redis encryption (generate with `openssl rand -base64 32`)\n- `CAKEMAILAPI_BASE_URL`: API base URL (default: `https://api.cakemail.dev`)\n- `REDIS_HOST`: Redis host (default: `localhost`)\n- `REDIS_PORT`: Redis port (default: `6379`)\n- `REDIS_DB`: Redis database (default: `0`)\n- `REDIS_PASSWORD`: Redis password (optional)\n\n## Response Locals\n\nThe middleware stores authentication data in `res.locals`, following Express best practices for passing data between middleware:\n\n### `res.locals.user: AuthenticatedUser`\n\nContains the authenticated user's data from `/users/self` and JWT claims:\n\n```typescript\n{\n  id: string;\n  email: string;\n  first_name: string;\n  last_name: string;\n  account: Account;      // User's own account (from JWT)\n  scopes: string[];      // User's scopes\n  user_key: string;      // User's API key\n  // ... other user properties\n}\n```\n\n### `res.locals.account: Account`\n\nContains the target account data:\n- If `?accountId=X` query parameter is present: authorized impersonated account\n- If no query parameter: user's own account (same as `res.locals.user.account`)\n\n```typescript\n{\n  id: string;\n  name: string;\n  lineage: string;\n  status: string;\n  usage_limits: UsageLimits;\n  // ... other account properties\n}\n```\n\n### `res.locals.token: string`\n\nThe raw JWT Bearer token string.\n\n## Data Population Guarantees\n\nThe middleware guarantees the following:\n\n- **`res.locals.account.id`**: Always the **target** account ID (safe to use for operations)\n- **`res.locals.user.account.id`**: Always the **user's own** account ID (never changes with impersonation)\n\nThis ensures downstream handlers always know:\n1. Which account is being operated on (`res.locals.account.id`)\n2. Which user is making the request (`res.locals.user.id`)\n3. Which account the user belongs to (`res.locals.user.account.id`)\n\n## Account Impersonation\n\nWhen a query parameter `accountId` or `account_id` is present, the middleware:\n\n1. Verifies the JWT token\n2. Calls `GET /accounts/:accountId` with the Bearer token\n3. If returns 200: access is authorized, `res.locals.account` is populated with account data\n4. If returns 403/401: throws `AuthorizationError` (403 response)\n\nExample:\n```typescript\n// User with account 1627783 accessing account 999999\nGET /api/resource?accountId=999999\nAuthorization: Bearer <token>\n\n// Result:\n// res.locals.user.account.id = \"1627783\" (user's own account)\n// res.locals.account.id = \"999999\" (target account)\n```\n\n## Caching Strategy\n\nThe middleware caches API responses in Redis to minimize API calls:\n\n### Cache Key Format\n\n```\nngapi:{tokenHash}:{accountId|userId}:{type}\n```\n\n- `tokenHash`: First 16 characters of SHA256(token)\n- `accountId|userId`: Account or user ID\n- `type`: `account` or `user`\n\nExample: `ngapi:a3f2c8d1e5f7:1627783:account`\n\n### TTL Strategy\n\n- Cache keys expire when the JWT token expires\n- Min TTL: 60 seconds\n- Max TTL: 24 hours\n\n### Fail-Open Behavior\n\nIf Redis is unavailable:\n1. Logs warning to console\n2. Continues without caching\n3. Makes API calls on every request\n\nThis ensures authentication/authorization remains functional even if Redis is down (at the cost of performance).\n\n## Error Handling\n\nThe middleware returns the following HTTP error responses:\n\n### 401 Unauthorized\n\n- Missing Authorization header\n- Invalid token format\n- Expired token\n- Invalid token signature\n\nResponse:\n```json\n{\n  \"error\": \"Authentication failed\",\n  \"message\": \"Token has expired\"\n}\n```\n\n### 403 Forbidden\n\n- User does not have access to requested account\n\nResponse:\n```json\n{\n  \"error\": \"Authorization failed\",\n  \"message\": \"Access denied to account 999999\"\n}\n```\n\n### 500 Internal Server Error\n\n- Unexpected errors during authentication/authorization\n\nResponse:\n```json\n{\n  \"error\": \"Internal server error\",\n  \"message\": \"An unexpected error occurred during authentication\"\n}\n```\n\n### Custom Error Handler\n\nYou can provide a custom error handler for logging or monitoring:\n\n```typescript\nconst authMiddleware = createAuthMiddleware({\n  publicKey,\n  onError: (error, req) => {\n    console.error('Auth error:', {\n      error: error.message,\n      path: req.path,\n      method: req.method,\n    });\n  },\n});\n```\n\n## Usage Examples\n\n### Basic Usage\n\n```typescript\nimport express from 'express';\nimport { createAuthMiddleware } from '@cakemail-org/ngapi-ts-auth-middleware';\n\nconst app = express();\n\n// Public key is automatically fetched from the API\nconst authMiddleware = createAuthMiddleware({\n  // Optional: specify API base URL (defaults to CAKEMAILAPI_BASE_URL env var)\n  // apiBaseUrl: 'https://api.cakemail.dev',\n});\n\napp.use(authMiddleware);\n\napp.get('/api/campaigns', (req, res) => {\n  // Access authenticated user\n  console.log(`User ${res.locals.user.email} accessing account ${res.locals.account.id}`);\n\n  res.json({ campaigns: [] });\n});\n\napp.listen(3000);\n```\n\n### With Redis Caching\n\n```typescript\nconst authMiddleware = createAuthMiddleware({\n  enableCaching: true,\n  redis: {\n    host: process.env.REDIS_HOST || 'localhost',\n    port: parseInt(process.env.REDIS_PORT || '6379'),\n    db: parseInt(process.env.REDIS_DB || '0'),\n    password: process.env.REDIS_PASSWORD,\n  },\n});\n```\n\n### With Custom Configuration\n\n```typescript\nconst authMiddleware = createAuthMiddleware({\n  // Public key is auto-fetched, but you can provide it manually if needed\n  // publicKey: fs.readFileSync('./pubkey.pem'),\n\n  apiBaseUrl: process.env.CAKEMAILAPI_BASE_URL,\n  enableCaching: true,\n  accountIdParams: ['accountId', 'account_id', 'aid'],\n  redis: {\n    host: process.env.REDIS_HOST,\n    port: parseInt(process.env.REDIS_PORT || '6379'),\n    keyPrefix: 'myapp:',\n  },\n  onError: (error, req) => {\n    console.error('Auth error:', error, 'Path:', req.path);\n  },\n  jwtOptions: {\n    algorithms: ['RS256'],\n    issuer: 'urn:cakemail',\n    clockTolerance: 30,\n  },\n});\n```\n\n### Route-Specific Middleware\n\n```typescript\nimport { createAuthMiddleware } from '@cakemail-org/ngapi-ts-auth-middleware';\n\nconst authMiddleware = createAuthMiddleware({});\n\n// Public routes (no auth)\napp.get('/health', (req, res) => {\n  res.json({ status: 'ok' });\n});\n\n// Protected routes\napp.get('/api/*', authMiddleware);\n\napp.get('/api/campaigns', (req, res) => {\n  // res.locals.user and res.locals.account are guaranteed to exist here\n  res.json({ campaigns: [] });\n});\n```\n\n## TypeScript Support\n\nThe middleware is written in TypeScript with full type definitions. It automatically augments `Express.Locals` so TypeScript knows about `res.locals.user`, `res.locals.account`, and `res.locals.token` without any manual type declarations.\n\n### Automatic Type Augmentation\n\nWhen you import this package, `Express.Locals` is automatically augmented:\n\n```typescript\nimport express from 'express';\nimport { createAuthMiddleware } from '@cakemail/ngapi-ts-auth-middleware';\n\nconst app = express();\nconst authMiddleware = createAuthMiddleware({ cacheSecret: process.env.CACHE_SECRET });\n\napp.get('/api/resource', authMiddleware, (req, res) => {\n  // TypeScript automatically knows about these types:\n  // - res.locals.user is AuthenticatedUser | undefined\n  // - res.locals.account is Account | undefined\n  // - res.locals.token is string | undefined\n\n  if (!res.locals.user || !res.locals.account) {\n    return res.status(500).json({ error: 'Authentication data missing' });\n  }\n\n  res.json({\n    userId: res.locals.user.id,\n    userEmail: res.locals.user.email,\n    accountId: res.locals.account.id,\n  });\n});\n```\n\nNo manual type casting or custom type declarations required.\n\n### Importing Types\n\nTypes can be imported directly from the package for use in your application:\n\n```typescript\nimport {\n  AuthMiddlewareConfig,\n  AuthenticatedUser,\n  Account,\n  User,\n  JwtPayload,\n  AuthenticationError,\n  AuthorizationError,\n} from '@cakemail-org/ngapi-ts-auth-middleware';\n```\n\n## Testing\n\nRun tests:\n\n```bash\nnpm test\n```\n\nRun tests with coverage:\n\n```bash\nnpm run test:coverage\n```\n\n## Security Considerations\n\n1. **HTTPS Only**: Always use HTTPS in production\n2. **Public Key Security**: Never expose or commit private keys\n3. **Token Expiration**: Tokens should have reasonable expiration times\n4. **Cache Key Hashing**: Tokens are hashed in cache keys to prevent leakage\n5. **Error Messages**: Error messages don't leak sensitive token information\n\n## Performance\n\n- **Redis Caching**: Reduces API calls by 90%+ for repeated requests\n- **Connection Pooling**: ioredis and axios handle connection pooling automatically\n- **Lazy Initialization**: Services initialize only when first needed\n- **Async Operations**: User and account data fetched in parallel when possible\n\n## License\n\nMIT\n\n## Contributing\n\nContributions are welcome! Please submit pull requests to the [GitHub repository](https://github.com/cakemail/ngapi-ts-auth-middleware).\n\n## Support\n\nFor issues or questions, please file an issue on [GitHub](https://github.com/cakemail/ngapi-ts-auth-middleware/issues).\n","readmeFilename":"README.md"}