Prod
This commit is contained in:
@@ -4,8 +4,6 @@ namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Firebase\JWT\JWT;
|
||||
use Firebase\JWT\Key;
|
||||
|
||||
class JwtAuthMiddleware
|
||||
{
|
||||
@@ -24,20 +22,24 @@ class JwtAuthMiddleware
|
||||
|
||||
$token = $matches[1];
|
||||
|
||||
$publicKey = str_replace('\\n', "\n", env('JWT_PUBLIC_KEY_PEM'));
|
||||
[$header, $payload, $signature] = $this->decodeToken($token);
|
||||
|
||||
$decoded = JWT::decode($token, new Key($publicKey, 'RS256'));
|
||||
if (($header['alg'] ?? null) !== 'RS256') {
|
||||
return response()->json(['message' => 'Invalid token algorithm'], 401);
|
||||
}
|
||||
|
||||
if (
|
||||
$decoded->iss !== env('JWT_ISSUER') ||
|
||||
$decoded->aud !== env('JWT_AUDIENCE') ||
|
||||
empty($decoded->sub)
|
||||
!$this->signatureIsValid($token, $signature) ||
|
||||
($payload['iss'] ?? null) !== config('jwt.issuer') ||
|
||||
($payload['aud'] ?? null) !== config('jwt.audience') ||
|
||||
empty($payload['sub']) ||
|
||||
$this->tokenIsExpired($payload)
|
||||
) {
|
||||
return response()->json(['message' => 'Invalid token'], 401);
|
||||
}
|
||||
|
||||
$request->attributes->set('auth', [
|
||||
'id' => $decoded->sub,
|
||||
'id' => $payload['sub'],
|
||||
'token' => $token
|
||||
]);
|
||||
|
||||
@@ -47,4 +49,68 @@ class JwtAuthMiddleware
|
||||
return response()->json(['message' => 'Invalid or expired token'], 401);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function decodeToken(string $token): array
|
||||
{
|
||||
$parts = explode('.', $token);
|
||||
|
||||
if (count($parts) !== 3) {
|
||||
throw new \InvalidArgumentException('Invalid token structure');
|
||||
}
|
||||
|
||||
return [
|
||||
$this->base64UrlDecodeJson($parts[0]),
|
||||
$this->base64UrlDecodeJson($parts[1]),
|
||||
$this->base64UrlDecode($parts[2]),
|
||||
];
|
||||
}
|
||||
|
||||
private function base64UrlDecodeJson(string $value): array
|
||||
{
|
||||
$decoded = json_decode($this->base64UrlDecode($value), true);
|
||||
|
||||
if (!is_array($decoded)) {
|
||||
throw new \InvalidArgumentException('Invalid token payload');
|
||||
}
|
||||
|
||||
return $decoded;
|
||||
}
|
||||
|
||||
private function base64UrlDecode(string $value): string
|
||||
{
|
||||
$value .= str_repeat('=', (4 - strlen($value) % 4) % 4);
|
||||
$decoded = base64_decode(strtr($value, '-_', '+/'), true);
|
||||
|
||||
if ($decoded === false) {
|
||||
throw new \InvalidArgumentException('Invalid base64url value');
|
||||
}
|
||||
|
||||
return $decoded;
|
||||
}
|
||||
|
||||
private function signatureIsValid(string $token, string $signature): bool
|
||||
{
|
||||
[$header, $payload] = explode('.', $token, 3);
|
||||
$publicKey = str_replace('\\n', "\n", (string) config('jwt.public_key'));
|
||||
|
||||
if ($publicKey === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return openssl_verify(
|
||||
$header . '.' . $payload,
|
||||
$signature,
|
||||
$publicKey,
|
||||
OPENSSL_ALGO_SHA256
|
||||
) === 1;
|
||||
}
|
||||
|
||||
private function tokenIsExpired(array $payload): bool
|
||||
{
|
||||
if (!isset($payload['exp']) || !is_numeric($payload['exp'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return time() >= (int) $payload['exp'];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user