201 lines
5.6 KiB
PHP
Executable File
201 lines
5.6 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* Utilidades JWT para autenticación
|
|
* Basado en Firebase PHP-JWT
|
|
*/
|
|
|
|
require_once __DIR__ . '/../../vendor/autoload.php';
|
|
require_once __DIR__ . '/../database/connection.php';
|
|
|
|
use Firebase\JWT\JWT;
|
|
use Firebase\JWT\Key;
|
|
|
|
class JWTAuth {
|
|
private static $secret;
|
|
private static $algorithm = 'HS256';
|
|
private static $expiration = 3600; // 1 hora por defecto
|
|
private static $userData = null; // Para almacenar los datos del usuario autenticado
|
|
|
|
private static function init() {
|
|
if (self::$secret === null) {
|
|
self::$secret = $_ENV['JWT_SECRET'] ?? getenv('JWT_SECRET');
|
|
$algo = $_ENV['JWT_ALGORITHM'] ?? getenv('JWT_ALGORITHM');
|
|
$exp = $_ENV['JWT_EXPIRATION'] ?? getenv('JWT_EXPIRATION');
|
|
|
|
if ($algo) self::$algorithm = $algo;
|
|
if ($exp) self::$expiration = (int)$exp;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generar un token JWT
|
|
*/
|
|
public static function generateToken($userId, $username, $rol, $idioma = 'es', $permisos = []) {
|
|
self::init();
|
|
|
|
$issuedAt = time();
|
|
$expire = $issuedAt + self::$expiration;
|
|
|
|
$payload = [
|
|
'iat' => $issuedAt,
|
|
'exp' => $expire,
|
|
'iss' => $_ENV['APP_URL'] ?? getenv('APP_URL'),
|
|
'data' => [
|
|
'userId' => $userId,
|
|
'username' => $username,
|
|
'rol' => $rol,
|
|
'idioma' => $idioma,
|
|
'permissions' => $permisos // Cambiado a 'permissions' para consistencia
|
|
]
|
|
];
|
|
|
|
return JWT::encode($payload, self::$secret, self::$algorithm);
|
|
}
|
|
|
|
/**
|
|
* Validar y decodificar un token JWT
|
|
*/
|
|
public static function validateToken($token) {
|
|
self::init();
|
|
|
|
try {
|
|
$decoded = JWT::decode($token, new Key(self::$secret, self::$algorithm));
|
|
return [
|
|
'valid' => true,
|
|
'data' => $decoded->data
|
|
];
|
|
} catch (Exception $e) {
|
|
return [
|
|
'valid' => false,
|
|
'error' => $e->getMessage()
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Refrescar un token JWT
|
|
*/
|
|
public static function refreshToken($token) {
|
|
$result = self::validateToken($token);
|
|
|
|
if (!$result['valid']) {
|
|
return null;
|
|
}
|
|
|
|
$data = $result['data'];
|
|
return self::generateToken(
|
|
$data->userId,
|
|
$data->username,
|
|
$data->rol,
|
|
$data->idioma,
|
|
(array)$data->permissions // Cambiado a 'permissions'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Extraer el token del header Authorization
|
|
*/
|
|
public static function getTokenFromHeader() {
|
|
// Compatibilidad con todos los entornos PHP
|
|
if (function_exists('getallheaders')) {
|
|
$headers = getallheaders();
|
|
} else {
|
|
$headers = [];
|
|
foreach ($_SERVER as $name => $value) {
|
|
if (substr($name, 0, 5) == 'HTTP_') {
|
|
$headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isset($headers['Authorization'])) {
|
|
$matches = [];
|
|
if (preg_match('/Bearer\s+(.*)$/i', $headers['Authorization'], $matches)) {
|
|
return $matches[1];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Middleware de autenticación
|
|
* Retorna los datos del usuario si el token es válido, o false si no
|
|
*/
|
|
public static function authenticate() {
|
|
if (self::$userData !== null) {
|
|
return self::$userData; // Ya autenticado
|
|
}
|
|
|
|
// Intentar obtener el token del header
|
|
$token = self::getTokenFromHeader();
|
|
|
|
// Si no está en el header, buscar en cookie
|
|
if (!$token && isset($_COOKIE['auth_token'])) {
|
|
$token = $_COOKIE['auth_token'];
|
|
}
|
|
|
|
if (!$token) {
|
|
return false;
|
|
}
|
|
|
|
$result = self::validateToken($token);
|
|
|
|
if (!$result['valid']) {
|
|
return false;
|
|
}
|
|
|
|
self::$userData = $result['data'];
|
|
return self::$userData;
|
|
}
|
|
|
|
/**
|
|
* Obtener los datos del usuario autenticado.
|
|
* Asume que authenticate() o requireAuth() ya han sido llamados.
|
|
*/
|
|
public static function getUserData() {
|
|
return self::$userData;
|
|
}
|
|
|
|
/**
|
|
* Middleware que requiere autenticación
|
|
* Redirige al login si no está autenticado
|
|
*/
|
|
public static function requireAuth($redirectTo = '/login.php') {
|
|
$userData = self::authenticate();
|
|
|
|
if (!$userData) {
|
|
header('Location: ' . $redirectTo);
|
|
exit;
|
|
}
|
|
|
|
return $userData;
|
|
}
|
|
|
|
/**
|
|
* Cargar los permisos de un usuario desde la base de datos
|
|
*/
|
|
public static function loadUserPermissions($userId) {
|
|
try {
|
|
$db = getDB();
|
|
|
|
$stmt = $db->prepare("
|
|
SELECT p.nombre
|
|
FROM permisos p
|
|
INNER JOIN usuarios_permisos up ON p.id = up.permiso_id
|
|
WHERE up.usuario_id = ?
|
|
");
|
|
|
|
$stmt->execute([$userId]);
|
|
$permisos = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
|
|
|
return $permisos;
|
|
|
|
} catch (PDOException $e) {
|
|
error_log("Error cargando permisos: " . $e->getMessage());
|
|
return [];
|
|
}
|
|
}
|
|
}
|
|
|