{"_id":"@emdzej/keycloak-api-keys-express","name":"@emdzej/keycloak-api-keys-express","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@emdzej/keycloak-api-keys-express","version":"0.1.0","publishConfig":{"access":"public"},"type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"}},"scripts":{"build":"tsup src/index.ts --format esm --dts","test":"vitest run","typecheck":"tsc --noEmit"},"peerDependencies":{"express":"^4.18.0 || ^5.0.0"},"devDependencies":{"@types/express":"^4.17.21","express":"^4.21.0","tsup":"^8.0.0","typescript":"^5.7.0","vitest":"^3.0.0"},"license":"Apache-2.0","repository":{"type":"git","url":"git+https://github.com/emdzej/keycloak-api-keys.git","directory":"packages/express"},"homepage":"https://github.com/emdzej/keycloak-api-keys#readme","bugs":{"url":"https://github.com/emdzej/keycloak-api-keys/issues"},"author":{"name":"Michał Jaskólski"},"gitHead":"4424e7c221030d05b8db510df70a03c9640523e3","_id":"@emdzej/keycloak-api-keys-express@0.1.0","description":"Express.js middleware for validating Keycloak API keys and attaching decoded auth info to the request.","_nodeVersion":"22.22.0","_npmVersion":"11.11.0","dist":{"integrity":"sha512-4Oh15rUHULMVRWrC1jabBO2vuIkBnV+st8oTQXadLqcH3Lp7dXQ42AmF3M8c53W7EqBDFWP9lSZwAgz3Ceobkg==","shasum":"91fe0fe87adcd5aeba127f1adc493f05e513079a","tarball":"https://registry.npmjs.org/@emdzej/keycloak-api-keys-express/-/keycloak-api-keys-express-0.1.0.tgz","fileCount":12,"unpackedSize":16708,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDBg6hvaKkxh0JX0zSArC45gTVMldfnGU9fQR3THcjcBgIgRaNrHgU5V0PT2wxdA1szt5AQvu1bqX5Dj66tahI1WJQ="}]},"_npmUser":{"name":"emdzej","email":"michal@jaskolski.pro"},"directories":{},"maintainers":[{"name":"emdzej","email":"michal@jaskolski.pro"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/keycloak-api-keys-express_0.1.0_1774018999727_0.5355579692248615"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-20T15:03:19.655Z","0.1.0":"2026-03-20T15:03:19.870Z","modified":"2026-03-20T15:03:20.094Z"},"maintainers":[{"name":"emdzej","email":"michal@jaskolski.pro"}],"description":"Express.js middleware for validating Keycloak API keys and attaching decoded auth info to the request.","homepage":"https://github.com/emdzej/keycloak-api-keys#readme","repository":{"type":"git","url":"git+https://github.com/emdzej/keycloak-api-keys.git","directory":"packages/express"},"author":{"name":"Michał Jaskólski"},"bugs":{"url":"https://github.com/emdzej/keycloak-api-keys/issues"},"license":"Apache-2.0","readme":"# @emdzej/keycloak-api-keys-express\n\nExpress.js middleware for validating Keycloak API keys and attaching decoded auth info to the request.\n\n## Installation\n\n```bash\npnpm add @emdzej/keycloak-api-keys-express express\n```\n\n## Usage\n\n```ts\nimport express from 'express';\nimport { keycloakApiKey } from '@emdzej/keycloak-api-keys-express';\n\nconst app = express();\n\napp.use(\n  '/api',\n  keycloakApiKey({\n    realm: 'my-realm',\n    serverUrl: 'https://keycloak.example.com',\n    clientId: 'my-app',\n    clientSecret: process.env.CLIENT_SECRET\n  })\n);\n\napp.get('/api/data', (req, res) => {\n  const userId = req.auth?.sub;\n  const roles = req.auth?.realm_access?.roles;\n  res.json({ userId, roles });\n});\n```\n\n## Configuration\n\n```ts\nkeycloakApiKey({\n  serverUrl: 'https://keycloak.example.com',\n  realm: 'my-realm',\n  clientId: 'my-app',\n  clientSecret: process.env.CLIENT_SECRET,\n  headerName: 'X-API-Key', // optional, default: X-API-Key\n  cacheTtl: 300 // optional, seconds\n});\n```\n\n### Options\n\n- `serverUrl` (string, required) — Keycloak base URL.\n- `realm` (string, required) — Keycloak realm name.\n- `clientId` (string, required) — OAuth client ID.\n- `clientSecret` (string, optional) — Required for confidential clients.\n- `headerName` (string, optional) — API key header (default `X-API-Key`).\n- `cacheTtl` (number, optional) — Cache TTL in seconds (default `300`).\n\n## Behavior\n\n- **Missing API key** → `401 Unauthorized`\n- **Invalid API key** → `401 Unauthorized`\n- **Rate limited** → `429 Too Many Requests` (rate limit headers forwarded)\n\n## TypeScript\n\nThe middleware augments `Express.Request` with `auth`:\n\n```ts\ninterface AuthInfo {\n  sub: string;\n  azp: string;\n  api_key_id: string;\n  realm_access?: { roles: string[] };\n  scope?: string;\n  [key: string]: unknown;\n}\n```\n","readmeFilename":"README.md","_rev":"1-7518d15d67526e111cb6dcaffd960a97"}