Authentication Middleware
Middleware provides automatic authentication for routes. Khadem offers flexible middleware for both API and web authentication with support for roles, permissions, and custom logic.
AuthMiddleware
Bearer, Basic, API Key authentication
WebAuthMiddleware
Session-based web authentication
Custom Middleware
Build your own auth logic
AuthMiddleware - API Authentication
AuthMiddleware authenticates API requests using Bearer tokens, Basic auth, or API keys. It automatically extracts credentials, verifies them, and attaches user data to requests.
dart
import 'package:khadem/khadem.dart';
// Basic Bearer token authentication
class ApiController {
static final authMiddleware = AuthMiddleware.bearer();
static Future<void> profile(Request req, Response res) async {
// User is already authenticated by middleware
final user = req.authenticatable;
if (user == null) {
return res.status(401).sendJson({'error': 'Unauthenticated'});
}
res.sendJson({
'user': user.toAuthArray(),
});
}
}
// Apply middleware to routes
void defineRoutes() {
// Single route
Route.get('/api/profile', ApiController.profile)
.middleware([AuthMiddleware.bearer()]);
// Route group
Route.group(() {
Route.get('/profile', ApiController.profile);
Route.get('/settings', ApiController.settings);
Route.post('/update', ApiController.update);
}, middleware: [AuthMiddleware.bearer()]);
}
dart
import 'package:khadem/khadem.dart';
class AuthMiddlewareTypes {
// Bearer token authentication (most common for APIs)
static final bearer = AuthMiddleware.bearer();
// Basic authentication (username:password in header)
static final basic = AuthMiddleware.basic(realm: 'My API');
// API key authentication (custom header)
static final apiKey = AuthMiddleware.apiKey('X-API-Key');
// Custom authentication
static final custom = AuthMiddleware.custom(
AuthType.bearer,
authenticator: (request) async {
final token = request.header('x-custom-token');
if (token == null) return null;
// Custom authentication logic
final auth = AuthManager();
return await auth.user(token);
},
);
}
// Usage examples
void defineRoutes() {
// Bearer token
Route.get('/api/v1/users', UserController.index)
.middleware([AuthMiddlewareTypes.bearer]);
// Basic auth
Route.get('/api/legacy/data', LegacyController.data)
.middleware([AuthMiddlewareTypes.basic]);
// API key
Route.post('/webhooks/stripe', WebhookController.stripe)
.middleware([AuthMiddlewareTypes.apiKey]);
// Custom auth
Route.get('/api/special', SpecialController.data)
.middleware([AuthMiddlewareTypes.custom]);
}
Protecting Routes with Middleware
Apply middleware to routes to automatically require authentication. Use route groups to apply middleware to multiple routes at once.
dart
import 'package:khadem/khadem.dart';
void defineRoutes() {
// Public routes (no middleware)
Route.get('/', HomeController.index);
Route.get('/about', HomeController.about);
// API routes with authentication
Route.group(() {
Route.get('/profile', UserController.profile);
Route.put('/profile', UserController.updateProfile);
Route.post('/avatar', UserController.uploadAvatar);
Route.delete('/account', UserController.deleteAccount);
}, middleware: [AuthMiddleware.bearer()], prefix: '/api');
// Admin routes with authentication
Route.group(() {
Route.get('/dashboard', AdminController.dashboard);
Route.get('/users', AdminController.users);
Route.post('/users/:id/ban', AdminController.banUser);
}, middleware: [AuthMiddleware.bearer()], prefix: '/api/admin');
// Mixed auth on different routes
Route.get('/api/public/posts', PostController.index); // No auth
Route.post('/api/posts', PostController.create) // Auth required
.middleware([AuthMiddleware.bearer()]);
}
Role-Based Access Control
Restrict routes to specific roles using the withRoles() method. Users without the required role will receive a 403 Forbidden response.
dart
import 'package:khadem/khadem.dart';
class RoleProtectedRoutes {
// Admin-only middleware
static final adminAuth = AuthMiddleware.bearer()
.withRoles(['admin']);
// Admin or moderator
static final moderatorAuth = AuthMiddleware.bearer()
.withRoles(['admin', 'moderator']);
// Editor only
static final editorAuth = AuthMiddleware.bearer()
.withRoles(['editor']);
}
void defineRoutes() {
// Admin-only routes
Route.group(() {
Route.get('/users', AdminController.users);
Route.delete('/users/:id', AdminController.deleteUser);
Route.get('/logs', AdminController.logs);
}, middleware: [RoleProtectedRoutes.adminAuth], prefix: '/api/admin');
// Moderator routes (admin or moderator can access)
Route.group(() {
Route.get('/posts/flagged', ModerationController.flaggedPosts);
Route.post('/posts/:id/approve', ModerationController.approve);
Route.post('/posts/:id/reject', ModerationController.reject);
}, middleware: [RoleProtectedRoutes.moderatorAuth], prefix: '/api/moderation');
// Editor routes
Route.group(() {
Route.post('/posts/:id/publish', EditorController.publish);
Route.post('/posts/:id/feature', EditorController.feature);
}, middleware: [RoleProtectedRoutes.editorAuth], prefix: '/api/editor');
}
// Manual role checking in controller
class AdminController {
static Future<void> users(Request req, Response res) async {
final user = req.authenticatable?.toAuthArray();
// Additional role check
if (user?['role'] != 'admin') {
return res.status(403).sendJson({
'error': 'Insufficient privileges',
'required_role': 'admin',
});
}
// Admin logic here
res.sendJson({'users': []});
}
}
⚠️ Important:
The user model must include a 'role' field in the toAuthArray() method for role checking to work.
Permission-Based Access Control
Restrict routes based on fine-grained permissions. Users must have ALL specified permissions to access the route.
dart
import 'package:khadem/khadem.dart';
class PermissionProtectedRoutes {
// User management permissions
static final userManagement = AuthMiddleware.bearer()
.withPermissions(['user.create', 'user.update', 'user.delete']);
// Post publishing permission
static final postPublish = AuthMiddleware.bearer()
.withPermissions(['post.publish']);
// Multiple permissions required
static final contentManagement = AuthMiddleware.bearer()
.withPermissions(['post.create', 'post.update', 'post.delete', 'post.publish']);
}
void defineRoutes() {
// User management (requires all 3 permissions)
Route.group(() {
Route.post('/users', UserController.create);
Route.put('/users/:id', UserController.update);
Route.delete('/users/:id', UserController.delete);
}, middleware: [PermissionProtectedRoutes.userManagement], prefix: '/api/admin');
// Publishing (requires post.publish permission)
Route.post('/api/posts/:id/publish', PostController.publish)
.middleware([PermissionProtectedRoutes.postPublish]);
// Content management (requires all 4 permissions)
Route.group(() {
Route.get('/posts', PostController.index);
Route.post('/posts', PostController.create);
Route.put('/posts/:id', PostController.update);
Route.delete('/posts/:id', PostController.delete);
}, middleware: [PermissionProtectedRoutes.contentManagement], prefix: '/api/content');
}
// Combining roles and permissions
class CombinedAuthRoutes {
static final adminWithPermissions = AuthMiddleware.bearer()
.withRoles(['admin'])
.withPermissions(['user.manage', 'system.config']);
}
void defineAdminRoutes() {
Route.group(() {
Route.get('/settings', SystemController.settings);
Route.put('/settings', SystemController.updateSettings);
}, middleware: [CombinedAuthRoutes.adminWithPermissions], prefix: '/api/system');
}
WebAuthMiddleware - Session Authentication
WebAuthMiddleware handles session-based authentication for traditional web applications. It checks session validity and redirects unauthenticated users to the login page.
dart
import 'package:khadem/khadem.dart';
// Web authentication middleware for session-based auth
class WebAuthExamples {
// Basic web auth - redirects to /login
static final webAuth = WebAuthMiddleware.auth();
// Custom redirect
static final customAuth = WebAuthMiddleware.auth(
redirectTo: '/signin',
);
// With excluded routes
static final webAuthWithExcept = WebAuthMiddleware.auth(
redirectTo: '/login',
except: ['/profile/public', '/profile/avatar'],
);
// Using specific guard
static final adminWebAuth = WebAuthMiddleware.auth(
guard: 'admin-web',
redirectTo: '/admin/login',
);
}
void defineWebRoutes() {
// Public routes
Route.get('/login', AuthController.showLogin);
Route.post('/login', AuthController.login);
Route.get('/register', AuthController.showRegister);
Route.post('/register', AuthController.register);
// Protected web routes
Route.group(() {
Route.get('/dashboard', DashboardController.index);
Route.get('/profile', ProfileController.show);
Route.post('/profile/update', ProfileController.update);
Route.get('/settings', SettingsController.show);
}, middleware: [WebAuthExamples.webAuth]);
// Admin web routes
Route.group(() {
Route.get('/dashboard', AdminController.dashboard);
Route.get('/users', AdminController.users);
}, middleware: [WebAuthExamples.adminWebAuth], prefix: '/admin');
}
dart
import 'package:khadem/khadem.dart';
class WebController {
static Future<void> dashboard(Request req, Response res) async {
// User is already authenticated by WebAuthMiddleware
final authenticatable = req.authenticatable;
if (authenticatable == null) {
// This shouldn't happen if middleware is working
return res.redirect('/login');
}
final user = authenticatable.toAuthArray();
await res.view('dashboard', data: {
'user': user,
'pageTitle': 'Dashboard',
});
}
static Future<void> profile(Request req, Response res) async {
final user = req.authenticatable?.toAuthArray();
await res.view('profile', data: {
'user': user,
'pageTitle': 'My Profile',
});
}
}
// Storing intended URL before login
class LoginController {
static Future<void> login(Request req, Response res) async {
final data = await req.validate({
'email': 'required|email',
'password': 'required|min:6',
});
final auth = AuthManager(guard: 'web');
final authResponse = await auth.attempt(data);
// Store in session
req.session.set('user_id', authResponse.user['id']);
// Redirect to intended URL or dashboard
final intended = req.session.pull('url.intended') ?? '/dashboard';
res.redirect(intended.toString());
}
}
Guest Middleware - Redirecting Authenticated Users
Use guest middleware on pages like login and register to redirect already authenticated users away from these pages.
dart
import 'package:khadem/khadem.dart';
// Guest middleware - redirects authenticated users away
class GuestMiddlewareExamples {
// Basic guest middleware
static final guest = WebAuthMiddleware.guest();
// Custom redirect for authenticated users
static final guestWithRedirect = WebAuthMiddleware.guest(
redirectTo: '/home',
);
// With exceptions
static final guestWithExcept = WebAuthMiddleware.guest(
redirectTo: '/dashboard',
except: ['/login/reset-password'],
);
}
void defineGuestRoutes() {
// Guest-only routes (login, register)
Route.group(() {
Route.get('/login', AuthController.showLogin);
Route.post('/login', AuthController.login);
Route.get('/register', AuthController.showRegister);
Route.post('/register', AuthController.register);
Route.get('/forgot-password', AuthController.showForgotPassword);
}, middleware: [GuestMiddlewareExamples.guest]);
// If authenticated user tries to visit /login, they get redirected to /dashboard
}
// Example: Showing different content for guest vs authenticated
class HomeController {
static Future<void> index(Request req, Response res) async {
final isAuthenticated = req.authenticatable != null;
await res.view('home', data: {
'isAuthenticated': isAuthenticated,
'user': isAuthenticated ? req.authenticatable?.toAuthArray() : null,
});
}
}
API Key Authentication
Authenticate requests using API keys in custom headers. Perfect for server-to-server communication and webhook endpoints.
dart
import 'package:khadem/khadem.dart';
// API Key authentication examples
class ApiKeyExamples {
// X-API-Key header
static final apiKey = AuthMiddleware.apiKey('X-API-Key');
// Custom header
static final customHeader = AuthMiddleware.apiKey('X-Custom-API-Key');
// Multiple API key middleware for different services
static final stripeWebhook = AuthMiddleware.apiKey('X-Stripe-Signature');
static final githubWebhook = AuthMiddleware.apiKey('X-Hub-Signature');
}
void defineWebhookRoutes() {
// Stripe webhook with API key validation
Route.post('/webhooks/stripe', WebhookController.stripe)
.middleware([ApiKeyExamples.stripeWebhook]);
// GitHub webhook
Route.post('/webhooks/github', WebhookController.github)
.middleware([ApiKeyExamples.githubWebhook]);
// General API with API key
Route.group(() {
Route.get('/data', ApiController.getData);
Route.post('/data', ApiController.postData);
}, middleware: [ApiKeyExamples.apiKey], prefix: '/api/external');
}
// API key validation in custom middleware
class CustomApiKeyMiddleware extends Middleware {
CustomApiKeyMiddleware() : super(_handle);
static Future<void> _handle(Request req, Response res, NextFunction next) async {
final apiKey = req.header('x-api-key');
if (apiKey == null) {
return res.status(401).sendJson({'error': 'API key required'});
}
// Validate API key against database
final validKey = await ApiKey().query
.where('key', '=', apiKey)
.where('active', '=', true)
.first();
if (validKey == null) {
return res.status(401).sendJson({'error': 'Invalid API key'});
}
// Attach API key info to request
req.setAttribute('api_key', validKey.toJson());
req.setAttribute('api_key_id', validKey.id);
await next();
}
}
Basic Authentication
HTTP Basic authentication sends credentials in the Authorization header. Useful for simple APIs and legacy system integration.
dart
import 'package:khadem/khadem.dart';
// Basic authentication examples
class BasicAuthExamples {
// Default basic auth
static final basic = AuthMiddleware.basic();
// Custom realm
static final customRealm = AuthMiddleware.basic(realm: 'Admin Area');
// With roles
static final adminBasic = AuthMiddleware.basic(realm: 'Admin')
.withRoles(['admin']);
}
void defineBasicAuthRoutes() {
// Protected with basic auth
Route.get('/api/legacy/users', LegacyController.users)
.middleware([BasicAuthExamples.basic]);
// Admin panel with basic auth
Route.group(() {
Route.get('/dashboard', AdminController.dashboard);
Route.get('/users', AdminController.users);
}, middleware: [BasicAuthExamples.adminBasic], prefix: '/admin');
}
// Client sends credentials like this:
// Authorization: Basic base64(username:password)
// Example: Authorization: Basic YWRtaW46cGFzc3dvcmQ=
// How to test basic auth with curl:
// curl -u username:password http://localhost:3000/api/legacy/users
Creating Custom Authentication Middleware
Build custom middleware for specific authentication requirements like OAuth, two-factor authentication, or custom token formats.
dart
import 'package:khadem/khadem.dart';
/// Custom OAuth middleware example
class OAuthMiddleware extends Middleware {
OAuthMiddleware() : super(_handle, priority: MiddlewarePriority.auth);
static Future<void> _handle(Request req, Response res, NextFunction next) async {
try {
// Extract OAuth token
final oauthToken = req.header('x-oauth-token');
if (oauthToken == null) {
return res.status(401).sendJson({'error': 'OAuth token required'});
}
// Verify with OAuth provider
final userInfo = await _verifyOAuthToken(oauthToken);
// Find or create user
final user = await _findOrCreateUser(userInfo);
// Attach to request
req.setAuthenticatable(user);
await next();
} catch (e) {
res.status(401).sendJson({
'error': 'OAuth authentication failed',
'message': e.toString(),
});
}
}
static Future<Map<String, dynamic>> _verifyOAuthToken(String token) async {
// Verify token with OAuth provider (Google, GitHub, etc.)
// This is a placeholder
return {'email': 'user@example.com', 'name': 'User'};
}
static Future<User> _findOrCreateUser(Map<String, dynamic> userInfo) async {
// Find existing user or create new one
final user = await User().query
.where('email', '=', userInfo['email'])
.first();
if (user != null) {
return user;
}
// Create new user
final newUser = User()
..fromJson({
'email': userInfo['email'],
'name': userInfo['name'],
'email_verified_at': DateTime.now().toIso8601String(),
});
await newUser.save();
return newUser;
}
}
// Two-factor authentication middleware
class TwoFactorMiddleware extends Middleware {
TwoFactorMiddleware() : super(_handle, priority: MiddlewarePriority.auth);
static Future<void> _handle(Request req, Response res, NextFunction next) async {
// User must be authenticated first
final user = req.authenticatable;
if (user == null) {
return res.status(401).sendJson({'error': 'Authentication required'});
}
final userData = user.toAuthArray();
// Check if 2FA is enabled for this user
if (userData['two_factor_enabled'] != true) {
return next(); // 2FA not enabled, proceed
}
// Check if 2FA is verified for this session
final twoFactorVerified = req.session.get('two_factor_verified');
if (twoFactorVerified == true) {
return next(); // Already verified
}
// Require 2FA verification
return res.status(403).sendJson({
'error': 'Two-factor authentication required',
'two_factor_required': true,
});
}
}
// Usage
void defineCustomAuthRoutes() {
// OAuth protected routes
Route.group(() {
Route.get('/profile', UserController.profile);
}, middleware: [OAuthMiddleware()]);
// 2FA protected routes
Route.group(() {
Route.get('/sensitive-data', UserController.sensitiveData);
Route.post('/transfer', UserController.transfer);
}, middleware: [
AuthMiddleware.bearer(),
TwoFactorMiddleware(),
]);
}
Chaining Multiple Middleware
Combine multiple middleware to create complex authorization rules. Middleware runs in the order specified.
dart
import 'package:khadem/khadem.dart';
// Chaining multiple middleware
void defineChainedRoutes() {
// Multiple middleware in sequence
Route.group(() {
Route.get('/admin/users', AdminController.users);
Route.post('/admin/users/:id/ban', AdminController.banUser);
}, middleware: [
AuthMiddleware.bearer(), // 1. Authenticate
RoleMiddleware(['admin']), // 2. Check role
PermissionMiddleware(['user.manage']), // 3. Check permission
AuditMiddleware(), // 4. Log action
]);
// Different middleware for different routes in same group
Route.group(() {
// Public in group
Route.get('/posts', PostController.index);
// Authenticated required
Route.post('/posts', PostController.create)
.middleware([AuthMiddleware.bearer()]);
// Admin only
Route.delete('/posts/:id', PostController.delete)
.middleware([
AuthMiddleware.bearer().withRoles(['admin'])
]);
}, prefix: '/api');
}
// Custom middleware chain
class MiddlewareChains {
// Admin with audit logging
static final adminWithAudit = [
AuthMiddleware.bearer().withRoles(['admin']),
AuditMiddleware(),
];
// User with rate limiting
static final userWithRateLimit = [
AuthMiddleware.bearer(),
RateLimitMiddleware(maxRequests: 100, windowMinutes: 1),
];
// Public with CORS
static final publicApi = [
CorsMiddleware(),
RateLimitMiddleware(maxRequests: 1000, windowMinutes: 1),
];
}
// Usage
void defineMiddlewareChainRoutes() {
Route.group(() {
Route.get('/users', AdminController.users);
}, middleware: MiddlewareChains.adminWithAudit);
Route.group(() {
Route.get('/profile', UserController.profile);
}, middleware: MiddlewareChains.userWithRateLimit);
}
Accessing Authenticated User in Controllers
After authentication middleware runs, user data is available in controllers through the request object.
dart
import 'package:khadem/khadem.dart';
class UserController {
/// Accessing authenticated user from request
static Future<void> profile(Request req, Response res) async {
// Method 1: Using authenticatable (recommended)
final authenticatable = req.authenticatable;
if (authenticatable == null) {
return res.status(401).sendJson({'error': 'Unauthenticated'});
}
final user = authenticatable.toAuthArray();
res.sendJson({
'id': user['id'],
'name': user['name'],
'email': user['email'],
'role': user['role'],
});
}
/// Accessing user ID directly
static Future<void> getUserPosts(Request req, Response res) async {
final authenticatable = req.authenticatable;
if (authenticatable == null) {
return res.status(401).sendJson({'error': 'Unauthenticated'});
}
final userId = authenticatable.getAuthIdentifier();
// Fetch user's posts
final posts = await Post().query
.where('user_id', '=', userId)
.orderBy('created_at', 'desc')
.get();
res.sendJson({
'posts': posts.map((p) => p.toJson()).toList(),
});
}
/// Type-safe user access with model
static Future<void> updateProfile(Request req, Response res) async {
final authenticatable = req.authenticatable;
if (authenticatable == null) {
return res.status(401).sendJson({'error': 'Unauthenticated'});
}
// Get full user model from database
final userId = authenticatable.getAuthIdentifier();
final user = await User().query.where('id', '=', userId).first();
if (user == null) {
return res.status(404).sendJson({'error': 'User not found'});
}
// Update user
final data = await req.validate({
'name': 'required',
'bio': 'nullable',
});
user.fromJson(data);
await user.save();
res.sendJson({
'message': 'Profile updated',
'user': user.toJson(),
});
}
/// Checking user permissions
static Future<void> deletePost(Request req, Response res) async {
final postId = req.param('id');
final authenticatable = req.authenticatable;
if (authenticatable == null) {
return res.status(401).sendJson({'error': 'Unauthenticated'});
}
final user = authenticatable.toAuthArray();
final post = await Post().query.where('id', '=', postId).first();
if (post == null) {
return res.status(404).sendJson({'error': 'Post not found'});
}
// Check if user owns the post or is admin
if (post.userId != user['id'] && user['role'] != 'admin') {
return res.status(403).sendJson({'error': 'Forbidden'});
}
await post.delete();
res.sendJson({'message': 'Post deleted'});
}
}
Middleware Priority and Order
Middleware can have priorities that determine execution order. Authentication middleware typically has high priority to run early in the request lifecycle.
dart
import 'package:khadem/khadem.dart';
// Middleware with different priorities
class PriorityMiddleware {
// High priority - runs first
static final cors = Middleware(
(req, res, next) async {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
await next();
},
priority: MiddlewarePriority.highest,
name: 'cors',
);
// Authentication priority
static final auth = AuthMiddleware.bearer(); // Default priority: auth (500)
// Normal priority - runs after auth
static final logging = Middleware(
(req, res, next) async {
print('Request: ${req.method} ${req.path}');
await next();
},
priority: MiddlewarePriority.normal,
name: 'logging',
);
// Low priority - runs last
static final analytics = Middleware(
(req, res, next) async {
// Track analytics
await next();
},
priority: MiddlewarePriority.low,
name: 'analytics',
);
}
// Execution order: cors -> auth -> logging -> analytics
void defineRoutes() {
Route.group(() {
Route.get('/users', UserController.index);
}, middleware: [
PriorityMiddleware.analytics, // Will run last (priority: 100)
PriorityMiddleware.auth, // Will run second (priority: 500)
PriorityMiddleware.logging, // Will run third (priority: 250)
PriorityMiddleware.cors, // Will run first (priority: 1000)
]);
}
// Custom priority values
class CustomPriorityMiddleware extends Middleware {
CustomPriorityMiddleware()
: super(
_handle,
priority: const MiddlewarePriority(600), // Custom value
name: 'custom-auth',
);
static Future<void> _handle(Request req, Response res, NextFunction next) async {
// Custom logic
await next();
}
}
| Priority | Value | Typical Use |
|---|---|---|
| highest | 1000 | CORS, security headers |
| high | 750 | Session initialization |
| auth | 500 | Authentication |
| normal | 250 | Most middleware |
| low | 100 | Logging, analytics |
Error Handling in Middleware
Handle authentication errors gracefully with appropriate HTTP status codes and helpful error messages.
dart
import 'package:khadem/khadem.dart';
class AuthErrorMiddleware extends Middleware {
AuthErrorMiddleware() : super(_handle);
static Future<void> _handle(Request req, Response res, NextFunction next) async {
try {
final token = req.header('authorization')?.replaceFirst('Bearer ', '');
if (token == null) {
throw AuthException('Token required', statusCode: 401);
}
final auth = AuthManager();
final user = await auth.user(token);
req.setAuthenticatable(user);
await next();
} on AuthException catch (e) {
// Handle authentication exceptions
_handleAuthError(res, e);
} on ValidationException catch (e) {
// Handle validation errors
res.status(422).sendJson({
'error': 'Validation failed',
'errors': e.errors,
});
} catch (e) {
// Handle unexpected errors
res.status(500).sendJson({
'error': 'Internal server error',
'message': env('APP_DEBUG') == 'true' ? e.toString() : 'An error occurred',
});
}
}
static void _handleAuthError(Response res, AuthException error) {
final statusCode = error.statusCode;
res.status(statusCode).sendJson({
'error': _getErrorType(statusCode),
'message': error.message,
'code': statusCode,
});
}
static String _getErrorType(int statusCode) {
switch (statusCode) {
case 401:
return 'Unauthenticated';
case 403:
return 'Forbidden';
case 422:
return 'Validation Error';
default:
return 'Authentication Error';
}
}
}
// Graceful error responses
class ApiErrorResponses {
static Map<String, dynamic> unauthenticated({String? message}) {
return {
'error': 'Unauthenticated',
'message': message ?? 'Authentication required',
'code': 401,
};
}
static Map<String, dynamic> forbidden({String? message}) {
return {
'error': 'Forbidden',
'message': message ?? 'You do not have permission to access this resource',
'code': 403,
};
}
static Map<String, dynamic> invalidToken({String? message}) {
return {
'error': 'Invalid Token',
'message': message ?? 'The provided token is invalid or expired',
'code': 401,
};
}
}
Middleware Best Practices
Follow these guidelines for secure and maintainable authentication middleware.
✅ Do:
- Use AuthMiddleware for APIs
- Use WebAuthMiddleware for web apps
- Chain middleware for complex rules
- Return proper HTTP status codes
- Log authentication failures
- Use middleware groups for organization
❌ Don't:
- Mix session and token auth in same route
- Expose sensitive errors to clients
- Skip authentication on sensitive routes
- Hard-code roles/permissions in middleware
- Forget to handle edge cases
- Use middleware without proper testing
