Authentication & Authorization
Authentication & Authorization
Section titled “Authentication & Authorization”Learn how to implement secure authentication and role-based access control (RBAC) in your Veloce-TS applications.
Table of Contents
Section titled “Table of Contents”- Overview
- Authentication Setup
- RBAC Configuration
- Decorators
- User Management
- Security Best Practices
- Examples
Overview
Section titled “Overview”Veloce-TS v0.2.6 provides a comprehensive authentication and authorization system:
- JWT-based Authentication with access and refresh tokens
- Role-Based Access Control (RBAC) with hierarchical roles
- Permission-based Authorization for fine-grained access control
- User Management with password hashing and validation
- Session Management (optional)
Authentication Setup
Section titled “Authentication Setup”1. Install Authentication Plugin
Section titled “1. Install Authentication Plugin”import { VeloceTS } from 'veloce-ts';
const app = new VeloceTS();
app.install('auth', { jwt: { secret: process.env.JWT_SECRET || 'your-secret-key', accessTokenTTL: 3600, // 1 hour refreshTokenTTL: 86400, // 24 hours }, userProvider: { findByCredentials: async (username: string, password: string) => { // Find user by username/email const user = await userService.findByUsername(username); if (!user) return null;
// Verify password const isValid = await userService.verifyPassword(password, user.password); return isValid ? user : null; }, findById: async (id: string) => { return await userService.findById(id); }, hashPassword: async (password: string) => { return await bcrypt.hash(password, 10); }, verifyPassword: async (password: string, hash: string) => { return await bcrypt.compare(password, hash); } }});2. Create Authentication Controller
Section titled “2. Create Authentication Controller”import { Controller, Post, Get, Body, Auth, CurrentUser} from 'veloce-ts';import { z } from 'zod';
const LoginSchema = z.object({ username: z.string().min(1), password: z.string().min(6)});
const RegisterSchema = z.object({ username: z.string().min(3).max(50), email: z.string().email(), password: z.string().min(6)});
@Controller('/auth')export class AuthController {
@Post('/login') async login(@Body(LoginSchema) credentials: z.infer<typeof LoginSchema>) { const user = await userService.validateCredentials( credentials.username, credentials.password );
if (!user) { throw new UnauthorizedException('Invalid credentials'); }
const tokens = authService.generateTokens({ sub: user.id, username: user.username, email: user.email, role: user.role, permissions: user.permissions });
return { accessToken: tokens.accessToken, refreshToken: tokens.refreshToken, user: { id: user.id, username: user.username, email: user.email, role: user.role } }; }
@Post('/register') async register(@Body(RegisterSchema) userData: z.infer<typeof RegisterSchema>) { const existingUser = await userService.findByUsername(userData.username); if (existingUser) { throw new ConflictException('Username already exists'); }
const hashedPassword = await userService.hashPassword(userData.password); const user = await userService.create({ ...userData, password: hashedPassword, role: 'viewer', // Default role permissions: ['tasks.read'] // Default permissions });
return { message: 'User created successfully', user: { id: user.id, username: user.username, email: user.email, role: user.role } }; }
@Post('/refresh') async refresh(@Body() body: { refreshToken: string }) { try { const tokens = await authService.refreshToken(body.refreshToken); return tokens; } catch (error) { throw new UnauthorizedException('Invalid refresh token'); } }
@Get('/me') @Auth() async getProfile(@CurrentUser() user: any) { return { id: user.id, username: user.username, email: user.email, role: user.role, permissions: user.permissions }; }
@Post('/logout') @Auth() async logout(@CurrentUser() user: any) { // Invalidate refresh token await authService.invalidateRefreshToken(user.id); return { message: 'Logged out successfully' }; }}RBAC Configuration
Section titled “RBAC Configuration”1. Install RBAC Plugin
Section titled “1. Install RBAC Plugin”app.install('rbac', { roles: [ { name: 'admin', level: 100, description: 'Full system access' }, { name: 'manager', level: 80, description: 'Team management access' }, { name: 'team_lead', level: 60, description: 'Team lead access' }, { name: 'developer', level: 40, description: 'Developer access' }, { name: 'viewer', level: 20, description: 'Read-only access' } ], permissions: [ // User permissions 'users.create', 'users.read', 'users.update', 'users.delete', 'users.list', 'users.change_role',
// Task permissions 'tasks.create', 'tasks.read', 'tasks.update', 'tasks.delete', 'tasks.assign', 'tasks.complete',
// Team permissions 'teams.create', 'teams.read', 'teams.update', 'teams.delete', 'teams.add_member', 'teams.remove_member',
// Admin permissions 'admin.users', 'admin.tasks', 'admin.teams', 'admin.analytics' ]});2. Role Hierarchy
Section titled “2. Role Hierarchy”Roles are hierarchical based on their level:
- Admin (100): Full access to everything
- Manager (80): Can manage teams and users
- Team Lead (60): Can manage team tasks
- Developer (40): Can create and update tasks
- Viewer (20): Read-only access
Decorators
Section titled “Decorators”Authentication Decorators
Section titled “Authentication Decorators”// Require authentication@Get('/protected')@Auth()async protectedRoute(@CurrentUser() user: any) { return { message: 'This is protected', user: user.username };}Role-Based Decorators
Section titled “Role-Based Decorators”// Require minimum role level@Get('/admin-only')@MinimumRole('admin')async adminOnly() { return { message: 'Admin access granted' };}
@Get('/manager-up')@MinimumRole('manager')async managerUp() { return { message: 'Manager level access granted' };}Permission-Based Decorators
Section titled “Permission-Based Decorators”// Single permission@Post('/users')@Permissions('users.create')async createUser(@Body() userData: any) { return await userService.create(userData);}
// Multiple permissions (user needs ALL)@Put('/users/:id')@Permissions('users.update', 'users.read')async updateUser(@Param('id') id: string, @Body() userData: any) { return await userService.update(id, userData);}
// Complex permission checks@Delete('/users/:id')@Permissions('users.delete')@MinimumRole('manager') // Also require manager roleasync deleteUser(@Param('id') id: string) { return await userService.delete(id);}User Management
Section titled “User Management”User Service Example
Section titled “User Service Example”import { Injectable } from 'veloce-ts';import bcrypt from 'bcrypt';
@Injectable('singleton')export class UserService {
async findByUsername(username: string): Promise<User | null> { // Your database query logic return await this.db.query('SELECT * FROM users WHERE username = ?', [username]); }
async findById(id: string): Promise<User | null> { return await this.db.query('SELECT * FROM users WHERE id = ?', [id]); }
async validateCredentials(username: string, password: string): Promise<User | null> { const user = await this.findByUsername(username); if (!user) return null;
const isValid = await this.verifyPassword(password, user.password); return isValid ? user : null; }
async hashPassword(password: string): Promise<string> { return await bcrypt.hash(password, 10); }
async verifyPassword(password: string, hash: string): Promise<boolean> { return await bcrypt.compare(password, hash); }
async create(userData: CreateUserDto): Promise<User> { const hashedPassword = await this.hashPassword(userData.password);
const user = { ...userData, password: hashedPassword, id: generateId(), createdAt: new Date(), updatedAt: new Date() };
await this.db.query( 'INSERT INTO users (id, username, email, password, role, permissions) VALUES (?, ?, ?, ?, ?, ?)', [user.id, user.username, user.email, user.password, user.role, JSON.stringify(user.permissions)] );
return user; }}Security Best Practices
Section titled “Security Best Practices”1. Environment Variables
Section titled “1. Environment Variables”JWT_SECRET=your-super-secret-jwt-key-hereJWT_ACCESS_TTL=3600JWT_REFRESH_TTL=86400BCRYPT_ROUNDS=122. Password Security
Section titled “2. Password Security”// Use strong password requirementsconst PasswordSchema = z.string() .min(8, 'Password must be at least 8 characters') .regex(/[A-Z]/, 'Password must contain uppercase letter') .regex(/[a-z]/, 'Password must contain lowercase letter') .regex(/[0-9]/, 'Password must contain number') .regex(/[^A-Za-z0-9]/, 'Password must contain special character');3. Token Management
Section titled “3. Token Management”// Implement token blacklisting@Injectable('singleton')export class TokenService { private blacklistedTokens = new Set<string>();
blacklistToken(tokenId: string) { this.blacklistedTokens.add(tokenId); }
isTokenBlacklisted(tokenId: string): boolean { return this.blacklistedTokens.has(tokenId); }}4. Rate Limiting
Section titled “4. Rate Limiting”import { rateLimit } from 'veloce-ts/middleware';
// Apply rate limiting to auth endpointsapp.use('/auth/login', rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 5 // 5 attempts per window}));Examples
Section titled “Examples”Complete Authentication Flow
Section titled “Complete Authentication Flow”// 1. Register userPOST /auth/register{ "username": "johndoe", "email": "john@example.com", "password": "SecurePass123!"}
// 2. LoginPOST /auth/login{ "username": "johndoe", "password": "SecurePass123!"}
// Response:{ "accessToken": "eyJhbGciOiJIUzI1NiIs...", "refreshToken": "eyJhbGciOiJIUzI1NiIs...", "user": { "id": "123", "username": "johndoe", "email": "john@example.com", "role": "viewer" }}
// 3. Use protected endpointGET /auth/meAuthorization: Bearer eyJhbGciOiJIUzI1NiIs...
// 4. Use role-protected endpointGET /admin/dashboardAuthorization: Bearer eyJhbGciOiJIUzI1NiIs...Role-Based Dashboard
Section titled “Role-Based Dashboard”@Controller('/dashboard')export class DashboardController {
@Get('/') @Auth() async getDashboard(@CurrentUser() user: any) { const baseDashboard = { user: { id: user.id, username: user.username, role: user.role } };
// Add role-specific data if (user.role === 'admin') { return { ...baseDashboard, adminStats: await this.getAdminStats(), systemHealth: await this.getSystemHealth() }; }
if (user.role === 'manager') { return { ...baseDashboard, teamStats: await this.getTeamStats(user.id), pendingApprovals: await this.getPendingApprovals(user.id) }; }
return { ...baseDashboard, myTasks: await this.getUserTasks(user.id), notifications: await this.getUserNotifications(user.id) }; }
@Get('/admin-stats') @MinimumRole('admin') async getAdminStats() { return { totalUsers: await this.userService.count(), totalTasks: await this.taskService.count(), systemUptime: process.uptime() }; }}Next Steps
Section titled “Next Steps”- TaskMaster Example - See authentication in action
- RBAC Guide - Advanced role management
- Security Guide - Security best practices
- Middleware Guide - Custom authentication middleware