{"_id":"@ai-partner-x/aiko-boot-starter-security","_rev":"4-6089362d6344cd13e119237d1541b9d7","name":"@ai-partner-x/aiko-boot-starter-security","dist-tags":{"latest":"0.1.5"},"versions":{"0.1.3":{"name":"@ai-partner-x/aiko-boot-starter-security","version":"0.1.3","keywords":["aiko-boot","boot-starter-security","authentication","authorization","jwt","oauth2","rbac","spring-security","typescript"],"_id":"@ai-partner-x/aiko-boot-starter-security@0.1.3","maintainers":[{"name":"moyin333","email":"158182907@qq.com"}],"dist":{"shasum":"6edb098489867b90d6c10a2d08dc6dfb01a1cedf","tarball":"https://registry.npmjs.org/@ai-partner-x/aiko-boot-starter-security/-/aiko-boot-starter-security-0.1.3.tgz","fileCount":10,"integrity":"sha512-Ak4YUGCKMsaFyg5XlOcX4ZhEsXq7aKTQ9mWQsi+TGYgnm38ZWhdK1Ryl/+P/G8pXpZ9RmN93Irykeek4ldfZmA==","signatures":[{"sig":"MEYCIQDZw0LMk/FWGWe2lEYfT4BTX0zqLXZ/tK/rt+fXS2/nGQIhAOFx/6piFxXCmSECVIctvegehSk6VJUSDJhBEaKe9y6o","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":203665},"main":"./dist/index.js","type":"module","_from":"file:ai-partner-x-aiko-boot-starter-security-0.1.3.tgz","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"}},"scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","clean":"rm -rf dist","test:watch":"vitest","type-check":"tsc --noEmit","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"moyin333","email":"158182907@qq.com"},"_resolved":"/tmp/6e4c286935d61e863068f01353c7fb10/ai-partner-x-aiko-boot-starter-security-0.1.3.tgz","_integrity":"sha512-Ak4YUGCKMsaFyg5XlOcX4ZhEsXq7aKTQ9mWQsi+TGYgnm38ZWhdK1Ryl/+P/G8pXpZ9RmN93Irykeek4ldfZmA==","_npmVersion":"10.8.2","description":"Aiko Boot - Spring Boot style Security Starter with authentication and authorization","directories":{},"_nodeVersion":"20.20.1","dependencies":{"tslib":"^2.6.0","bcryptjs":"^2.4.3","passport":"^0.7.0","jsonwebtoken":"^9.0.2","passport-jwt":"^4.0.1","passport-local":"^1.0.0","passport-oauth2":"^1.8.0","reflect-metadata":"^0.2.1","@ai-partner-x/aiko-boot":"0.1.3"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","react":"^18.2.0","vitest":"^1.2.0","express":"^4.18.0","typescript":"^5.3.0","@types/node":"^20.11.0","@types/react":"^18.2.0","@types/express":"^4.17.21","@types/bcryptjs":"^2.4.6","@types/passport":"^1.0.16","express-session":"^1.17.3","@types/jsonwebtoken":"^9.0.5","@types/passport-jwt":"^4.0.1","@vitest/coverage-v8":"^1.2.0","@types/passport-local":"^1.0.38","@types/passport-oauth2":"^1.4.15"},"peerDependencies":{"react":">=17.0.0","express":">=4.0.0","express-session":">=1.0.0"},"_npmOperationalInternal":{"tmp":"tmp/aiko-boot-starter-security_0.1.3_1773857072539_0.3511137298014593","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"@ai-partner-x/aiko-boot-starter-security","version":"0.1.4","keywords":["aiko-boot","boot-starter-security","authentication","authorization","jwt","oauth2","rbac","spring-security","typescript"],"_id":"@ai-partner-x/aiko-boot-starter-security@0.1.4","maintainers":[{"name":"moyin333","email":"158182907@qq.com"}],"dist":{"shasum":"3e218bc9995627d6d0a34c3edf929c7fd125e049","tarball":"https://registry.npmjs.org/@ai-partner-x/aiko-boot-starter-security/-/aiko-boot-starter-security-0.1.4.tgz","fileCount":10,"integrity":"sha512-2sHVeL8fb4ut3Bj80rtkq/YUTX/irfSFRlgogqQ4OOgg1V38Mtt5RBJgYWA0XZgATv4r3aWC3fXZzukxXPkBLw==","signatures":[{"sig":"MEUCIEPgOdlh7PdN4gjLjBGhhhhiVneF6Jh7DSQJAvCgKxpBAiEAnG5NhBeHO/AxWDt3NwklwVQVRz21xDQmie3F7URkzvk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":203665},"main":"./dist/index.js","type":"module","_from":"file:ai-partner-x-aiko-boot-starter-security-0.1.4.tgz","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"}},"scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","clean":"rm -rf dist","test:watch":"vitest","type-check":"tsc --noEmit","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"moyin333","email":"158182907@qq.com"},"_resolved":"/tmp/b09ee72be2de12041700e561c21d277c/ai-partner-x-aiko-boot-starter-security-0.1.4.tgz","_integrity":"sha512-2sHVeL8fb4ut3Bj80rtkq/YUTX/irfSFRlgogqQ4OOgg1V38Mtt5RBJgYWA0XZgATv4r3aWC3fXZzukxXPkBLw==","_npmVersion":"10.8.2","description":"Aiko Boot - Spring Boot style Security Starter with authentication and authorization","directories":{},"_nodeVersion":"20.20.1","dependencies":{"tslib":"^2.6.0","bcryptjs":"^2.4.3","passport":"^0.7.0","jsonwebtoken":"^9.0.2","passport-jwt":"^4.0.1","passport-local":"^1.0.0","passport-oauth2":"^1.8.0","reflect-metadata":"^0.2.1","@ai-partner-x/aiko-boot":"0.1.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","react":"^18.2.0","vitest":"^1.2.0","express":"^4.18.0","typescript":"^5.3.0","@types/node":"^20.11.0","@types/react":"^18.2.0","@types/express":"^4.17.21","@types/bcryptjs":"^2.4.6","@types/passport":"^1.0.16","express-session":"^1.17.3","@types/jsonwebtoken":"^9.0.5","@types/passport-jwt":"^4.0.1","@vitest/coverage-v8":"^1.2.0","@types/passport-local":"^1.0.38","@types/passport-oauth2":"^1.4.15"},"peerDependencies":{"react":">=17.0.0","express":">=4.0.0","express-session":">=1.0.0"},"_npmOperationalInternal":{"tmp":"tmp/aiko-boot-starter-security_0.1.4_1773908282321_0.3183613094650848","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@ai-partner-x/aiko-boot-starter-security","version":"0.1.5","description":"Aiko Boot - Spring Boot style Security Starter with authentication and authorization","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./react":{"import":"./dist/react.js","types":"./dist/react.d.ts"}},"dependencies":{"bcryptjs":"^2.4.3","jsonwebtoken":"^9.0.2","passport":"^0.7.0","passport-jwt":"^4.0.1","passport-local":"^1.0.0","passport-oauth2":"^1.8.0","reflect-metadata":"^0.2.1","tslib":"^2.6.0","@ai-partner-x/aiko-boot":"0.1.5"},"peerDependencies":{"express":">=4.0.0","express-session":">=1.0.0","react":">=17.0.0"},"devDependencies":{"@types/bcryptjs":"^2.4.6","@types/express":"^4.17.21","@types/jsonwebtoken":"^9.0.5","@types/node":"^20.11.0","@types/passport":"^1.0.16","@types/passport-jwt":"^4.0.1","@types/passport-local":"^1.0.38","@types/passport-oauth2":"^1.4.15","@types/react":"^18.2.0","@vitest/coverage-v8":"^1.2.0","express":"^4.18.0","express-session":"^1.17.3","react":"^18.2.0","tsup":"^8.0.0","typescript":"^5.3.0","vitest":"^1.2.0"},"keywords":["aiko-boot","boot-starter-security","authentication","authorization","jwt","oauth2","rbac","spring-security","typescript"],"publishConfig":{"registry":"https://registry.npmjs.org","access":"public"},"scripts":{"build":"tsup","dev":"tsup --watch","type-check":"tsc --noEmit","test":"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage","clean":"rm -rf dist"},"_id":"@ai-partner-x/aiko-boot-starter-security@0.1.5","_integrity":"sha512-yVO7zefRpiAI+NCcHB0PrtwYlMEoaBfGz1wsP7/zruPlYr8WEhwlx79XFeSOWbPdlK4wiIglBgRIyXl1Dh4UBw==","_resolved":"/tmp/7a03d672ec231571ac68c64fc03e40af/ai-partner-x-aiko-boot-starter-security-0.1.5.tgz","_from":"file:ai-partner-x-aiko-boot-starter-security-0.1.5.tgz","_nodeVersion":"20.20.1","_npmVersion":"10.8.2","dist":{"integrity":"sha512-yVO7zefRpiAI+NCcHB0PrtwYlMEoaBfGz1wsP7/zruPlYr8WEhwlx79XFeSOWbPdlK4wiIglBgRIyXl1Dh4UBw==","shasum":"a98a1d0144c2dd317de95c28cbb38ac68cc87087","tarball":"https://registry.npmjs.org/@ai-partner-x/aiko-boot-starter-security/-/aiko-boot-starter-security-0.1.5.tgz","fileCount":10,"unpackedSize":203665,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIAXlnuEVjkhOKfACyuJ6udPJiwn193HF99WJ/hZWjPhyAiEAixTYuGg618cE0mWsTHsNA/Lrr9nvN/4IXKxroFHKbuU="}]},"_npmUser":{"name":"moyin333","email":"158182907@qq.com"},"directories":{},"maintainers":[{"name":"moyin333","email":"158182907@qq.com"},{"name":"liujin0528","email":"un0528@hotmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/aiko-boot-starter-security_0.1.5_1774102921752_0.9015140867929448"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-18T18:04:32.463Z","modified":"2026-03-21T14:22:02.073Z","0.1.3":"2026-03-18T18:04:32.716Z","0.1.4":"2026-03-19T08:18:02.464Z","0.1.5":"2026-03-21T14:22:01.919Z"},"keywords":["aiko-boot","boot-starter-security","authentication","authorization","jwt","oauth2","rbac","spring-security","typescript"],"description":"Aiko Boot - Spring Boot style Security Starter with authentication and authorization","maintainers":[{"name":"moyin333","email":"158182907@qq.com"},{"name":"liujin0528","email":"un0528@hotmail.com"}],"readme":"# @ai-partner-x/aiko-boot-starter-security\n\nAiko Boot Security Starter - Spring Boot style authentication and authorization for AI-First Framework.\n\n## Features\n\n- **Multiple Authentication Strategies**: JWT, OAuth2, Session, Local\n- **Role-Based Access Control (RBAC)**: Comprehensive permission system\n- **Declarative Security**: Decorator-based security configuration\n- **Auto Configuration**: Zero-config startup with sensible defaults\n- **Type Safe**: Full TypeScript support\n- **Java Compatible**: Decorators can be transpiled to Spring Security annotations\n\n## Installation\n\n```bash\npnpm add @ai-partner-x/aiko-boot-starter-security\n```\n\n## Quick Start\n\n```typescript\nimport { createApp } from '@ai-partner-x/aiko-boot';\nimport '@ai-partner-x/aiko-boot-starter-security';\n\nconst app = await createApp({ srcDir: __dirname });\napp.run();\n```\n\n## Usage\n\n### Controller with Security Decorators\n\n```typescript\nimport { RestController, GetMapping, PostMapping } from '@ai-partner-x/aiko-boot-starter-web';\nimport { Public, PreAuthorize, RolesAllowed } from '@ai-partner-x/aiko-boot-starter-security';\n\n@RestController({ path: '/api/users' })\nexport class UserController {\n  @GetMapping()\n  @PreAuthorize(\"hasRole('ADMIN')\")\n  async list(): Promise<User[]> {\n    return this.userService.getAllUsers();\n  }\n\n  @GetMapping('/public')\n  @Public()\n  async publicInfo(): Promise<any> {\n    return { message: 'Public API' };\n  }\n}\n```\n\n### Configuration\n\n```typescript\nimport type { AppConfig } from '@ai-partner-x/aiko-boot';\n\nexport default {\n  security: {\n    enabled: true,\n    jwt: {\n      secret: process.env.JWT_SECRET, // REQUIRED in production!\n      expiresIn: '1h', // Shorter expiration for production\n    },\n    publicPaths: ['/api/auth/login', '/api/auth/register'],\n  },\n} satisfies AppConfig;\n```\n\n## Decorators\n\n### Authentication\n\n- `@Public()` - Mark endpoint as publicly accessible\n- `@Authenticated()` - Require authentication\n- `@RolesAllowed(...roles)` - Require specific roles\n\n### Authorization\n\n- `@PreAuthorize(expression)` - Pre-authorization check\n- `@PostAuthorize(expression)` - Post-authorization check\n- `@Secured(...permissions)` - Require specific permissions\n\n## Permission Expressions\n\n- `hasRole('ROLE_NAME')` - Check if user has role\n- `hasPermission('permission:name')` - Check if user has permission\n- `hasAnyRole('ROLE1', 'ROLE2')` - Check if user has any of the roles\n- `hasAllRoles('ROLE1', 'ROLE2')` - Check if user has all roles\n- `authenticated()` - Check if user is authenticated\n\n## React Integration\n\n```typescript\nimport { SecurityProvider, useSecurity, HasPermission } from '@ai-partner-x/aiko-boot-starter-security/react';\n\nfunction App() {\n  return (\n    <SecurityProvider>\n      <Dashboard />\n    </SecurityProvider>\n  );\n}\n\nfunction Dashboard() {\n  const { user, isAuthenticated, hasRole } = useSecurity();\n  \n  if (!isAuthenticated) {\n    return <Login />;\n  }\n  \n  return (\n    <HasPermission permission=\"user:read\">\n      <UserList />\n    </HasPermission>\n  );\n}\n```\n\n## Security Best Practices\n\n### Production Configuration\n\n**CRITICAL**: Never use default secret keys in production!\n\n```typescript\n// ❌ NEVER do this in production\nconst config = {\n  security: {\n    jwt: { secret: 'your-secret-key' } // INSECURE!\n  }\n};\n\n// ✅ Always use environment variables\nconst config = {\n  security: {\n    jwt: { \n      secret: process.env.JWT_SECRET, // Required!\n      expiresIn: '1h'\n    },\n    session: {\n      secret: process.env.SESSION_SECRET // Required!\n    }\n  }\n};\n```\n\n### Rate Limiting\n\nProtect your authentication endpoints from brute force attacks:\n\n```typescript\nimport express from 'express';\nimport rateLimit from 'express-rate-limit';\n\nconst app = express();\n\n// Rate limit login endpoint\nconst loginLimiter = rateLimit({\n  windowMs: 15 * 60 * 1000, // 15 minutes\n  max: 5, // 5 attempts per window\n  message: { error: 'Too many login attempts, please try again later' },\n  standardHeaders: true,\n  legacyHeaders: false,\n});\n\n// Apply to login endpoint\napp.post('/api/auth/login', loginLimiter, authController.login);\n\n// Stricter rate limit for password reset\nconst passwordResetLimiter = rateLimit({\n  windowMs: 60 * 60 * 1000, // 1 hour\n  max: 3, // 3 attempts per hour\n});\n\napp.post('/api/auth/forgot-password', passwordResetLimiter, authController.forgotPassword);\n```\n\n### Password Security\n\n- Use strong password hashing (bcrypt with cost factor >= 10)\n- Enforce minimum password length (>= 8 characters)\n- Consider password complexity requirements\n- Implement password breach detection\n\n```typescript\n// Example: Strong password validation\nconst validatePassword = (password: string): boolean => {\n  if (password.length < 8) return false;\n  if (!/[A-Z]/.test(password)) return false; // Uppercase\n  if (!/[a-z]/.test(password)) return false; // Lowercase\n  if (!/[0-9]/.test(password)) return false; // Number\n  if (!/[!@#$%^&*]/.test(password)) return false; // Special char\n  return true;\n};\n```\n\n### Token Security\n\n- Use short expiration times for access tokens (15-60 minutes)\n- Implement refresh token rotation\n- Store tokens securely (httpOnly cookies for web)\n- Implement token revocation for logout\n\n### CORS Configuration\n\n```typescript\nconst config = {\n  security: {\n    cors: {\n      enabled: true,\n      origin: ['https://yourdomain.com'], // Specify exact origins\n      credentials: true,\n    }\n  }\n};\n```\n\n### Sensitive Data Protection\n\nThe `sanitizeUser` method automatically excludes sensitive fields:\n\n```typescript\n// These fields are automatically excluded from API responses:\n// - password, passwordHash\n// - salt, token, refreshToken\n// - secret, apiKey, privateKey\n```\n\n## API Reference\n\n### AuthService\n\n```typescript\ninterface AuthService {\n  login(credentials: LoginDto): Promise<LoginResult>;\n  register(userData: RegisterDto): Promise<User>;\n  refreshToken(refreshToken: string): Promise<LoginResult>;\n  logout(token: string): Promise<void>;\n  changePassword(userId: number, oldPassword: string, newPassword: string): Promise<boolean>;\n}\n```\n\n### PermissionService\n\n```typescript\ninterface PermissionService {\n  hasPermission(user: User, permission: string): Promise<boolean>;\n  hasPermissions(user: User, permissions: string[]): Promise<boolean>;\n  hasAnyPermission(user: User, permissions: string[]): Promise<boolean>;\n  hasRole(user: User, role: string): boolean;\n  hasAllRoles(user: User, roles: string[]): boolean;\n  hasAnyRole(user: User, roles: string[]): boolean;\n}\n```\n\n### SecurityContext\n\n```typescript\ninterface SecurityContext {\n  getCurrentUser(): User | null;\n  setCurrentUser(user: User | null): void;\n  isAuthenticated(): boolean;\n  hasRole(role: string): boolean;\n  hasAnyRole(roles: string[]): boolean;\n  clear(): void;\n}\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}