feat: implement JWT-based authentication system with repository, service, and middleware layers
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
namespace WorkbloomERP\Middleware;
|
||||
|
||||
use Throwable;
|
||||
use KrothiumAPI\Utils\HttpUtil;
|
||||
use WorkbloomERP\Security\JwtService;
|
||||
use WorkbloomERP\Security\AuthContext;
|
||||
|
||||
class AuthMiddleware {
|
||||
private JwtService $jwtService;
|
||||
|
||||
public function __construct(?JwtService $jwtService = null) {
|
||||
$this->jwtService = $jwtService ?? new JwtService();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executa a validação de autenticação Bearer Token.
|
||||
* Retorna true em caso de sucesso ou array estruturado de bloqueio (401).
|
||||
*/
|
||||
public function handle(): array|bool {
|
||||
$token = HttpUtil::getBearerToken();
|
||||
|
||||
if (empty($token)) {
|
||||
return [
|
||||
'block' => true,
|
||||
'response_code' => 401,
|
||||
'message' => 'Token de autenticação não fornecido.',
|
||||
];
|
||||
}
|
||||
|
||||
try {
|
||||
$payload = $this->jwtService->validateToken($token);
|
||||
AuthContext::setUser($payload);
|
||||
return true;
|
||||
} catch (Throwable) {
|
||||
return [
|
||||
'block' => true,
|
||||
'response_code' => 401,
|
||||
'message' => 'Token inválido ou expirado.',
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user