{"_id":"@bitovi-training/auth-middleware","_rev":"4-0078ec32db513022ffc1a11b180b320f","name":"@bitovi-training/auth-middleware","dist-tags":{"latest":"0.2.1"},"versions":{"0.2.0":{"name":"@bitovi-training/auth-middleware","version":"0.2.0","keywords":["nestjs","authentication","jwt","rbac","mock","development"],"author":{"name":"Bitovi Training"},"license":"MIT","_id":"@bitovi-training/auth-middleware@0.2.0","maintainers":[{"name":"paytonrog","email":"paytonrog@gmail.com"}],"homepage":"https://github.com/bitovi-training/auth-middleware#readme","bugs":{"url":"https://github.com/bitovi-training/auth-middleware/issues"},"dist":{"shasum":"0ecc9842619bf9c74cb676004a50cd4fdf644d3a","tarball":"https://registry.npmjs.org/@bitovi-training/auth-middleware/-/auth-middleware-0.2.0.tgz","fileCount":2,"integrity":"sha512-IWA21sFoUPQ+ivLsmIO0nArfEQNVzukOfMVPmZO742cHsctVjPiBXBDvEAV1tTJjstM6xLMTnIgbeZ8s830/gg==","signatures":[{"sig":"MEQCIFxgalPqb1ghEZ52grMOzNuMJnR0G+LaFfCxFFv4GpfbAiBs5K7D0FtUwnVlSGkh4mBHCfJNzmM0ZLsxlW+56Pkc2w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":9730},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"2a9883cf3eecb57e6681feeace7cdab7fd607c38","scripts":{"lint":"eslint \"{src,test}/**/*.ts\"","test":"jest","build":"tsc","lint:fix":"eslint \"{src,test}/**/*.ts\" --fix","test:cov":"jest --coverage","test:watch":"jest --watch"},"_npmUser":{"name":"paytonrog","email":"paytonrog@gmail.com"},"repository":{"url":"git+https://github.com/bitovi-training/auth-middleware.git","type":"git","directory":"auth-middleware"},"_npmVersion":"10.9.2","description":"NestJS mock authentication middleware with JWT parsing and role-based access control (development mode only)","directories":{},"_nodeVersion":"22.14.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.5.0","rxjs":"^7.8.0","eslint":"^8.57.1","ts-jest":"^29.1.0","typescript":"^5.0.0","@types/jest":"^29.5.0","@types/node":"^20.0.0","@nestjs/core":"^11.0.0","@nestjs/common":"^11.0.0","@nestjs/testing":"^11.0.0","reflect-metadata":"^0.1.13","@nestjs/platform-express":"^11.0.0","@typescript-eslint/parser":"^8.53.0","@typescript-eslint/eslint-plugin":"^8.53.0"},"peerDependencies":{"rxjs":"^7.8.0","@nestjs/core":"^11.0.0","@nestjs/common":"^11.0.0","reflect-metadata":"^0.1.13 || ^0.2.0"},"_npmOperationalInternal":{"tmp":"tmp/auth-middleware_0.2.0_1772472027713_0.4464276606657007","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@bitovi-training/auth-middleware","version":"0.2.1","description":"NestJS mock authentication middleware with JWT parsing and role-based access control (development mode only)","main":"dist/index.js","types":"dist/index.d.ts","scripts":{"build":"tsc","test":"jest","test:watch":"jest --watch","test:cov":"jest --coverage","lint":"eslint \"{src,test}/**/*.ts\"","lint:fix":"eslint \"{src,test}/**/*.ts\" --fix"},"keywords":["nestjs","authentication","jwt","rbac","mock","development"],"author":{"name":"Bitovi Training"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bitovi-training/auth-middleware.git","directory":"auth-middleware"},"publishConfig":{"access":"public"},"peerDependencies":{"@nestjs/common":"^11.0.0","@nestjs/core":"^11.0.0","reflect-metadata":"^0.1.13 || ^0.2.0","rxjs":"^7.8.0"},"devDependencies":{"@nestjs/common":"^11.0.0","@nestjs/core":"^11.0.0","@nestjs/platform-express":"^11.0.0","@nestjs/testing":"^11.0.0","@types/jest":"^29.5.0","@types/node":"^20.0.0","@typescript-eslint/eslint-plugin":"^8.53.0","@typescript-eslint/parser":"^8.53.0","eslint":"^8.57.1","jest":"^29.5.0","reflect-metadata":"^0.1.13","rxjs":"^7.8.0","ts-jest":"^29.1.0","typescript":"^5.0.0"},"_id":"@bitovi-training/auth-middleware@0.2.1","gitHead":"2a9883cf3eecb57e6681feeace7cdab7fd607c38","bugs":{"url":"https://github.com/bitovi-training/auth-middleware/issues"},"homepage":"https://github.com/bitovi-training/auth-middleware#readme","_nodeVersion":"22.14.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-VDH4Aw0yTt7Ca79NVKTJrjI8eWu20Veo1OH1owj6Fm5HAncp8qcLCp/qdFziFOGYptul9eX+xOVBgZ+cm7J2Uw==","shasum":"49ea0def4228723adccf8ca2213e9edde8cfb9fb","tarball":"https://registry.npmjs.org/@bitovi-training/auth-middleware/-/auth-middleware-0.2.1.tgz","fileCount":39,"unpackedSize":166944,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIATcZLhn5CW4cC6bsC44Kqzu9QlN+3Y9KIG99feGWMaPAiEAlYCT9o5sNT7QWb3q809aR5bY6ykhRloi3b10WwBBHdw="}]},"_npmUser":{"name":"paytonrog","email":"paytonrog@gmail.com"},"directories":{},"maintainers":[{"name":"paytonrog","email":"paytonrog@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/auth-middleware_0.2.1_1772472863706_0.11060397671451838"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-02T17:18:51.689Z","modified":"2026-03-02T17:34:23.976Z","0.1.0":"2026-03-02T17:18:51.983Z","0.2.0":"2026-03-02T17:20:27.871Z","0.2.1":"2026-03-02T17:34:23.847Z"},"bugs":{"url":"https://github.com/bitovi-training/auth-middleware/issues"},"author":{"name":"Bitovi Training"},"license":"MIT","homepage":"https://github.com/bitovi-training/auth-middleware#readme","keywords":["nestjs","authentication","jwt","rbac","mock","development"],"repository":{"type":"git","url":"git+https://github.com/bitovi-training/auth-middleware.git","directory":"auth-middleware"},"description":"NestJS mock authentication middleware with JWT parsing and role-based access control (development mode only)","maintainers":[{"name":"paytonrog","email":"paytonrog@gmail.com"}],"readme":"# NestJS Mock Authentication Middleware\n\nA lightweight NestJS authentication middleware that provides JWT-based authentication and role-based access control (RBAC) without cryptographic signature verification. Ideal for development, testing, and prototyping environments.\n\n⚠️ **WARNING**: This is a MOCK implementation that does NOT verify JWT signatures. **DO NOT use in production** without adding proper JWT verification.\n\n## Features\n\n- ✅ JWT token parsing and validation (structure and required claims)\n- ✅ User claims extraction (sub, email, roles, exp, iat)\n- ✅ Role-based access control with any-of semantics (`@Roles()`)\n- ✅ Role-based access control with all-of semantics (`@RequireAllRoles()`)\n- ✅ Structured logging with NestJS Logger\n- ✅ Custom exceptions with consistent error responses\n- ✅ TypeScript-first with strict type checking\n- ✅ Zero external dependencies for JWT parsing\n\n## Installation\n\n```bash\nnpm install @bitovi-training/auth-middleware\n```\n\n### Peer Dependencies\n\nEnsure you have the following NestJS packages installed:\n\n```bash\nnpm install @nestjs/common@^11.0.0 @nestjs/core@^11.0.0 reflect-metadata rxjs\n```\n\n## Quick Start\n\n### 1. Import the AuthModule\n\n```typescript\nimport { Module } from '@nestjs/common';\nimport { AuthModule } from '@bitovi-training/auth-middleware';\n\n@Module({\n  imports: [AuthModule],\n  controllers: [AppController],\n})\nexport class AppModule {}\n```\n\n### 2. Protect Routes with AuthGuard\n\n```typescript\nimport { Controller, Get, UseGuards } from '@nestjs/common';\nimport { AuthGuard, User, UserClaims } from '@bitovi-training/auth-middleware';\n\n@Controller('api')\n@UseGuards(AuthGuard)\nexport class ApiController {\n  @Get('profile')\n  getProfile(@User() user: UserClaims) {\n    return {\n      id: user.sub,\n      email: user.email,\n      roles: user.roles,\n    };\n  }\n}\n```\n\n### 3. Add Role-Based Access Control\n\n#### Any-Of Semantics (User needs ONE of the specified roles)\n\n```typescript\nimport { Controller, Get, UseGuards } from '@nestjs/common';\nimport { AuthGuard, RequireRolesGuard, Roles } from '@bitovi-training/auth-middleware';\n\n@Controller('admin')\n@UseGuards(AuthGuard, RequireRolesGuard)\nexport class AdminController {\n  @Get('dashboard')\n  @Roles('admin', 'moderator')\n  getDashboard() {\n    // User with 'admin' OR 'moderator' role can access\n    return { message: 'Admin dashboard' };\n  }\n}\n```\n\n#### All-Of Semantics (User needs ALL specified roles)\n\n```typescript\nimport { Controller, Delete, UseGuards } from '@nestjs/common';\nimport { AuthGuard, RequireAllRolesGuard, RequireAllRoles } from '@bitovi-training/auth-middleware';\n\n@Controller('admin')\n@UseGuards(AuthGuard, RequireAllRolesGuard)\nexport class AdminController {\n  @Delete('critical-operation')\n  @RequireAllRoles('admin', 'superuser')\n  criticalOperation() {\n    // User must have BOTH 'admin' AND 'superuser' roles\n    return { message: 'Operation complete' };\n  }\n}\n```\n\n## API Reference\n\n### Guards\n\n#### `AuthGuard`\n\nValidates JWT tokens and attaches user claims to the request.\n\n- Extracts Bearer token from `Authorization` header\n- Parses JWT payload and validates structure\n- Attaches `UserClaims` to `request.user`\n- Throws `InvalidTokenException` (401) if token is missing or invalid\n\n#### `RequireRolesGuard`\n\nEnforces any-of role semantics. User must have at least ONE of the specified roles.\n\n- Reads roles from `@Roles()` decorator\n- Throws `InsufficientPermissionsException` (403) if user lacks all required roles\n- Must be used after `AuthGuard`\n\n#### `RequireAllRolesGuard`\n\nEnforces all-of role semantics. User must have ALL of the specified roles.\n\n- Reads roles from `@RequireAllRoles()` decorator\n- Throws `InsufficientPermissionsException` (403) if user lacks any required role\n- Must be used after `AuthGuard`\n\n### Decorators\n\n#### `@User(property?: keyof UserClaims)`\n\nParameter decorator to extract user claims from request.\n\n```typescript\n// Get entire UserClaims object\n@Get('profile')\ngetProfile(@User() user: UserClaims) { }\n\n// Get specific property\n@Get('email')\ngetEmail(@User('email') email: string) { }\n\n@Get('roles')\ngetRoles(@User('roles') roles: string[]) { }\n```\n\n#### `@Roles(...roles: string[])`\n\nRoute decorator for any-of role requirements.\n\n```typescript\n@Roles('admin', 'moderator')\n@Get('dashboard')\ngetDashboard() { }\n```\n\n#### `@RequireAllRoles(...roles: string[])`\n\nRoute decorator for all-of role requirements.\n\n```typescript\n@RequireAllRoles('admin', 'superuser')\n@Delete('critical')\ncriticalOperation() { }\n```\n\n### Interfaces\n\n#### `UserClaims`\n\n```typescript\ninterface UserClaims {\n  sub: string;        // User ID (required)\n  email: string;      // User email (required)\n  roles: string[];    // User roles (defaults to [] if missing)\n  exp?: number;       // Token expiration (Unix timestamp)\n  iat?: number;       // Token issued at (Unix timestamp)\n}\n```\n\n### Exceptions\n\n#### `InvalidTokenException` (401 Unauthorized)\n\nThrown when:\n- Authorization header is missing\n- Token format is invalid (not Bearer scheme or not 3 parts)\n- Token payload cannot be decoded\n- Required claims (sub, email) are missing\n\n#### `InsufficientPermissionsException` (403 Forbidden)\n\nThrown when:\n- User lacks required roles\n\n## Token Format\n\nThe middleware expects JWT tokens in the `Authorization` header with Bearer scheme:\n\n```\nAuthorization: Bearer <token>\n```\n\nToken structure (3 parts separated by dots):\n\n```\n<header>.<payload>.<signature>\n```\n\nExample payload:\n\n```json\n{\n  \"sub\": \"user-123\",\n  \"email\": \"user@example.com\",\n  \"roles\": [\"admin\", \"user\"],\n  \"exp\": 1735689600,\n  \"iat\": 1735603200\n}\n```\n\n## Edge Cases & Behavior\n\n### Missing Roles Claim\n\nIf the `roles` claim is missing or not an array, defaults to empty array `[]` (permissive behavior).\n\n### Expired Tokens\n\nExpired tokens (where `exp < current time`) are **ACCEPTED** with a warning log. This is intentional for development environments.\n\n### Role Case Sensitivity\n\nRole comparisons are **case-sensitive**:\n- `\"admin\"` ≠ `\"Admin\"` ≠ `\"ADMIN\"`\n\n### Empty Roles Decorator\n\nIf `@Roles()` or `@RequireAllRoles()` is used with no arguments, the guard allows access (no roles required).\n\n## Logging\n\nThe middleware uses NestJS Logger with structured JSON output:\n\n```typescript\n// Authentication success\n{\n  \"level\": \"log\",\n  \"message\": \"Authentication successful\",\n  \"userId\": \"user-123\",\n  \"email\": \"user@example.com\",\n  \"rolesCount\": 2,\n  \"path\": \"/api/profile\",\n  \"method\": \"GET\"\n}\n\n// Authorization failure\n{\n  \"level\": \"warn\",\n  \"message\": \"Authorization failed: insufficient roles\",\n  \"userId\": \"user-123\",\n  \"userRoles\": [\"user\"],\n  \"requiredRoles\": [\"admin\", \"moderator\"],\n  \"path\": \"/admin/dashboard\",\n  \"method\": \"GET\"\n}\n```\n\n**Security**: Logs contain user IDs and role counts but **NOT** JWT tokens or sensitive claim data.\n\n## Production Migration\n\n⚠️ **This middleware does NOT verify JWT signatures** and should only be used in development/testing environments.\n\nFor production use, you must:\n\n1. **Add signature verification** using a library like `jsonwebtoken` or `passport-jwt`\n2. **Validate token issuer** (iss claim) against trusted issuers\n3. **Validate audience** (aud claim) to prevent token misuse\n4. **Use HTTPS** for all API endpoints\n5. **Implement token rotation** and revocation mechanisms\n6. **Add rate limiting** to prevent brute force attacks\n7. **Store secrets securely** (environment variables, secret managers)\n\nSee [quickstart.md](./specs/001-nestjs-mock-auth/quickstart.md) for detailed production migration guidance.\n\n## Requirements\n\n- **Node.js**: v20 LTS (minimum v16+)\n- **NestJS**: v11.x\n- **TypeScript**: v5.x\n\n## Development\n\n```bash\n# Install dependencies\nnpm install\n\n# Build\nnpm run build\n\n# Run tests\nnpm test\n\n# Run tests with coverage\nnpm run test:cov\n```\n\n## License\n\nMIT\n\n## Contributing\n\nContributions are welcome! Please ensure:\n- All code passes TypeScript strict mode\n- Unit tests achieve 90%+ coverage\n- JSDoc comments for all public APIs\n- No sensitive data in logs\n\n## Support\n\nFor issues and questions, please file a GitHub issue.\n\n---\n\n**Remember**: This is a MOCK authentication middleware. Do not use in production without proper JWT signature verification.\n","readmeFilename":"README.md"}