# JWT Authentication System - Retail POS API ## Overview A complete JWT-based authentication system for the NestJS Retail POS backend, implementing secure user authentication, role-based access control (RBAC), and comprehensive user management. ## Features - JWT authentication with Passport.js - Role-based access control (Admin, Manager, Cashier, User) - Secure password hashing with bcrypt (10 rounds) - Global authentication guards with public route support - Token validation and refresh mechanism - User management with CRUD operations - Swagger API documentation - TypeORM database integration --- ## Architecture ### Modules 1. **AuthModule** (`src/modules/auth/`) - Authentication logic - JWT token generation and validation - Login and registration endpoints - Password validation 2. **UsersModule** (`src/modules/users/`) - User CRUD operations - User repository pattern - Role management 3. **Common Guards** (`src/common/guards/`) - Global JWT authentication guard - Role-based authorization guard 4. **Common Decorators** (`src/common/decorators/`) - @CurrentUser() - Extract user from request - @Public() - Mark routes as public - @Roles() - Specify required roles --- ## User Roles ```typescript enum UserRole { ADMIN = 'admin', // Full access to all endpoints MANAGER = 'manager', // Product and category management CASHIER = 'cashier', // Transaction processing only USER = 'user', // Read-only access } ``` --- ## API Endpoints ### Authentication Endpoints #### 1. Register User ```http POST /api/auth/register Content-Type: application/json { "name": "John Doe", "email": "john@example.com", "password": "Password123!", "roles": ["user"] // Optional, defaults to ["user"] } ``` **Response:** ```json { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "user": { "id": "uuid", "name": "John Doe", "email": "john@example.com", "roles": ["user"], "isActive": true, "createdAt": "2025-01-15T10:00:00.000Z" } } ``` **Validation Rules:** - Name: Required, max 255 characters - Email: Valid email format, unique - Password: Min 8 characters, must contain uppercase, lowercase, and number - Roles: Optional array of valid UserRole values --- #### 2. Login User ```http POST /api/auth/login Content-Type: application/json { "email": "admin@retailpos.com", "password": "Admin123!" } ``` **Response:** ```json { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "user": { "id": "uuid", "name": "Admin User", "email": "admin@retailpos.com", "roles": ["admin"], "isActive": true, "createdAt": "2025-01-15T10:00:00.000Z" } } ``` --- #### 3. Get Current User Profile ```http GET /api/auth/profile Authorization: Bearer ``` **Response:** ```json { "success": true, "data": { "id": "uuid", "email": "admin@retailpos.com", "name": "Admin User", "roles": ["admin"], "isActive": true } } ``` --- #### 4. Refresh Access Token ```http POST /api/auth/refresh Authorization: Bearer ``` **Response:** ```json { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "user": { "id": "uuid", "name": "Admin User", "email": "admin@retailpos.com", "roles": ["admin"], "isActive": true, "createdAt": "2025-01-15T10:00:00.000Z" } } ``` --- ### User Management Endpoints (Protected) #### 1. Get All Users (Admin/Manager) ```http GET /api/users Authorization: Bearer ``` **Required Roles:** Admin, Manager --- #### 2. Get User by ID (Admin/Manager) ```http GET /api/users/:id Authorization: Bearer ``` **Required Roles:** Admin, Manager --- #### 3. Create User (Admin Only) ```http POST /api/users Authorization: Bearer Content-Type: application/json { "name": "New User", "email": "newuser@example.com", "password": "Password123!", "roles": ["cashier"], "isActive": true } ``` **Required Roles:** Admin --- #### 4. Update User (Admin Only) ```http PATCH /api/users/:id Authorization: Bearer Content-Type: application/json { "name": "Updated Name", "roles": ["manager"], "isActive": false } ``` **Required Roles:** Admin **Note:** Password cannot be updated via this endpoint --- #### 5. Delete User (Admin Only) ```http DELETE /api/users/:id Authorization: Bearer ``` **Required Roles:** Admin **Response:** 204 No Content --- ## Usage Examples ### 1. Using @Public() Decorator Mark routes as public (skip JWT authentication): ```typescript @Controller('products') export class ProductsController { @Get() @Public() // This route is accessible without authentication async findAll() { return this.productsService.findAll(); } @Post() // This route requires authentication (global guard) async create(@Body() dto: CreateProductDto) { return this.productsService.create(dto); } } ``` --- ### 2. Using @Roles() Decorator Restrict routes to specific roles: ```typescript @Controller('products') export class ProductsController { @Post() @Roles(UserRole.ADMIN, UserRole.MANAGER) // Only admin and manager can create async create(@Body() dto: CreateProductDto) { return this.productsService.create(dto); } @Delete(':id') @Roles(UserRole.ADMIN) // Only admin can delete async remove(@Param('id') id: string) { return this.productsService.remove(id); } } ``` --- ### 3. Using @CurrentUser() Decorator Extract current user from request: ```typescript @Controller('profile') export class ProfileController { @Get() @UseGuards(JwtAuthGuard) async getProfile(@CurrentUser() user: User) { // user object is automatically extracted from request return { id: user.id, email: user.email, name: user.name, }; } } ``` --- ## Security Features ### Password Security - **Hashing Algorithm:** bcrypt with 10 salt rounds - **Validation Rules:** - Minimum 8 characters - At least one uppercase letter - At least one lowercase letter - At least one number - **Password Exclusion:** Password field is never returned in API responses (@Exclude decorator) ### JWT Configuration - **Secret:** Configured via JWT_SECRET environment variable - **Expiration:** 1 day (configurable via JWT_EXPIRES_IN) - **Token Storage:** Client-side (localStorage or secure storage) - **Token Format:** Bearer token in Authorization header ### Global Guards - **JWT Authentication:** Applied globally to all routes - **Public Routes:** Use @Public() decorator to bypass authentication - **Role-Based Access:** Use @Roles() decorator for authorization --- ## Database Schema ### Users Table ```sql CREATE TABLE users ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), name VARCHAR(255) NOT NULL, email VARCHAR(255) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL, roles TEXT NOT NULL DEFAULT 'user', isActive BOOLEAN DEFAULT true, createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, INDEX idx_users_email (email) ); ``` --- ## Environment Variables ```bash # JWT Configuration JWT_SECRET=retail-pos-super-secret-key-change-in-production-2025 JWT_EXPIRES_IN=1d # Database DB_HOST=localhost DB_PORT=5432 DB_USERNAME=postgres DB_PASSWORD=postgres DB_DATABASE=retail_pos # Bcrypt BCRYPT_ROUNDS=10 ``` --- ## Setup Instructions ### 1. Install Dependencies All required dependencies are already installed: - @nestjs/jwt - @nestjs/passport - passport - passport-jwt - bcrypt ### 2. Run Database Migration ```bash npm run migration:run ``` ### 3. Seed Default Users ```bash npm run seed:run ``` This creates three default users: - **Admin:** admin@retailpos.com / Admin123! - **Manager:** manager@retailpos.com / Manager123! - **Cashier:** cashier@retailpos.com / Cashier123! ### 4. Start Development Server ```bash npm run start:dev ``` ### 5. Access Swagger Documentation Open browser: http://localhost:3000/api/docs --- ## Testing the Authentication System ### 1. Test Login ```bash curl -X POST http://localhost:3000/api/auth/login \ -H "Content-Type: application/json" \ -d '{ "email": "admin@retailpos.com", "password": "Admin123!" }' ``` ### 2. Test Protected Endpoint ```bash # Get the access_token from login response curl -X GET http://localhost:3000/api/auth/profile \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` ### 3. Test Role-Based Access ```bash # Admin only endpoint (get all users) curl -X GET http://localhost:3000/api/users \ -H "Authorization: Bearer YOUR_ADMIN_TOKEN" ``` --- ## File Structure ``` src/ ├── modules/ │ ├── auth/ │ │ ├── dto/ │ │ │ ├── login.dto.ts │ │ │ ├── register.dto.ts │ │ │ ├── auth-response.dto.ts │ │ │ └── index.ts │ │ ├── guards/ │ │ │ ├── jwt-auth.guard.ts │ │ │ └── local-auth.guard.ts │ │ ├── interfaces/ │ │ │ └── jwt-payload.interface.ts │ │ ├── strategies/ │ │ │ ├── jwt.strategy.ts │ │ │ └── local.strategy.ts │ │ ├── auth.controller.ts │ │ ├── auth.service.ts │ │ └── auth.module.ts │ └── users/ │ ├── dto/ │ │ ├── create-user.dto.ts │ │ ├── update-user.dto.ts │ │ ├── user-response.dto.ts │ │ └── index.ts │ ├── entities/ │ │ └── user.entity.ts │ ├── users.controller.ts │ ├── users.service.ts │ ├── users.repository.ts │ └── users.module.ts ├── common/ │ ├── decorators/ │ │ ├── current-user.decorator.ts │ │ ├── public.decorator.ts │ │ ├── roles.decorator.ts │ │ └── index.ts │ └── guards/ │ ├── jwt-auth.guard.ts │ ├── roles.guard.ts │ └── index.ts └── database/ ├── migrations/ │ └── 1704470000000-CreateUsersTable.ts └── seeds/ ├── users.seed.ts └── run-seeds.ts ``` --- ## Best Practices 1. **Never log passwords** - Always hash before storing 2. **Use HTTPS in production** - Never send tokens over HTTP 3. **Rotate JWT secrets regularly** - Update JWT_SECRET periodically 4. **Implement refresh tokens** - For long-lived sessions 5. **Log authentication events** - Track login attempts and failures 6. **Rate limit auth endpoints** - Prevent brute force attacks 7. **Validate all inputs** - Use DTOs with class-validator 8. **Handle token expiration** - Provide clear error messages 9. **Use strong passwords** - Enforce password complexity 10. **Implement account lockout** - After multiple failed attempts --- ## Error Responses ### 400 Bad Request ```json { "success": false, "error": { "statusCode": 400, "message": "Validation failed", "details": [ "password must be at least 8 characters long", "email must be a valid email address" ] }, "timestamp": "2025-01-15T10:00:00.000Z", "path": "/api/auth/register" } ``` ### 401 Unauthorized ```json { "success": false, "error": { "statusCode": 401, "message": "Invalid credentials" }, "timestamp": "2025-01-15T10:00:00.000Z", "path": "/api/auth/login" } ``` ### 403 Forbidden ```json { "success": false, "error": { "statusCode": 403, "message": "Insufficient permissions" }, "timestamp": "2025-01-15T10:00:00.000Z", "path": "/api/users" } ``` ### 409 Conflict ```json { "success": false, "error": { "statusCode": 409, "message": "Email already registered" }, "timestamp": "2025-01-15T10:00:00.000Z", "path": "/api/auth/register" } ``` --- ## Next Steps 1. **Implement Refresh Tokens:** Add refresh token table and rotation logic 2. **Add Email Verification:** Send verification emails on registration 3. **Implement Password Reset:** Forgot password functionality 4. **Add Two-Factor Authentication:** Enhanced security with 2FA 5. **Implement Session Management:** Track active sessions 6. **Add Rate Limiting:** Protect against brute force attacks 7. **Implement Account Lockout:** Lock accounts after failed attempts 8. **Add Audit Logging:** Track all authentication events 9. **Implement Social Login:** Google, Facebook, etc. 10. **Add API Key Authentication:** For service-to-service communication --- ## Support For issues or questions: - GitHub Issues: [Create an issue](https://github.com/yourusername/retail-pos) - Email: support@retailpos.com - Documentation: http://localhost:3000/api/docs