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 includes patterns and plugins for authentication and authorization (confirm APIs against your installed version and the changelog):
- 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 { Veloce, AuthPlugin } from 'veloce-ts';import bcrypt from 'bcrypt';
const app = new Veloce();
app.usePlugin(new AuthPlugin({ jwt: { secret: process.env.JWT_SECRET || 'your-secret-key', expiresIn: '1h', refreshExpiresIn: '7d', }, userProvider: { findByCredentials: async (username: string, password: string) => { // Find user by username/email and verify password const user = await userService.findByUsername(username); if (!user) return null; const isValid = await bcrypt.compare(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”import { RBACPlugin } from 'veloce-ts/auth';
// Must be installed after AuthPluginapp.usePlugin(new RBACPlugin({ roles: [ { name: 'admin', level: 100, permissions: ['users.*', 'tasks.*', 'admin.*'] }, { name: 'manager', level: 80, permissions: ['tasks.*', 'teams.*'] }, { name: 'team_lead', level: 60, permissions: ['tasks.create', 'tasks.read', 'tasks.update'] }, { name: 'developer', level: 40, permissions: ['tasks.create', 'tasks.read', 'tasks.update'] }, { name: 'viewer', level: 20, permissions: ['tasks.read', 'users.read'] }, ],}));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 (pass as array)@Post('/users')@Permissions(['users.create'])async createUser(@Body() userData: any) { return await userService.create(userData);}
// Multiple permissions — user needs ANY of these (default)@Put('/users/:id')@Permissions(['users.update', 'users.read'])async updateUser(@Param('id') id: string, @Body() userData: any) { return await userService.update(id, userData);}
// Require ALL permissions + minimum role@Delete('/users/:id')@Permissions({ permissions: ['users.delete'], requireAll: true })@MinimumRole('manager')async 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”Use the built-in @RateLimit decorator per route, or createRateLimitMiddleware for global middleware:
import { Post, RateLimit } from 'veloce-ts';
// Per-route declarative rate limiting@Post('/login')@RateLimit({ windowMs: 15 * 60 * 1000, max: 5 })async login(@Body(LoginSchema) credentials: any) { // ...}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
- Plugins Guide - Using AuthPlugin, RBACPlugin, and PermissionPlugin
- Decorators Guide - Full decorator reference
- API Reference - Complete API documentation