64 lines
1.8 KiB
PHP
64 lines
1.8 KiB
PHP
<?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);
|
|
}
|
|
}
|
|
}
|