feat: implement JWT-based authentication system with repository, service, and middleware layers

This commit is contained in:
2026-09-09 20:02:55 -03:00
parent f6d7d42f10
commit 14b85d28a1
11 changed files with 975 additions and 2 deletions
+26
View File
@@ -0,0 +1,26 @@
<?php
namespace WorkbloomERP\Security;
class AuthContext {
private static ?array $user = null;
public static function setUser(array $user): void {
self::$user = $user;
}
public static function getUser(): ?array {
return self::$user;
}
public static function getUserId(): ?int {
return isset(self::$user['id']) ? (int)self::$user['id'] : null;
}
public static function getUserUuid(): ?string {
return self::$user['sub'] ?? self::$user['uuid'] ?? null;
}
public static function clear(): void {
self::$user = null;
}
}
+63
View File
@@ -0,0 +1,63 @@
<?php
namespace WorkbloomERP\Security;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Throwable;
use RuntimeException;
class JwtService {
private string $secret;
private int $expiresIn;
public function __construct(?string $secret = null, ?int $expiresIn = null) {
$this->secret = $secret ?? $_ENV['JWT_SECRET'] ?? getenv('JWT_SECRET') ?: '';
if (empty($this->secret)) {
throw new RuntimeException('JWT secret is not configured.');
}
$this->expiresIn = $expiresIn ?? (int)($_ENV['JWT_EXPIRES_IN'] ?? getenv('JWT_EXPIRES_IN') ?: 86400);
}
/**
* Gera um novo token JWT para o payload fornecido.
*
* @param array $userData Dados do usuário e contexto
* @return array{token: string, expires_in: int, expires_at: int}
*/
public function generateToken(array $userData): array {
$now = time();
$expiresAt = $now + $this->expiresIn;
$payload = array_merge($userData, [
'iat' => $now,
'nbf' => $now,
'exp' => $expiresAt,
]);
$token = JWT::encode($payload, $this->secret, 'HS256');
return [
'token' => $token,
'expires_in' => $this->expiresIn,
'expires_at' => $expiresAt,
];
}
/**
* Decodifica e valida o token JWT.
* Retorna o payload em array ou lança uma exceção caso inválido ou expirado.
*
* @param string $token
* @return array
* @throws RuntimeException
*/
public function validateToken(string $token): array {
try {
$decoded = JWT::decode($token, new Key($this->secret, 'HS256'));
return (array)$decoded;
} catch (Throwable $e) {
throw new RuntimeException('Token inválido ou expirado: ' . $e->getMessage(), 401, $e);
}
}
}