Primer commit del sistema separado falta mejorar mucho
This commit is contained in:
200
shared/auth/jwt.php
Executable file
200
shared/auth/jwt.php
Executable file
@@ -0,0 +1,200 @@
|
||||
<?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 [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user