{"_id":"@aaaahoang123/nest-keycloak-connect","_rev":"5-fd15f20901e47b95bd3cddc704795247","name":"@aaaahoang123/nest-keycloak-connect","dist-tags":{"latest":"1.9.5","beta1":"1.9.5-beta1","beta2":"1.9.5-beta2"},"versions":{"1.9.2":{"name":"@aaaahoang123/nest-keycloak-connect","version":"1.9.2","description":"keycloak-nodejs-connect module for Nest","author":{"name":"John Joshua Ferrer","email":"johnjoshuaferrer@disroot.org"},"license":"MIT","scripts":{"start:dev":"tsc -w","clean":"rimraf dist","build":"tsc","build:copy":"cpr README.md dist/README.md && cpr LICENSE dist/LICENSE && cpr package.json dist/package.json","release":"release-it","release:alpha":"release-it --preReleaseId=alpha --npm.tag=next --github.preRelease","format":"prettier --write \"src/**/*.ts\"","lint":"eslint ./src --ext .ts"},"keywords":["nestjs","keycloak","typescript"],"repository":{"type":"git","url":"git+https://github.com/aaaahoang123/nest-keycloak-connect.git"},"bugs":{"url":"https://github.com/aaaahoang123/nest-keycloak-connect/issues"},"peerDependencies":{"@nestjs/common":">=6.0.0 <10.0.0","@nestjs/core":">=6.0.0 <10.0.0","@nestjs/graphql":">=6","keycloak-connect":">=10.0.0 <21.0.0"},"devDependencies":{"@nestjs/common":"^9.0.0","@nestjs/core":"^9.0.0","@nestjs/graphql":"^10.0.0","@types/express":"^4.17.13","@types/node":"^18.0.3","@typescript-eslint/eslint-plugin":"5.30.6","@typescript-eslint/parser":"5.30.6","class-transformer":"0.5.1","class-validator":"0.13.2","cpr":"3.0.1","eslint":"8.19.0","eslint-config-prettier":"8.5.0","eslint-plugin-prettier":"3.4.0","graphql":">=15.8.0 <16.0.0 || >=16.0.0 <17.0.0","keycloak-connect":"18.0.2","prettier":"1.19.1","reflect-metadata":"0.1.13","release-it":"14.13.1","rimraf":"3.0.2","rxjs":"7.5.6","ts-node":"10.8.2","typescript":"4.7.4"},"peerDependenciesMeta":{"@nestjs/graphql":{"optional":true}},"gitHead":"7539d690326d0a28f9a450595474e0372927a03d","homepage":"https://github.com/aaaahoang123/nest-keycloak-connect#readme","_id":"@aaaahoang123/nest-keycloak-connect@1.9.2","_nodeVersion":"18.12.0","_npmVersion":"8.19.2","dist":{"integrity":"sha512-lcwpJPkcg62q06HpLmSYf0RrMOog+ZDHv1/rS8eviKzyOwvqnf8UDgqPlU2jAz5j3dfH8uZC4GY0UHCz7jzOQg==","shasum":"589efda1739c0e17c4ec3627c29ce35af3bc4dc6","tarball":"https://registry.npmjs.org/@aaaahoang123/nest-keycloak-connect/-/nest-keycloak-connect-1.9.2.tgz","fileCount":55,"unpackedSize":367001,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDFIM2oE0PKqM/uuTnqJku9zwFp+X52rgnKLb9kcQYq9AiAmVAT4sd8Ynqj4yYFFSN3A7FTlqcbxWif+DTaPmCqIMg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkAIQnACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqCeA/+L+z1Q/3hxs6rcYD0FR2pL5fxPh95Y236frNbsWa2V+dgAJfP\r\nyGsj06HVQiVye3/k/rv+pPOFUd0Vz/Y+LIlTKk1Mphco/Eub5xdrKCa9Mp0B\r\nG0ugmxirxurLWwzBpnDRocXCU89H8MhV6shs9zESCVFleu+2z64hPuQrt8dE\r\n9ILQiobh1/5Vz1tUaOJoIrX+Sn9kjkrEqQWyoMXYkn6TzMdnYI3FnwKxxEEq\r\nEOlGLtgvpHKZnjbDr8ykkmvs1BLOVWEp3rxKdNnrj529RapBQczxdG/LZJw/\r\nM75XMwIL+Ao+mPu2zhOxqEO7sFl5cDg5BLYQhDq53cLH4juV6EcAflXPZYAA\r\neTPMv9Ezt+osx73Uoefl/dkVDysCn/nEKOdFkTFTeh3PxkE5YqTzAIkba4cO\r\n0wLsxEUADUdip3Ha1OgLAvd/LdSfc/Bby35HJTO/PHjOljNh5FzH+HhkPdXr\r\n/oVFMHV1MNj2bpbOMsGTmOnQSb4+4lxyjTtdztnxpzF+fUaGeakqsatW6YWw\r\nGR9QaJF1m3gX/WBubpqgdpVhbH+MAI52JVqvFmVQ0V85afJzKaBO7FHKhiNl\r\nNVU+nvVXsh3Gjt2+stFyzuhu96V7tGMSZwqPBZnGnCxggR6++dsr3bq7kzWS\r\nOU/KYs24p3OZHoPGvU3k+7WwKGaB2RlWH3I=\r\n=EqQX\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"aaaahoang123","email":"hoangdo.2194@gmail.com"},"directories":{},"maintainers":[{"name":"aaaahoang123","email":"hoangdo.2194@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/nest-keycloak-connect_1.9.2_1677755430981_0.18157036253385206"},"_hasShrinkwrap":false},"1.9.3":{"name":"@aaaahoang123/nest-keycloak-connect","version":"1.9.3","description":"keycloak-nodejs-connect module for Nest","author":{"name":"John Joshua Ferrer","email":"johnjoshuaferrer@disroot.org"},"license":"MIT","scripts":{"start:dev":"tsc -w","clean":"rimraf dist","build":"tsc","build:copy":"cpr README.md dist/README.md && cpr LICENSE dist/LICENSE && cpr package.json dist/package.json","release":"release-it","release:alpha":"release-it --preReleaseId=alpha --npm.tag=next --github.preRelease","format":"prettier --write \"src/**/*.ts\"","lint":"eslint ./src --ext .ts"},"keywords":["nestjs","keycloak","typescript"],"repository":{"type":"git","url":"git+https://github.com/aaaahoang123/nest-keycloak-connect.git"},"bugs":{"url":"https://github.com/aaaahoang123/nest-keycloak-connect/issues"},"peerDependencies":{"@nestjs/common":">=6.0.0 <10.0.0","@nestjs/core":">=6.0.0 <10.0.0","@nestjs/graphql":">=6","keycloak-connect":">=10.0.0 <21.0.0"},"devDependencies":{"@nestjs/common":"^9.0.0","@nestjs/core":"^9.0.0","@nestjs/graphql":"^10.0.0","@types/express":"^4.17.13","@types/node":"^18.0.3","@typescript-eslint/eslint-plugin":"5.30.6","@typescript-eslint/parser":"5.30.6","class-transformer":"0.5.1","class-validator":"0.13.2","cpr":"3.0.1","eslint":"8.19.0","eslint-config-prettier":"8.5.0","eslint-plugin-prettier":"3.4.0","graphql":">=15.8.0 <16.0.0 || >=16.0.0 <17.0.0","keycloak-connect":"18.0.2","prettier":"1.19.1","reflect-metadata":"0.1.13","release-it":"14.13.1","rimraf":"3.0.2","rxjs":"7.5.6","ts-node":"10.8.2","typescript":"4.7.4"},"peerDependenciesMeta":{"@nestjs/graphql":{"optional":true}},"types":"./index.d.ts","gitHead":"a456b8446396a81ffd0a97c26077f1ce3a269459","homepage":"https://github.com/aaaahoang123/nest-keycloak-connect#readme","_id":"@aaaahoang123/nest-keycloak-connect@1.9.3","_nodeVersion":"18.12.0","_npmVersion":"8.19.2","dist":{"integrity":"sha512-A/QJ4fm5xueMRIhVa3G7QAoMSMLpWQdfDZAvhVAFfCG3qEIa4nlXDr/9nNovEV308FbE3YhqAsp+GhbKrCmBzg==","shasum":"ea8cfc6444fced1955387054c3473dfd0420ea3e","tarball":"https://registry.npmjs.org/@aaaahoang123/nest-keycloak-connect/-/nest-keycloak-connect-1.9.3.tgz","fileCount":51,"unpackedSize":82543,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHr3jCmni4zP5Ux02UVILg17ZSXNLTFxGhh1pDe14+LSAiBEt+XTjZDYtoCXZL9rO8WltE68lrsR06Xn60hW8bcXug=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkBY3JACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrKeA//StGL/ESQQeZ5F+njDBdO7U1o7fjd+8u2Vr2l33XL+RzvicJr\r\nGVX+eTeaO5cBe2NPJVYOCBPthzbqflXd/GOFJmElMLnMpCMG1poDZBOyoj/v\r\n9fzhNWI3SYjPh2yzdZkc8BotG1ZBpRfv0mQ9lmfQuEvg0HmEwLZh9qUwgZz9\r\nYVxm2ihigoSOyz5y1mbyYxkPtEkUggk2xrvKaN0W2XVeq6B0MnqISrkB7wY9\r\n/QQ0Nc1UzqchCdalI06GUinkmZEPdsF45lIR8leJvzNTzr/31ADoXCenU4cV\r\nLJnOnox/bFQqjdEM5MFIou5YsGYQ6pP5sc+3t5NZF/vGyeAb88+ItVHIpFB5\r\nEBG6Ejho+KZjypW4p5lG/K0WAYl532BlA2gxmSWz8k8mayYPjQFrvlqPmjQV\r\ndxJiz2OHMivjT+lrr/vGGXgg+5rKilqfqh2syM3Ylaa/MYTmECoOp0GEuAo7\r\nVv9fdaDIrRdOKJOzJvbMRKVYQud+abTeWHmK8qsvMtkRCU2Zomq7IBdE2mIH\r\ncbMT9colJNGpQlSqH2dvcx/zFJXq0Lj+mZ0nlmiTRZBk7gc7MkgUhck2h2X7\r\nLYBciqlhLTRuXdoXBklXlTnYsYe6Ue0PeyyMOOyLwfNV0mmBplilxmWuDIbt\r\n+97HKQAORCMU+teVsWZ5vUBIRoRB/Wf7ghE=\r\n=75ds\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"aaaahoang123","email":"hoangdo.2194@gmail.com"},"directories":{},"maintainers":[{"name":"aaaahoang123","email":"hoangdo.2194@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/nest-keycloak-connect_1.9.3_1678085577533_0.3289828822505172"},"_hasShrinkwrap":false},"1.9.4":{"name":"@aaaahoang123/nest-keycloak-connect","version":"1.9.4","description":"keycloak-nodejs-connect module for Nest","author":{"name":"John Joshua Ferrer","email":"johnjoshuaferrer@disroot.org"},"license":"MIT","scripts":{"start:dev":"tsc -w","clean":"rimraf dist","build":"tsc","build:copy":"cpr README.md dist/README.md && cpr LICENSE dist/LICENSE && cpr package.json dist/package.json","release":"release-it","release:alpha":"release-it --preReleaseId=alpha --npm.tag=next --github.preRelease","format":"prettier --write \"src/**/*.ts\"","lint":"eslint ./src --ext .ts"},"keywords":["nestjs","keycloak","typescript"],"repository":{"type":"git","url":"git+https://github.com/aaaahoang123/nest-keycloak-connect.git"},"bugs":{"url":"https://github.com/aaaahoang123/nest-keycloak-connect/issues"},"peerDependencies":{"@nestjs/common":">=6.0.0 <10.0.0","@nestjs/core":">=6.0.0 <10.0.0","@nestjs/graphql":">=6","keycloak-connect":">=10.0.0 <21.0.0"},"devDependencies":{"@nestjs/common":"^9.0.0","@nestjs/core":"^9.0.0","@nestjs/graphql":"^10.0.0","@types/express":"^4.17.13","@types/node":"^18.0.3","@typescript-eslint/eslint-plugin":"5.30.6","@typescript-eslint/parser":"5.30.6","class-transformer":"0.5.1","class-validator":"0.13.2","cpr":"3.0.1","eslint":"8.19.0","eslint-config-prettier":"8.5.0","eslint-plugin-prettier":"3.4.0","graphql":">=15.8.0 <16.0.0 || >=16.0.0 <17.0.0","keycloak-connect":"18.0.2","prettier":"1.19.1","reflect-metadata":"0.1.13","release-it":"14.13.1","rimraf":"3.0.2","rxjs":"7.5.6","ts-node":"10.8.2","typescript":"4.7.4"},"peerDependenciesMeta":{"@nestjs/graphql":{"optional":true}},"types":"./index.d.ts","gitHead":"a3a78c5f1d9fbef43d873f7b1d19cb1f7078e450","homepage":"https://github.com/aaaahoang123/nest-keycloak-connect#readme","_id":"@aaaahoang123/nest-keycloak-connect@1.9.4","_nodeVersion":"18.12.0","_npmVersion":"8.19.2","dist":{"integrity":"sha512-LtWLcRykgBPFLcii0aoqEGxttbDskR4DS61giAdEkiTXAGPKvf11VlT8AZqkk0aA8Wqf4ccKc0My53PO9iC+Rg==","shasum":"fc3ae19dae291416f07b56e1e847cc44c85a57c7","tarball":"https://registry.npmjs.org/@aaaahoang123/nest-keycloak-connect/-/nest-keycloak-connect-1.9.4.tgz","fileCount":51,"unpackedSize":82543,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICf2keZOPiQDLeHwAYw4fIeJt+iYZqEBPjWM2QucgM9FAiEArSi8FVDKT/dDjlAlWgOfUUbZe/GpxG1gnKwedIcEvoo="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkBaMxACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqpIA//b9/jRhr/txHrQYknuaXHwRpE6pLiR46c6S5Ihf+A2tZBMRzo\r\nM6QGnE75PqNydI1y7dYHANGvd36zS6aLm/NpyzXdjQAStPjUJFdBOZu4RONT\r\nOqN/8VzTue6LEuUX341AucHY73mrlK5SWemmCBtwGDcKW3/zMd/RcomvgPYb\r\nOLSE6mKsC/HB5KaEQXukb1tByDm2fjEe5DTFzsiY0LOrsMhbWxtSej6ImT0+\r\nZn6QdgEZ/5NLsPmmB0aLJi2gNS43Rig+pbGsA/CELDJuwaj8t02LEq3NZD2k\r\nTOC9kNQEIsHiMbGAejNz/Ej79sCfZi87f5v/4NymWwqM+DnGf5ARjzFR1sq2\r\nRIpxTnFNReclRCPVPApbp+H1trf+a9XBCmgwgQV8foUtoPmp+JWfLo2Qy9cT\r\nymZ3H+YhUphQRhcDoAHHpJn4VYFcwWrKQ46dE7jE6cEKj+LlPsbGsFhTjiif\r\n9A+l0lh9eNI0tGCuHdf8rXveUqXb86kZo/+w7c3PQzkZXdaYbu3EOYIr85Ys\r\nx/JrR7WkX/2Md4Hq10Mki4SU6rUqJs4LT2v19vYe1Q+apQ5RW1JvE9Sj70m4\r\nyS9ClxEQ8GzCoU6lcccBjtTubt18Cg7WMU4TaqxhTOlrEecCHEr5Vp5NR5QT\r\nJjyp6H+3P9R0iGZFWhaLx/DlKLXlZDj5O/Y=\r\n=ZGYG\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"aaaahoang123","email":"hoangdo.2194@gmail.com"},"directories":{},"maintainers":[{"name":"aaaahoang123","email":"hoangdo.2194@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/nest-keycloak-connect_1.9.4_1678091057628_0.1402006064204524"},"_hasShrinkwrap":false},"1.9.5-beta1":{"name":"@aaaahoang123/nest-keycloak-connect","version":"1.9.5-beta1","description":"keycloak-nodejs-connect module for Nest","author":{"name":"John Joshua Ferrer","email":"johnjoshuaferrer@disroot.org"},"license":"MIT","scripts":{"start:dev":"tsc -w","clean":"rimraf dist","build":"tsc","build:copy":"cpr README.md dist/README.md && cpr LICENSE dist/LICENSE && cpr package.json dist/package.json","release":"release-it","release:alpha":"release-it --preReleaseId=alpha --npm.tag=next --github.preRelease","format":"prettier --write \"src/**/*.ts\"","lint":"eslint ./src --ext .ts"},"keywords":["nestjs","keycloak","typescript"],"repository":{"type":"git","url":"git+https://github.com/aaaahoang123/nest-keycloak-connect.git"},"bugs":{"url":"https://github.com/aaaahoang123/nest-keycloak-connect/issues"},"peerDependencies":{"@nestjs/common":">=6.0.0 <10.0.0","@nestjs/core":">=6.0.0 <10.0.0","@nestjs/graphql":">=6","keycloak-connect":">=10.0.0 <21.0.0"},"devDependencies":{"@nestjs/common":"^9.0.0","@nestjs/core":"^9.0.0","@nestjs/graphql":"^10.0.0","@types/express":"^4.17.13","@types/node":"^18.0.3","@typescript-eslint/eslint-plugin":"5.30.6","@typescript-eslint/parser":"5.30.6","class-transformer":"0.5.1","class-validator":"0.13.2","cpr":"3.0.1","eslint":"8.19.0","eslint-config-prettier":"8.5.0","eslint-plugin-prettier":"3.4.0","graphql":">=15.8.0 <16.0.0 || >=16.0.0 <17.0.0","keycloak-connect":"18.0.2","prettier":"1.19.1","reflect-metadata":"0.1.13","release-it":"14.13.1","rimraf":"3.0.2","rxjs":"7.5.6","ts-node":"10.8.2","typescript":"4.7.4"},"peerDependenciesMeta":{"@nestjs/graphql":{"optional":true}},"types":"./index.d.ts","readme":"# Nest Keycloak Connect\r\n\r\n![GitHub](https://img.shields.io/github/license/ferrerojosh/nest-keycloak-connect)\r\n![npm](https://img.shields.io/npm/v/nest-keycloak-connect)\r\n![npm peer dependency version](https://img.shields.io/npm/dependency-version/nest-keycloak-connect/peer/@nestjs/common)\r\n![npm peer dependency version](https://img.shields.io/npm/dependency-version/nest-keycloak-connect/peer/keycloak-connect)\r\n[![Verify Build](https://github.com/ferrerojosh/nest-keycloak-connect/actions/workflows/verify-build.yml/badge.svg?branch=master)](https://github.com/ferrerojosh/nest-keycloak-connect/actions/workflows/verify-build.yml)\r\n![npm](https://img.shields.io/npm/dw/nest-keycloak-connect)\r\n![npm](https://img.shields.io/npm/dt/nest-keycloak-connect)\r\n\r\n[![Support via PayPal](https://cdn.rawgit.com/twolfson/paypal-github-button/1.0.0/dist/button.svg)](https://www.paypal.me/ferrerojosh/)\r\n\r\n> An adapter for [keycloak-nodejs-connect](https://github.com/keycloak/keycloak-nodejs-connect).\r\n\r\n## Features\r\n\r\n- Protect your resources using [Keycloak's Authorization Services](https://www.keycloak.org/docs/latest/authorization_services/).\r\n- Simply add `@Resource`, `@Scopes`, or `@Roles` in your controllers and you're good to go.\r\n- Compatible with [Fastify](https://github.com/fastify/fastify) platform.\r\n\r\n## Installation\r\n\r\n### Yarn\r\n\r\n```bash\r\nyarn add @aaaahoang123/nest-keycloak-connect keycloak-connect\r\n```\r\n\r\n### NPM\r\n\r\n```bash\r\nnpm install @aaaahoang123/nest-keycloak-connect keycloak-connect --save\r\n```\r\n\r\n## Getting Started\r\n\r\n### Module registration\r\n\r\nRegistering the module:\r\n```typescript\r\nKeycloakConnectModule.register({\r\n  authServerUrl: 'http://localhost:8080', // might be http://localhost:8080/auth for older keycloak versions\r\n  realm: 'master',\r\n  clientId: 'my-nestjs-app',\r\n  secret: 'secret',   \r\n  policyEnforcement: PolicyEnforcementMode.PERMISSIVE, // optional\r\n  tokenValidation: TokenValidation.ONLINE, // optional\r\n})\r\n```\r\n\r\nAsync registration is also available:\r\n```typescript\r\nKeycloakConnectModule.registerAsync({\r\n  useExisting: KeycloakConfigService,\r\n  imports: [ConfigModule]\r\n})\r\n```\r\n\r\n#### KeycloakConfigService\r\n```typescript\r\nimport { Injectable } from '@nestjs/common';\r\nimport { KeycloakConnectOptions, KeycloakConnectOptionsFactory, PolicyEnforcementMode, TokenValidation } from 'nest-keycloak-connect';\r\n\r\n@Injectable()\r\nexport class KeycloakConfigService implements KeycloakConnectOptionsFactory {\r\n\r\n  createKeycloakConnectOptions(): KeycloakConnectOptions {\r\n    return {\r\n      authServerUrl: 'http://localhost:8080', // might be http://localhost:8080/auth for older keycloak versions\r\n      realm: 'master',\r\n      clientId: 'my-nestjs-app',\r\n      secret: 'secret',\r\n      policyEnforcement: PolicyEnforcementMode.PERMISSIVE,\r\n      tokenValidation: TokenValidation.ONLINE,\r\n    };\r\n  } \r\n}\r\n```\r\n\r\nYou can also register by just providing the `keycloak.json` path and an optional module configuration:\r\n\r\n```typescript\r\nKeycloakConnectModule.register(`./keycloak.json`, {\r\n  policyEnforcement: PolicyEnforcementMode.PERMISSIVE,\r\n  tokenValidation: TokenValidation.ONLINE,\r\n})\r\n```\r\n\r\n### Guards\r\n\r\nRegister any of the guards either globally, or scoped in your controller.\r\n\r\n#### Global registration using APP_GUARD token\r\n***NOTE: These are in order, see https://docs.nestjs.com/guards#binding-guards for more information.***\r\n```typescript\r\nproviders: [\r\n  {\r\n    provide: APP_GUARD,     \r\n    useClass: AuthGuard,\r\n  },\r\n  {\r\n    provide: APP_GUARD,\r\n    useClass: ResourceGuard,\r\n  },\r\n  {\r\n    provide: APP_GUARD,\r\n    useClass: RoleGuard,\r\n  },\r\n]\r\n```\r\n#### Scoped registration\r\n```typescript\r\n@Controller('cats')\r\n@UseGuards(AuthGuard, ResourceGuard)\r\nexport class CatsController {}\r\n```\r\n\r\n## What does these providers do ?\r\n\r\n### AuthGuard\r\nAdds an authentication guard, you can also have it scoped if you like (using regular `@UseGuards(AuthGuard)` in your controllers). By default, it will throw a 401 unauthorized when it is unable to verify the JWT token or `Bearer` header is missing.\r\n\r\n### ResourceGuard\r\nAdds a resource guard, which is permissive by default (can be configured see [options](#nest-keycloak-options)). Only controllers annotated with `@Resource` and methods with `@Scopes` are handled by this guard.\r\n\r\n***NOTE: This guard is not necessary if you are using role-based authorization exclusively. You can use role guard exclusively for that.***\r\n\r\n### RoleGuard\r\nAdds a role guard, **can only be used in conjunction with resource guard when enforcement policy is PERMISSIVE**, unless you only use role guard exclusively.\r\nPermissive by default. Used by controller methods annotated with `@Roles` (matching can be configured)\r\n\r\n## Configuring controllers\r\n\r\nIn your controllers, simply do:\r\n\r\n```typescript\r\nimport { Resource, Roles, Scopes, Public, RoleMatchingMode } from 'nest-keycloak-connect';\r\nimport { Controller, Get, Delete, Put, Post, Param } from '@nestjs/common';\r\nimport { Product } from './product';\r\nimport { ProductService } from './product.service';\r\n\r\n@Controller()\r\n@Resource(Product.name)\r\nexport class ProductController {\r\n  constructor(private service: ProductService) {}\r\n\r\n  @Get()\r\n  @Public()\r\n  async findAll() {\r\n    return await this.service.findAll();\r\n  }\r\n\r\n  @Get()\r\n  @Roles({ roles: ['admin', 'other'] })\r\n  async findAllBarcodes() {\r\n    return await this.service.findAllBarcodes();\r\n  }\r\n\r\n  @Get(':code')\r\n  @Scopes('View')\r\n  async findByCode(@Param('code') code: string) {\r\n    return await this.service.findByCode(code);\r\n  }\r\n\r\n  @Post()\r\n  @Scopes('Create')\r\n  async create(@Body() product: Product) {\r\n    return await this.service.create(product);\r\n  }\r\n\r\n  @Delete(':code')\r\n  @Scopes('Delete')\r\n  @Roles({ roles: ['admin', 'realm:sysadmin'], mode: RoleMatchingMode.ALL })\r\n  async deleteByCode(@Param('code') code: string) {\r\n    return await this.service.deleteByCode(code);\r\n  }\r\n\r\n  @Put(':code')\r\n  @Scopes('Edit')\r\n  async update(@Param('code') code: string, @Body() product: Product) {\r\n    return await this.service.update(code, product);\r\n  }\r\n}\r\n```\r\n\r\n## Decorators\r\n\r\nHere is the decorators you can use in your controllers.\r\n\r\n| Decorator          | Description                                                                                               |\r\n|--------------------|-----------------------------------------------------------------------------------------------------------|\r\n| @AuthenticatedUser | Retrieves the current Keycloak logged-in user. (must be per method, unless controller is request scoped.) |\r\n| @EnforcerOptions   | Keycloak enforcer options.                                                                                |\r\n| @Public            | Allow any user to use the route.                                                                          |\r\n| @Resource          | Keycloak application resource name.                                                                       |\r\n| @Scope             | Keycloak application scope name.                                                                          |\r\n| @Roles             | Keycloak realm/application roles.                                                                         |\r\n\r\n## Multi tenant configuration\r\nSetting up for multi-tenant is configured as an option in your configuration:\r\n```typescript\r\n{\r\n  authServerUrl: 'http://localhost:8180/auth',\r\n  clientId: 'nest-api',\r\n  secret: 'fallback', // will be used as fallback when resolver returns null\r\n  multiTenant: {\r\n    realmResolver: (request) => {\r\n      return request.get('host').split('.')[0];\r\n    },\r\n    realmSecretResolver: (realm) => {\r\n      const secrets = { master: 'secret', slave: 'password' };\r\n      return secrets[realm];\r\n    }\r\n  }\r\n}\r\n```\r\n\r\n## Configuration options\r\n\r\n### Keycloak Options\r\nFor Keycloak options, refer to the official [keycloak-connect](https://github.com/keycloak/keycloak-nodejs-connect/blob/main/middleware/auth-utils/config.js) library.\r\n\r\n### Nest Keycloak Options\r\n| Option            | Description                                                                         | Required | Default      |\r\n|-------------------|-------------------------------------------------------------------------------------|----------|--------------|\r\n| cookieKey         | Cookie Key                                                                          | no       | KEYCLOAK_JWT |\r\n| logLevels         | Built-in logger level (deprecated, will be removed in 2.0)                          | no       | log          |\r\n| useNestLogger     | Use the nest logger (deprecated, will be removed in 2.0)                            | no       | true         |\r\n| policyEnforcement | Sets the policy enforcement mode                                                    | no       | PERMISSIVE   |\r\n| tokenValidation   | Sets the token validation method                                                    | no       | ONLINE       |\r\n| multiTenant       | Sets the options for [multi-tenant configuration](#multi-tenant-options)            | no       | -            |\r\n| roleMerge         | Sets the merge mode for @Role decorator                                             | no       | OVERRIDE     |\r\n\r\n### Multi Tenant Options\r\n| Option              | Description                                                                                             | Required | Default      |\r\n|---------------------|---------------------------------------------------------------------------------------------------------|----------|--------------|\r\n| resolveAlways       | Option to always resolve the realm and secret. Disabled by default.                                     | no       | false        |\r\n| realmResolver       | A function that passes a request (from respective platform i.e express or fastify) and returns a string | yes      | -            |\r\n| realmSecretResolver | A function that passes the realm string and returns the secret string                                   | yes      | -            |\r\n\r\n## Example app\r\n\r\nAn [example application](example) is provided in the source code with both Keycloak Realm and Postman requests for you to experiment with.\r\n","readmeFilename":"README.md","gitHead":"1bd4ce94f4828cc4999147debcc2a42d3d54fd88","homepage":"https://github.com/aaaahoang123/nest-keycloak-connect#readme","_id":"@aaaahoang123/nest-keycloak-connect@1.9.5-beta1","_nodeVersion":"18.12.0","_npmVersion":"8.19.2","dist":{"integrity":"sha512-swGWlzh3kmwYTN53Am5OhhUn6mqq3a4uVB65aqtEPuXF8W63lhHWvQg/hid1QVNBh4/8hJmQnXDfmfcfjJcWuw==","shasum":"a539c6404b0533a76d2ecb4e40a48ee729123465","tarball":"https://registry.npmjs.org/@aaaahoang123/nest-keycloak-connect/-/nest-keycloak-connect-1.9.5-beta1.tgz","fileCount":53,"unpackedSize":89636,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDGK95DSn0aGKQKhgF0O3NroYrfN+5XHG7w6/1GHQu5PQIhAKEoUoIvVa3/zU7OIxxJryLz0obaASJ3dbOZuCb/JL+m"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkG/gWACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr39A/+PsJsgk9Op+b6feN48Eg6aPQ0drlNpH0hiPP7lbjAXxBUKDFu\r\ne5j0D4hkqnXeShLiAUxh6KDQxxgplM5EOyt46CRldsNBSj1RXJoUhHbuAZUm\r\nVA1XjubHV/grvYkD3vDcQeLEavreSqG5eTai0jwy0xkhTjFrNj1c/OR2hhEt\r\n4gWVxezM2vRsGjXxfpwv3LwS7GIGD6vmt//Z3HsXG6KN9T2+QP3Ai/6XW4AL\r\nCbmBxNvCeQeliekMzMOOtEnRvSImnZQpHhJQaEYyEbYxFdHMeb8a9nmEusXr\r\nx6qrspAXl8bu4ekL8FckOoBxeqIxNzVC761zpN/ZkAl6/cmqWP2N0REzahXR\r\nturKETV4HoU1XnC/G1u4Q6aY1zOpF19KhYBuOIDIIfDaCX6s8aVa/qwSt1hm\r\n0MjX9n3ekkcly2bjxmZpArZsr/SHPyseIyApBL8a5eA5vkyBk30X2DGGqWwo\r\nFKMmYbaZykhwksOwnhPlFcpOwLtY0sAAKp6F53Yg1FiQJ7/xBeMLQZfGbA3S\r\n+wW4Jf+axMGxlXt7gId1/wTBs/SyU9GpkOs2NtnEAjfivIKLYp1eNvZcnSVy\r\nk/Y8Gi3Ual7s9MTzqLVga0aOSkZiDWPg8+0Yd4S5Cyxnpi5POVKD3xB6SNGG\r\nbtLpLvE7sDc5BBUGluekpRFbfcadqRcGqFQ=\r\n=2LKX\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"aaaahoang123","email":"hoangdo.2194@gmail.com"},"directories":{},"maintainers":[{"name":"aaaahoang123","email":"hoangdo.2194@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/nest-keycloak-connect_1.9.5-beta1_1679554582029_0.024606002304503827"},"_hasShrinkwrap":false},"1.9.5-beta2":{"name":"@aaaahoang123/nest-keycloak-connect","version":"1.9.5-beta2","description":"keycloak-nodejs-connect module for Nest","author":{"name":"John Joshua Ferrer","email":"johnjoshuaferrer@disroot.org"},"license":"MIT","scripts":{"start:dev":"tsc -w","clean":"rimraf dist","build":"tsc","build:copy":"cpr README.md dist/README.md && cpr LICENSE dist/LICENSE && cpr package.json dist/package.json","release":"release-it","release:alpha":"release-it --preReleaseId=alpha --npm.tag=next --github.preRelease","format":"prettier --write \"src/**/*.ts\"","lint":"eslint ./src --ext .ts"},"keywords":["nestjs","keycloak","typescript"],"repository":{"type":"git","url":"git+https://github.com/aaaahoang123/nest-keycloak-connect.git"},"bugs":{"url":"https://github.com/aaaahoang123/nest-keycloak-connect/issues"},"peerDependencies":{"@nestjs/common":">=6.0.0 <10.0.0","@nestjs/core":">=6.0.0 <10.0.0","@nestjs/graphql":">=6","keycloak-connect":">=10.0.0 <21.0.0"},"devDependencies":{"@nestjs/common":"^9.0.0","@nestjs/core":"^9.0.0","@nestjs/graphql":"^10.0.0","@types/express":"^4.17.13","@types/node":"^18.0.3","@typescript-eslint/eslint-plugin":"5.30.6","@typescript-eslint/parser":"5.30.6","class-transformer":"0.5.1","class-validator":"0.13.2","cpr":"3.0.1","eslint":"8.19.0","eslint-config-prettier":"8.5.0","eslint-plugin-prettier":"3.4.0","graphql":">=15.8.0 <16.0.0 || >=16.0.0 <17.0.0","keycloak-connect":"18.0.2","prettier":"1.19.1","reflect-metadata":"0.1.13","release-it":"14.13.1","rimraf":"3.0.2","rxjs":"7.5.6","ts-node":"10.8.2","typescript":"4.7.4"},"peerDependenciesMeta":{"@nestjs/graphql":{"optional":true}},"types":"./index.d.ts","readme":"# Nest Keycloak Connect\r\n\r\n![GitHub](https://img.shields.io/github/license/ferrerojosh/nest-keycloak-connect)\r\n![npm](https://img.shields.io/npm/v/nest-keycloak-connect)\r\n![npm peer dependency version](https://img.shields.io/npm/dependency-version/nest-keycloak-connect/peer/@nestjs/common)\r\n![npm peer dependency version](https://img.shields.io/npm/dependency-version/nest-keycloak-connect/peer/keycloak-connect)\r\n[![Verify Build](https://github.com/ferrerojosh/nest-keycloak-connect/actions/workflows/verify-build.yml/badge.svg?branch=master)](https://github.com/ferrerojosh/nest-keycloak-connect/actions/workflows/verify-build.yml)\r\n![npm](https://img.shields.io/npm/dw/nest-keycloak-connect)\r\n![npm](https://img.shields.io/npm/dt/nest-keycloak-connect)\r\n\r\n[![Support via PayPal](https://cdn.rawgit.com/twolfson/paypal-github-button/1.0.0/dist/button.svg)](https://www.paypal.me/ferrerojosh/)\r\n\r\n> An adapter for [keycloak-nodejs-connect](https://github.com/keycloak/keycloak-nodejs-connect).\r\n\r\n## Features\r\n\r\n- Protect your resources using [Keycloak's Authorization Services](https://www.keycloak.org/docs/latest/authorization_services/).\r\n- Simply add `@Resource`, `@Scopes`, or `@Roles` in your controllers and you're good to go.\r\n- Compatible with [Fastify](https://github.com/fastify/fastify) platform.\r\n\r\n## Installation\r\n\r\n### Yarn\r\n\r\n```bash\r\nyarn add @aaaahoang123/nest-keycloak-connect keycloak-connect\r\n```\r\n\r\n### NPM\r\n\r\n```bash\r\nnpm install @aaaahoang123/nest-keycloak-connect keycloak-connect --save\r\n```\r\n\r\n## Getting Started\r\n\r\n### Module registration\r\n\r\nRegistering the module:\r\n```typescript\r\nKeycloakConnectModule.register({\r\n  authServerUrl: 'http://localhost:8080', // might be http://localhost:8080/auth for older keycloak versions\r\n  realm: 'master',\r\n  clientId: 'my-nestjs-app',\r\n  secret: 'secret',   \r\n  policyEnforcement: PolicyEnforcementMode.PERMISSIVE, // optional\r\n  tokenValidation: TokenValidation.ONLINE, // optional\r\n})\r\n```\r\n\r\nAsync registration is also available:\r\n```typescript\r\nKeycloakConnectModule.registerAsync({\r\n  useExisting: KeycloakConfigService,\r\n  imports: [ConfigModule]\r\n})\r\n```\r\n\r\n#### KeycloakConfigService\r\n```typescript\r\nimport { Injectable } from '@nestjs/common';\r\nimport { KeycloakConnectOptions, KeycloakConnectOptionsFactory, PolicyEnforcementMode, TokenValidation } from 'nest-keycloak-connect';\r\n\r\n@Injectable()\r\nexport class KeycloakConfigService implements KeycloakConnectOptionsFactory {\r\n\r\n  createKeycloakConnectOptions(): KeycloakConnectOptions {\r\n    return {\r\n      authServerUrl: 'http://localhost:8080', // might be http://localhost:8080/auth for older keycloak versions\r\n      realm: 'master',\r\n      clientId: 'my-nestjs-app',\r\n      secret: 'secret',\r\n      policyEnforcement: PolicyEnforcementMode.PERMISSIVE,\r\n      tokenValidation: TokenValidation.ONLINE,\r\n    };\r\n  } \r\n}\r\n```\r\n\r\nYou can also register by just providing the `keycloak.json` path and an optional module configuration:\r\n\r\n```typescript\r\nKeycloakConnectModule.register(`./keycloak.json`, {\r\n  policyEnforcement: PolicyEnforcementMode.PERMISSIVE,\r\n  tokenValidation: TokenValidation.ONLINE,\r\n})\r\n```\r\n\r\n### Guards\r\n\r\nRegister any of the guards either globally, or scoped in your controller.\r\n\r\n#### Global registration using APP_GUARD token\r\n***NOTE: These are in order, see https://docs.nestjs.com/guards#binding-guards for more information.***\r\n```typescript\r\nproviders: [\r\n  {\r\n    provide: APP_GUARD,     \r\n    useClass: AuthGuard,\r\n  },\r\n  {\r\n    provide: APP_GUARD,\r\n    useClass: ResourceGuard,\r\n  },\r\n  {\r\n    provide: APP_GUARD,\r\n    useClass: RoleGuard,\r\n  },\r\n]\r\n```\r\n#### Scoped registration\r\n```typescript\r\n@Controller('cats')\r\n@UseGuards(AuthGuard, ResourceGuard)\r\nexport class CatsController {}\r\n```\r\n\r\n## What does these providers do ?\r\n\r\n### AuthGuard\r\nAdds an authentication guard, you can also have it scoped if you like (using regular `@UseGuards(AuthGuard)` in your controllers). By default, it will throw a 401 unauthorized when it is unable to verify the JWT token or `Bearer` header is missing.\r\n\r\n### ResourceGuard\r\nAdds a resource guard, which is permissive by default (can be configured see [options](#nest-keycloak-options)). Only controllers annotated with `@Resource` and methods with `@Scopes` are handled by this guard.\r\n\r\n***NOTE: This guard is not necessary if you are using role-based authorization exclusively. You can use role guard exclusively for that.***\r\n\r\n### RoleGuard\r\nAdds a role guard, **can only be used in conjunction with resource guard when enforcement policy is PERMISSIVE**, unless you only use role guard exclusively.\r\nPermissive by default. Used by controller methods annotated with `@Roles` (matching can be configured)\r\n\r\n## Configuring controllers\r\n\r\nIn your controllers, simply do:\r\n\r\n```typescript\r\nimport { Resource, Roles, Scopes, Public, RoleMatchingMode } from 'nest-keycloak-connect';\r\nimport { Controller, Get, Delete, Put, Post, Param } from '@nestjs/common';\r\nimport { Product } from './product';\r\nimport { ProductService } from './product.service';\r\n\r\n@Controller()\r\n@Resource(Product.name)\r\nexport class ProductController {\r\n  constructor(private service: ProductService) {}\r\n\r\n  @Get()\r\n  @Public()\r\n  async findAll() {\r\n    return await this.service.findAll();\r\n  }\r\n\r\n  @Get()\r\n  @Roles({ roles: ['admin', 'other'] })\r\n  async findAllBarcodes() {\r\n    return await this.service.findAllBarcodes();\r\n  }\r\n\r\n  @Get(':code')\r\n  @Scopes('View')\r\n  async findByCode(@Param('code') code: string) {\r\n    return await this.service.findByCode(code);\r\n  }\r\n\r\n  @Post()\r\n  @Scopes('Create')\r\n  async create(@Body() product: Product) {\r\n    return await this.service.create(product);\r\n  }\r\n\r\n  @Delete(':code')\r\n  @Scopes('Delete')\r\n  @Roles({ roles: ['admin', 'realm:sysadmin'], mode: RoleMatchingMode.ALL })\r\n  async deleteByCode(@Param('code') code: string) {\r\n    return await this.service.deleteByCode(code);\r\n  }\r\n\r\n  @Put(':code')\r\n  @Scopes('Edit')\r\n  async update(@Param('code') code: string, @Body() product: Product) {\r\n    return await this.service.update(code, product);\r\n  }\r\n}\r\n```\r\n\r\n## Decorators\r\n\r\nHere is the decorators you can use in your controllers.\r\n\r\n| Decorator          | Description                                                                                               |\r\n|--------------------|-----------------------------------------------------------------------------------------------------------|\r\n| @AuthenticatedUser | Retrieves the current Keycloak logged-in user. (must be per method, unless controller is request scoped.) |\r\n| @EnforcerOptions   | Keycloak enforcer options.                                                                                |\r\n| @Public            | Allow any user to use the route.                                                                          |\r\n| @Resource          | Keycloak application resource name.                                                                       |\r\n| @Scope             | Keycloak application scope name.                                                                          |\r\n| @Roles             | Keycloak realm/application roles.                                                                         |\r\n\r\n## Multi tenant configuration\r\nSetting up for multi-tenant is configured as an option in your configuration:\r\n```typescript\r\n{\r\n  authServerUrl: 'http://localhost:8180/auth',\r\n  clientId: 'nest-api',\r\n  secret: 'fallback', // will be used as fallback when resolver returns null\r\n  multiTenant: {\r\n    realmResolver: (request) => {\r\n      return request.get('host').split('.')[0];\r\n    },\r\n    realmSecretResolver: (realm) => {\r\n      const secrets = { master: 'secret', slave: 'password' };\r\n      return secrets[realm];\r\n    }\r\n  }\r\n}\r\n```\r\n\r\n## Configuration options\r\n\r\n### Keycloak Options\r\nFor Keycloak options, refer to the official [keycloak-connect](https://github.com/keycloak/keycloak-nodejs-connect/blob/main/middleware/auth-utils/config.js) library.\r\n\r\n### Nest Keycloak Options\r\n| Option            | Description                                                                         | Required | Default      |\r\n|-------------------|-------------------------------------------------------------------------------------|----------|--------------|\r\n| cookieKey         | Cookie Key                                                                          | no       | KEYCLOAK_JWT |\r\n| logLevels         | Built-in logger level (deprecated, will be removed in 2.0)                          | no       | log          |\r\n| useNestLogger     | Use the nest logger (deprecated, will be removed in 2.0)                            | no       | true         |\r\n| policyEnforcement | Sets the policy enforcement mode                                                    | no       | PERMISSIVE   |\r\n| tokenValidation   | Sets the token validation method                                                    | no       | ONLINE       |\r\n| multiTenant       | Sets the options for [multi-tenant configuration](#multi-tenant-options)            | no       | -            |\r\n| roleMerge         | Sets the merge mode for @Role decorator                                             | no       | OVERRIDE     |\r\n\r\n### Multi Tenant Options\r\n| Option              | Description                                                                                             | Required | Default      |\r\n|---------------------|---------------------------------------------------------------------------------------------------------|----------|--------------|\r\n| resolveAlways       | Option to always resolve the realm and secret. Disabled by default.                                     | no       | false        |\r\n| realmResolver       | A function that passes a request (from respective platform i.e express or fastify) and returns a string | yes      | -            |\r\n| realmSecretResolver | A function that passes the realm string and returns the secret string                                   | yes      | -            |\r\n\r\n## Example app\r\n\r\nAn [example application](example) is provided in the source code with both Keycloak Realm and Postman requests for you to experiment with.\r\n","readmeFilename":"README.md","gitHead":"53bcd4c629806be7fcd5e7d826ffef07f2b09f68","homepage":"https://github.com/aaaahoang123/nest-keycloak-connect#readme","_id":"@aaaahoang123/nest-keycloak-connect@1.9.5-beta2","_nodeVersion":"18.12.0","_npmVersion":"8.19.2","dist":{"integrity":"sha512-Re/TLFaY8wbULRENFWDRc7XLT/nvtXNsGE9V5y3sVaZj3rg5V3ot35o+M5caAYKz0gwN8Du83YFpkZSBykXxEg==","shasum":"9a24c773590736ed0f2c066ffa1699f9a13a6362","tarball":"https://registry.npmjs.org/@aaaahoang123/nest-keycloak-connect/-/nest-keycloak-connect-1.9.5-beta2.tgz","fileCount":53,"unpackedSize":89645,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAq9J53TH1nm8DTqVksQni0UCtnjR0CCzIQ/XmK3JU4UAiEAkW0/WAdPS7WrkARflqCnYenv8ZJkASGXQ/PneQdwic4="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkIPt8ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqDCxAAj1bDCGhomg5cbzShCcdqbXQhw2Dbs5iAmh9CFATKeiXDHDk4\r\no7mYmJUoO1/QxplVWteeE+wPx6i7fif6ok9Qs25wdlhBhpQEuIGbQ4/flsXU\r\nXdvtIDv2Y+sFJyf+3osPU+9kROOwnO9iRr2T0kDf1jeRe3GN5ad8b/I1WSa7\r\na6QWvF0b5HMrzy7z74BLfzca+AwCHAOtodlOFGY5ogVJdcOtg5QLhxVxzuXQ\r\nMvX20W6GSuigEjXnBxrylXODCS8LVkt8fPEf54ZPAepC94yfn+OcD1FpqM/1\r\noDpQn6J8S95b7eAlOmwxZgNkO9l/k0aCHvRgaLW0Lw5x2pPITdMHr166+GFO\r\nZrjzEar21MPvBXW9XqvQlHS8RjNlzuR69NbJYL0PszMHykd4LdzuPal1+vJu\r\nFI5tkGUiLudkU2i/bKSzQxKhawFjOUo+6pJYerQJ2+qTZPY4N1ooGkxgGUdB\r\n5l2kbXUraljEdrqzDeA+oXTIuN4sT2yatI35WWbcYFc+EIabvijCcCyCEzTw\r\nE0c5C85VqPVM7itIse1M3wlvcht8nGmAeAjlvwbqJ1cHYq9Nh4ZQ73BqacOD\r\nohw0vzTlSEw52ryvZoa87VYNnkV4T7zLKDPPMA0Ngqff828L/3zFS1kclOYV\r\naIawNz0RUMd5lTf0cxO3/EezdLzKe4MB7sc=\r\n=LH4v\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"aaaahoang123","email":"hoangdo.2194@gmail.com"},"directories":{},"maintainers":[{"name":"aaaahoang123","email":"hoangdo.2194@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/nest-keycloak-connect_1.9.5-beta2_1679883132643_0.6062121763178996"},"_hasShrinkwrap":false},"1.9.5":{"name":"@aaaahoang123/nest-keycloak-connect","version":"1.9.5","description":"keycloak-nodejs-connect module for Nest","author":{"name":"John Joshua Ferrer","email":"johnjoshuaferrer@disroot.org"},"license":"MIT","scripts":{"start:dev":"tsc -w","clean":"rimraf dist","build":"tsc","build:copy":"cpr README.md dist/README.md && cpr LICENSE dist/LICENSE && cpr package.json dist/package.json","release":"release-it","release:alpha":"release-it --preReleaseId=alpha --npm.tag=next --github.preRelease","format":"prettier --write \"src/**/*.ts\"","lint":"eslint ./src --ext .ts"},"keywords":["nestjs","keycloak","typescript"],"repository":{"type":"git","url":"git+https://github.com/aaaahoang123/nest-keycloak-connect.git"},"bugs":{"url":"https://github.com/aaaahoang123/nest-keycloak-connect/issues"},"peerDependencies":{"@nestjs/common":">=6.0.0 <10.0.0","@nestjs/core":">=6.0.0 <10.0.0","@nestjs/graphql":">=6","keycloak-connect":">=10.0.0 <21.0.0"},"devDependencies":{"@nestjs/common":"^9.0.0","@nestjs/core":"^9.0.0","@nestjs/graphql":"^10.0.0","@types/express":"^4.17.13","@types/node":"^18.0.3","@typescript-eslint/eslint-plugin":"5.30.6","@typescript-eslint/parser":"5.30.6","class-transformer":"0.5.1","class-validator":"0.13.2","cpr":"3.0.1","eslint":"8.19.0","eslint-config-prettier":"8.5.0","eslint-plugin-prettier":"3.4.0","graphql":">=15.8.0 <16.0.0 || >=16.0.0 <17.0.0","keycloak-connect":"18.0.2","prettier":"1.19.1","reflect-metadata":"0.1.13","release-it":"14.13.1","rimraf":"3.0.2","rxjs":"7.5.6","ts-node":"10.8.2","typescript":"4.7.4"},"peerDependenciesMeta":{"@nestjs/graphql":{"optional":true}},"types":"./index.d.ts","gitHead":"a60a87a6dd8009ea5c04b324a2e02894f00354b9","homepage":"https://github.com/aaaahoang123/nest-keycloak-connect#readme","_id":"@aaaahoang123/nest-keycloak-connect@1.9.5","_nodeVersion":"18.12.0","_npmVersion":"8.19.2","dist":{"integrity":"sha512-NTTd34TBs8KF8ZTD/cGHhICE0bJRs9nzsCHcUUowRRWE0eHi9J7+uCtFJ9ZHIJUzQWdn0lXU3EPovOsr6J9bWw==","shasum":"4cfc4c223218191b0f79c658d7d57065fc6b270b","tarball":"https://registry.npmjs.org/@aaaahoang123/nest-keycloak-connect/-/nest-keycloak-connect-1.9.5.tgz","fileCount":53,"unpackedSize":89639,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD8/ci9RZ05xHC9WMwroBn4IPZ3i79BCjz0TQSWWurY3gIgCj4nTd9Z0OYzrxZhvtNVjfkk8KxmGzToPpCjahyLTj4="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkIP9FACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp66xAAobWEUgNtdsTNXnFThtQlqIwfzqwOZHJtOBpn1TZ7Y6E19RSt\r\nzn7e/iZm9Mn3IHYNb1ONZFJ+JhxzpoymiYgueRLuSh3uPIywN5J0spb0Udff\r\nocz+G/IC3kf6Ef2NAHquML0OHAGm/9C/p38GEWdJxGCMEj3OiuNxUJUYTP9G\r\nBh9SJCu+xlKLiwsIi54q/Nyb57UWmpQnOp9LyeIAR1Bl3npfkYwkYJhEfDvn\r\nWXoFz7ZRY0polAqE3EcMt6Yf22QCvsLRzm8vPsVNIOCROFdfCAY6tZpUyQ+N\r\n44k7ZuIW/wCMiW0dOajIq4+QT5uBWBUIZXF+LWE5nZGul1zgt1X9QJn+BuWi\r\ngHITOHD/IVDjMcW+RKxsQs/cWSMssydQUN5FnHvWOxWICMDOZ3a43MyIncCS\r\nMHv0y7zdzDhMRVRi2G0SQtt6pD/1WjTNIcS+9IuaY3zqf5ENQyCYLP/KSGTg\r\nxc27z4SqPV6YhMRZyWFRVj39YXaedhOAUV6XjPndvF7Rmdy+Hkv4ED9KhQ01\r\nO9MlG9SmBejeLjQJ+A4km1p+VMsdfFO8IdBuae6VEFiqC7oByXr3MRk/uLU+\r\nRfGqK1h4gkU2aOBxdZw3TuWpabaRhNchJKzfPxy8kjnItKMoQQWg3yIW5qFw\r\nJeEnAU3rzB1xoq93ukbe82KWyKEydBgloBg=\r\n=lenk\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"aaaahoang123","email":"hoangdo.2194@gmail.com"},"directories":{},"maintainers":[{"name":"aaaahoang123","email":"hoangdo.2194@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/nest-keycloak-connect_1.9.5_1679884101515_0.8654485231856419"},"_hasShrinkwrap":false}},"time":{"created":"2023-03-02T11:10:30.835Z","1.9.2":"2023-03-02T11:10:31.190Z","modified":"2023-03-27T02:28:21.772Z","1.9.3":"2023-03-06T06:52:57.686Z","1.9.4":"2023-03-06T08:24:17.810Z","1.9.5-beta1":"2023-03-23T06:56:22.226Z","1.9.5-beta2":"2023-03-27T02:12:12.806Z","1.9.5":"2023-03-27T02:28:21.672Z"},"maintainers":[{"name":"aaaahoang123","email":"hoangdo.2194@gmail.com"}],"description":"keycloak-nodejs-connect module for Nest","homepage":"https://github.com/aaaahoang123/nest-keycloak-connect#readme","keywords":["nestjs","keycloak","typescript"],"repository":{"type":"git","url":"git+https://github.com/aaaahoang123/nest-keycloak-connect.git"},"author":{"name":"John Joshua Ferrer","email":"johnjoshuaferrer@disroot.org"},"bugs":{"url":"https://github.com/aaaahoang123/nest-keycloak-connect/issues"},"license":"MIT","readme":"# Nest Keycloak Connect\r\n\r\n![GitHub](https://img.shields.io/github/license/ferrerojosh/nest-keycloak-connect)\r\n![npm](https://img.shields.io/npm/v/nest-keycloak-connect)\r\n![npm peer dependency version](https://img.shields.io/npm/dependency-version/nest-keycloak-connect/peer/@nestjs/common)\r\n![npm peer dependency version](https://img.shields.io/npm/dependency-version/nest-keycloak-connect/peer/keycloak-connect)\r\n[![Verify Build](https://github.com/ferrerojosh/nest-keycloak-connect/actions/workflows/verify-build.yml/badge.svg?branch=master)](https://github.com/ferrerojosh/nest-keycloak-connect/actions/workflows/verify-build.yml)\r\n![npm](https://img.shields.io/npm/dw/nest-keycloak-connect)\r\n![npm](https://img.shields.io/npm/dt/nest-keycloak-connect)\r\n\r\n[![Support via PayPal](https://cdn.rawgit.com/twolfson/paypal-github-button/1.0.0/dist/button.svg)](https://www.paypal.me/ferrerojosh/)\r\n\r\n> An adapter for [keycloak-nodejs-connect](https://github.com/keycloak/keycloak-nodejs-connect).\r\n\r\n## Features\r\n\r\n- Protect your resources using [Keycloak's Authorization Services](https://www.keycloak.org/docs/latest/authorization_services/).\r\n- Simply add `@Resource`, `@Scopes`, or `@Roles` in your controllers and you're good to go.\r\n- Compatible with [Fastify](https://github.com/fastify/fastify) platform.\r\n\r\n## Installation\r\n\r\n### Yarn\r\n\r\n```bash\r\nyarn add @aaaahoang123/nest-keycloak-connect keycloak-connect\r\n```\r\n\r\n### NPM\r\n\r\n```bash\r\nnpm install @aaaahoang123/nest-keycloak-connect keycloak-connect --save\r\n```\r\n\r\n## Getting Started\r\n\r\n### Module registration\r\n\r\nRegistering the module:\r\n```typescript\r\nKeycloakConnectModule.register({\r\n  authServerUrl: 'http://localhost:8080', // might be http://localhost:8080/auth for older keycloak versions\r\n  realm: 'master',\r\n  clientId: 'my-nestjs-app',\r\n  secret: 'secret',   \r\n  policyEnforcement: PolicyEnforcementMode.PERMISSIVE, // optional\r\n  tokenValidation: TokenValidation.ONLINE, // optional\r\n})\r\n```\r\n\r\nAsync registration is also available:\r\n```typescript\r\nKeycloakConnectModule.registerAsync({\r\n  useExisting: KeycloakConfigService,\r\n  imports: [ConfigModule]\r\n})\r\n```\r\n\r\n#### KeycloakConfigService\r\n```typescript\r\nimport { Injectable } from '@nestjs/common';\r\nimport { KeycloakConnectOptions, KeycloakConnectOptionsFactory, PolicyEnforcementMode, TokenValidation } from 'nest-keycloak-connect';\r\n\r\n@Injectable()\r\nexport class KeycloakConfigService implements KeycloakConnectOptionsFactory {\r\n\r\n  createKeycloakConnectOptions(): KeycloakConnectOptions {\r\n    return {\r\n      authServerUrl: 'http://localhost:8080', // might be http://localhost:8080/auth for older keycloak versions\r\n      realm: 'master',\r\n      clientId: 'my-nestjs-app',\r\n      secret: 'secret',\r\n      policyEnforcement: PolicyEnforcementMode.PERMISSIVE,\r\n      tokenValidation: TokenValidation.ONLINE,\r\n    };\r\n  } \r\n}\r\n```\r\n\r\nYou can also register by just providing the `keycloak.json` path and an optional module configuration:\r\n\r\n```typescript\r\nKeycloakConnectModule.register(`./keycloak.json`, {\r\n  policyEnforcement: PolicyEnforcementMode.PERMISSIVE,\r\n  tokenValidation: TokenValidation.ONLINE,\r\n})\r\n```\r\n\r\n### Guards\r\n\r\nRegister any of the guards either globally, or scoped in your controller.\r\n\r\n#### Global registration using APP_GUARD token\r\n***NOTE: These are in order, see https://docs.nestjs.com/guards#binding-guards for more information.***\r\n```typescript\r\nproviders: [\r\n  {\r\n    provide: APP_GUARD,     \r\n    useClass: AuthGuard,\r\n  },\r\n  {\r\n    provide: APP_GUARD,\r\n    useClass: ResourceGuard,\r\n  },\r\n  {\r\n    provide: APP_GUARD,\r\n    useClass: RoleGuard,\r\n  },\r\n]\r\n```\r\n#### Scoped registration\r\n```typescript\r\n@Controller('cats')\r\n@UseGuards(AuthGuard, ResourceGuard)\r\nexport class CatsController {}\r\n```\r\n\r\n## What does these providers do ?\r\n\r\n### AuthGuard\r\nAdds an authentication guard, you can also have it scoped if you like (using regular `@UseGuards(AuthGuard)` in your controllers). By default, it will throw a 401 unauthorized when it is unable to verify the JWT token or `Bearer` header is missing.\r\n\r\n### ResourceGuard\r\nAdds a resource guard, which is permissive by default (can be configured see [options](#nest-keycloak-options)). Only controllers annotated with `@Resource` and methods with `@Scopes` are handled by this guard.\r\n\r\n***NOTE: This guard is not necessary if you are using role-based authorization exclusively. You can use role guard exclusively for that.***\r\n\r\n### RoleGuard\r\nAdds a role guard, **can only be used in conjunction with resource guard when enforcement policy is PERMISSIVE**, unless you only use role guard exclusively.\r\nPermissive by default. Used by controller methods annotated with `@Roles` (matching can be configured)\r\n\r\n## Configuring controllers\r\n\r\nIn your controllers, simply do:\r\n\r\n```typescript\r\nimport { Resource, Roles, Scopes, Public, RoleMatchingMode } from 'nest-keycloak-connect';\r\nimport { Controller, Get, Delete, Put, Post, Param } from '@nestjs/common';\r\nimport { Product } from './product';\r\nimport { ProductService } from './product.service';\r\n\r\n@Controller()\r\n@Resource(Product.name)\r\nexport class ProductController {\r\n  constructor(private service: ProductService) {}\r\n\r\n  @Get()\r\n  @Public()\r\n  async findAll() {\r\n    return await this.service.findAll();\r\n  }\r\n\r\n  @Get()\r\n  @Roles({ roles: ['admin', 'other'] })\r\n  async findAllBarcodes() {\r\n    return await this.service.findAllBarcodes();\r\n  }\r\n\r\n  @Get(':code')\r\n  @Scopes('View')\r\n  async findByCode(@Param('code') code: string) {\r\n    return await this.service.findByCode(code);\r\n  }\r\n\r\n  @Post()\r\n  @Scopes('Create')\r\n  async create(@Body() product: Product) {\r\n    return await this.service.create(product);\r\n  }\r\n\r\n  @Delete(':code')\r\n  @Scopes('Delete')\r\n  @Roles({ roles: ['admin', 'realm:sysadmin'], mode: RoleMatchingMode.ALL })\r\n  async deleteByCode(@Param('code') code: string) {\r\n    return await this.service.deleteByCode(code);\r\n  }\r\n\r\n  @Put(':code')\r\n  @Scopes('Edit')\r\n  async update(@Param('code') code: string, @Body() product: Product) {\r\n    return await this.service.update(code, product);\r\n  }\r\n}\r\n```\r\n\r\n## Decorators\r\n\r\nHere is the decorators you can use in your controllers.\r\n\r\n| Decorator          | Description                                                                                               |\r\n|--------------------|-----------------------------------------------------------------------------------------------------------|\r\n| @AuthenticatedUser | Retrieves the current Keycloak logged-in user. (must be per method, unless controller is request scoped.) |\r\n| @EnforcerOptions   | Keycloak enforcer options.                                                                                |\r\n| @Public            | Allow any user to use the route.                                                                          |\r\n| @Resource          | Keycloak application resource name.                                                                       |\r\n| @Scope             | Keycloak application scope name.                                                                          |\r\n| @Roles             | Keycloak realm/application roles.                                                                         |\r\n\r\n## Multi tenant configuration\r\nSetting up for multi-tenant is configured as an option in your configuration:\r\n```typescript\r\n{\r\n  authServerUrl: 'http://localhost:8180/auth',\r\n  clientId: 'nest-api',\r\n  secret: 'fallback', // will be used as fallback when resolver returns null\r\n  multiTenant: {\r\n    realmResolver: (request) => {\r\n      return request.get('host').split('.')[0];\r\n    },\r\n    realmSecretResolver: (realm) => {\r\n      const secrets = { master: 'secret', slave: 'password' };\r\n      return secrets[realm];\r\n    }\r\n  }\r\n}\r\n```\r\n\r\n## Configuration options\r\n\r\n### Keycloak Options\r\nFor Keycloak options, refer to the official [keycloak-connect](https://github.com/keycloak/keycloak-nodejs-connect/blob/main/middleware/auth-utils/config.js) library.\r\n\r\n### Nest Keycloak Options\r\n| Option            | Description                                                                         | Required | Default      |\r\n|-------------------|-------------------------------------------------------------------------------------|----------|--------------|\r\n| cookieKey         | Cookie Key                                                                          | no       | KEYCLOAK_JWT |\r\n| logLevels         | Built-in logger level (deprecated, will be removed in 2.0)                          | no       | log          |\r\n| useNestLogger     | Use the nest logger (deprecated, will be removed in 2.0)                            | no       | true         |\r\n| policyEnforcement | Sets the policy enforcement mode                                                    | no       | PERMISSIVE   |\r\n| tokenValidation   | Sets the token validation method                                                    | no       | ONLINE       |\r\n| multiTenant       | Sets the options for [multi-tenant configuration](#multi-tenant-options)            | no       | -            |\r\n| roleMerge         | Sets the merge mode for @Role decorator                                             | no       | OVERRIDE     |\r\n\r\n### Multi Tenant Options\r\n| Option              | Description                                                                                             | Required | Default      |\r\n|---------------------|---------------------------------------------------------------------------------------------------------|----------|--------------|\r\n| resolveAlways       | Option to always resolve the realm and secret. Disabled by default.                                     | no       | false        |\r\n| realmResolver       | A function that passes a request (from respective platform i.e express or fastify) and returns a string | yes      | -            |\r\n| realmSecretResolver | A function that passes the realm string and returns the secret string                                   | yes      | -            |\r\n\r\n## Example app\r\n\r\nAn [example application](example) is provided in the source code with both Keycloak Realm and Postman requests for you to experiment with.\r\n","readmeFilename":"README.md"}