Security API
Comprehensive security features including authentication, authorization, encryption, and security best practices for Forge Engine applications.
Security Overview
Security is a critical aspect of any web application. Forge Engine provides a comprehensive security layer that includes authentication, authorization, encryption, CSRF protection, input sanitization, and more. This guide covers all security-related APIs and best practices.
Authentication
Secure user authentication with multiple providers, session management, and token-based authentication.
Authorization
Role-based access control (RBAC), permissions, policies, and resource-level authorization.
Encryption
Data encryption, hashing, secure key management, and cryptographic operations.
Protection
CSRF protection, XSS prevention, SQL injection prevention, and security headers.
Authentication
Auth Manager
Central authentication management with multiple providers and strategies.
use Forge\Security\AuthManager;
use Forge\Security\Providers\DatabaseAuthProvider;
use Forge\Security\Providers\TokenAuthProvider;
$authManager = new AuthManager();
/**
 * Register authentication providers
 */
$authManager->registerProvider('database', new DatabaseAuthProvider());
$authManager->registerProvider('token', new TokenAuthProvider());
/**
 * Authenticate user with credentials
 */
$user = $authManager->attempt([
    'email' => 'user@example.com',
    'password' => 'password123'
], 'database');
if ($user) {
    // Authentication successful
    echo "Welcome, {$user->name}!";
} else {
    // Authentication failed
    echo "Invalid credentials";
}
/**
 * Authenticate with token
 */
$user = $authManager->attempt([
    'token' => $request->bearerToken()
], 'token');
/**
 * Check if user is authenticated
 */
if ($authManager->check()) {
    $currentUser = $authManager->user();
}
/**
 * Get current user
 */
$user = $authManager->user();
/**
 * Logout user
 */
$authManager->logout();
/**
 * Get authentication guard
 */
$guard = $authManager->guard('web');
$guard = $authManager->guard('api');Session-based Authentication
Traditional session-based authentication with secure session management.
use Forge\Security\SessionManager;
use Forge\Security\Providers\SessionAuthProvider;
$sessionManager = new SessionManager();
$sessionAuth = new SessionAuthProvider($sessionManager);
/**
 * Start secure session
 */
$sessionManager->start([
    'name' => 'forge_session',
    'lifetime' => 7200, // 2 hours
    'path' => '/',
    'domain' => '.example.com',
    'secure' => true,
    'httponly' => true,
    'samesite' => 'strict'
]);
/**
 * Login user and create session
 */
public function login(Request $request): Response
{
    $credentials = $request->validate([
        'email' => 'required|email',
        'password' => 'required|string'
    ]);
    
    $user = $this->auth->attempt($credentials);
    
    if ($user) {
        // Regenerate session ID for security
        $this->session->regenerate();
        
        // Store user data in session
        $this->session->put('user_id', $user->id);
        $this->session->put('user_data', [
            'id' => $user->id,
            'email' => $user->email,
            'name' => $user->name,
            'roles' => $user->roles->pluck('name')->toArray()
        ]);
        
        // Set additional security flags
        $this->session->put('ip_address', $request->ip());
        $this->session->put('user_agent', $request->userAgent());
        $this->session->put('login_time', time());
        
        return redirect('/dashboard')->with('success', 'Login successful');
    }
    
    return back()->withErrors(['email' => 'Invalid credentials']);
}
/**
 * Remember me functionality
 */
public function loginWithRemember(Request $request): Response
{
    $credentials = $request->validate([
        'email' => 'required|email',
        'password' => 'required|string',
        'remember' => 'boolean'
    ]);
    
    $remember = $request->boolean('remember', false);
    
    if ($this->auth->attempt($credentials, $remember)) {
        if ($remember) {
            // Create remember token
            $token = $this->createRememberToken($request->user());
            
            // Set secure cookie
            $this->cookie->queue('remember_token', $token, 60 * 24 * 30); // 30 days
        }
        
        return redirect('/dashboard');
    }
    
    return back()->withErrors(['email' => 'Invalid credentials']);
}
/**
 * Session security checks
 */
public function validateSession(Request $request): bool
{
    $sessionData = $this->session->get('user_data');
    
    if (!$sessionData) {
        return false;
    }
    
    // Check IP address (optional - can be problematic with mobile users)
    if ($this->session->get('ip_address') !== $request->ip()) {
        Log::warning('Session IP mismatch', [
            'expected' => $this->session->get('ip_address'),
            'actual' => $request->ip()
        ]);
        
        // Optionally invalidate session
        // return false;
    }
    
    // Check user agent
    if ($this->session->get('user_agent') !== $request->userAgent()) {
        Log::warning('Session user agent mismatch');
        return false;
    }
    
    // Check session timeout
    $loginTime = $this->session->get('login_time', 0);
    $timeout = config('session.lifetime', 7200);
    
    if (time() - $loginTime > $timeout) {
        $this->session->invalidate();
        return false;
    }
    
    return true;
}Token-based Authentication
JWT and API token authentication for stateless applications.
use Forge\Security\TokenManager;
use Forge\Security\JWTManager;
use Firebase\JWT\JWT;
$tokenManager = new TokenManager();
$jwtManager = new JWTManager();
/**
 * Generate API token
 */
public function createApiToken(User $user): string
{
    $token = bin2hex(random_bytes(32));
    
    // Store token in database
    ApiToken::create([
        'user_id' => $user->id,
        'token' => hash('sha256', $token),
        'name' => 'API Token',
        'abilities' => ['read', 'write'],
        'expires_at' => now()->addDays(30)
    ]);
    
    return $token;
}
/**
 * Generate JWT token
 */
public function createJwtToken(User $user): string
{
    $payload = [
        'iss' => 'forge-engine', // Issuer
        'sub' => $user->id,      // Subject
        'aud' => 'api-users',    // Audience
        'iat' => time(),         // Issued at
        'exp' => time() + 3600,  // Expiration (1 hour)
        'nbf' => time(),         // Not before
        'jti' => uniqid(),       // JWT ID
        'data' => [
            'user_id' => $user->id,
            'email' => $user->email,
            'roles' => $user->roles->pluck('name')->toArray()
        ]
    ];
    
    return JWT::encode($payload, config('app.jwt_secret'), 'HS256');
}
/**
 * Refresh JWT token
 */
public function refreshJwtToken(string $refreshToken): ?string
{
    try {
        // Validate refresh token
        $refreshData = JWT::decode($refreshToken, config('app.jwt_refresh_secret'), ['HS256']);
        
        // Get user
        $user = User::find($refreshData->sub);
        if (!$user) {
            return null;
        }
        
        // Generate new access token
        return $this->createJwtToken($user);
        
    } catch (\Exception $e) {
        Log::error('JWT refresh failed', ['error' => $e->getMessage()]);
        return null;
    }
}
/**
 * Validate API token
 */
public function validateApiToken(string $token): ?User
{
    $hashedToken = hash('sha256', $token);
    
    $apiToken = ApiToken::where('token', $hashedToken)
        ->where('expires_at', '>', now())
        ->first();
    
    if ($apiToken) {
        // Update last used timestamp
        $apiToken->update(['last_used_at' => now()]);
        
        return $apiToken->user;
    }
    
    return null;
}
/**
 * Validate JWT token
 */
public function validateJwtToken(string $token): ?array
{
    try {
        $decoded = JWT::decode($token, config('app.jwt_secret'), ['HS256']);
        
        // Check expiration
        if ($decoded->exp < time()) {
            return null;
        }
        
        // Check if token is blacklisted
        if (Cache::has("blacklist:{$decoded->jti}")) {
            return null;
        }
        
        return (array) $decoded;
        
    } catch (\Exception $e) {
        Log::error('JWT validation failed', ['error' => $e->getMessage()]);
        return null;
    }
}
/**
 * Revoke token
 */
public function revokeToken(string $token): void
{
    // For JWT, add to blacklist
    try {
        $decoded = JWT::decode($token, config('app.jwt_secret'), ['HS256']);
        $ttl = $decoded->exp - time();
        
        if ($ttl > 0) {
            Cache::put("blacklist:{$decoded->jti}", true, $ttl);
        }
    } catch (\Exception $e) {
        // Token is already invalid
    }
    
    // For API tokens, delete from database
    $hashedToken = hash('sha256', $token);
    ApiToken::where('token', $hashedToken)->delete();
}