From d7ed3d7fa552a8013b9479d7ec29d901bb8bc6a2 Mon Sep 17 00:00:00 2001 From: Edson Salvatore Date: Sun, 3 May 2026 22:13:41 -0500 Subject: [PATCH] feat: implementado middleware de autenticacao jwt conforme especificacao --- Dockerfile | 10 +++- app/Http/Middleware/JwtAuthMiddleware.php | 67 +++++++++++++++++++++ bootstrap/app.php | 6 +- composer.json | 1 + composer.lock | 72 +++++++++++++++++++++-- 5 files changed, 149 insertions(+), 7 deletions(-) create mode 100644 app/Http/Middleware/JwtAuthMiddleware.php diff --git a/Dockerfile b/Dockerfile index 1c6abf0..2935879 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,15 @@ +# Usamos a imagem oficial do PHP 8.3 FROM php:8.3-cli -RUN docker-php-ext-install pdo pdo_mysql +# Instalamos o git, unzip (para o Composer) e a extensão do MySQL +RUN apt-get update && apt-get install -y git unzip \ + && docker-php-ext-install pdo pdo_mysql +# Trazemos o Composer pronto da imagem oficial dele +COPY --from=composer:latest /usr/bin/composer /usr/bin/composer + +# Definimos a pasta de trabalho WORKDIR /var/www/html +# Comando para manter o servidor do Laravel rodando CMD ["php", "artisan", "serve", "--host=0.0.0.0", "--port=8000"] \ No newline at end of file diff --git a/app/Http/Middleware/JwtAuthMiddleware.php b/app/Http/Middleware/JwtAuthMiddleware.php new file mode 100644 index 0000000..f9aca99 --- /dev/null +++ b/app/Http/Middleware/JwtAuthMiddleware.php @@ -0,0 +1,67 @@ + + $authHeader = $request->header('Authorization'); + + if (!$authHeader || !preg_match('/Bearer\s(\S+)/', $authHeader, $matches)) { + return response()->json(['message' => 'Missing or invalid Authorization header'], 401); // Retorna 401 se falhar + } + + $token = $matches[1]; + + // Corrige as quebras de linha da chave pública que vêm do .env + $publicKey = str_replace('\\n', "\n", env('JWT_PUBLIC_KEY_PEM')); + $issuer = env('JWT_ISSUER'); + $audience = env('JWT_AUDIENCE'); + + try { + // 2. Validar assinatura RS256 com JWT_PUBLIC_KEY_PEM e expiração (automático pela biblioteca) + $decoded = JWT::decode($token, new Key($publicKey, 'RS256')); + + // 3. Validar iss e aud + if ($decoded->iss !== $issuer) { + throw new Exception('Invalid issuer'); + } + + $tokenAudience = is_array($decoded->aud) ? $decoded->aud[0] : $decoded->aud; + if ($tokenAudience !== $audience) { + throw new Exception('Invalid audience'); + } + + // 4. Validar se sub existe (nosso user_id confiável) + if (!isset($decoded->sub) || empty(trim((string)$decoded->sub))) { + throw new Exception('Invalid token claims: sub is missing'); + } + + // 5. Montar a identificação para as rotas usarem (equivalente ao request.auth = { id: sub, token }) + $request->attributes->add([ + 'auth_id' => $decoded->sub, + 'token' => $token + ]); + + return $next($request); + + } catch (Exception $e) { + // Retorna 401 para token inválido ou expirado + return response()->json(['message' => 'Invalid or expired access token'], 401); + } + } +} \ No newline at end of file diff --git a/bootstrap/app.php b/bootstrap/app.php index c183276..55973c5 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -10,8 +10,10 @@ return Application::configure(basePath: dirname(__DIR__)) commands: __DIR__.'/../routes/console.php', health: '/up', ) - ->withMiddleware(function (Middleware $middleware): void { - // + ->withMiddleware(function (Middleware $middleware) { + $middleware->alias([ + 'jwt.auth' => \App\Http\Middleware\JwtAuthMiddleware::class, + ]); }) ->withExceptions(function (Exceptions $exceptions): void { // diff --git a/composer.json b/composer.json index daa04c6..8bc24f5 100644 --- a/composer.json +++ b/composer.json @@ -7,6 +7,7 @@ "license": "MIT", "require": { "php": "^8.3", + "firebase/php-jwt": "^7.0", "laravel/framework": "^13.0", "laravel/tinker": "^3.0" }, diff --git a/composer.lock b/composer.lock index aa14aa7..bb77584 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "12a93e9ee58f99b3ee9ac9b5d35d65e5", + "content-hash": "16d1bbc8c7c72342cf2d5a5239006285", "packages": [ { "name": "brick/math", @@ -508,6 +508,70 @@ ], "time": "2025-03-06T22:45:56+00:00" }, + { + "name": "firebase/php-jwt", + "version": "v7.0.5", + "source": { + "type": "git", + "url": "https://github.com/googleapis/php-jwt.git", + "reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/googleapis/php-jwt/zipball/47ad26bab5e7c70ae8a6f08ed25ff83631121380", + "reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "guzzlehttp/guzzle": "^7.4", + "phpfastcache/phpfastcache": "^9.2", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", + "psr/cache": "^2.0||^3.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0" + }, + "suggest": { + "ext-sodium": "Support EdDSA (Ed25519) signatures", + "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" + }, + "type": "library", + "autoload": { + "psr-4": { + "Firebase\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Neuman Vong", + "email": "neuman+pear@twilio.com", + "role": "Developer" + }, + { + "name": "Anant Narayanan", + "email": "anant@php.net", + "role": "Developer" + } + ], + "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", + "homepage": "https://github.com/firebase/php-jwt", + "keywords": [ + "jwt", + "php" + ], + "support": { + "issues": "https://github.com/googleapis/php-jwt/issues", + "source": "https://github.com/googleapis/php-jwt/tree/v7.0.5" + }, + "time": "2026-04-01T20:38:03+00:00" + }, { "name": "fruitcake/php-cors", "version": "v1.4.0", @@ -8369,12 +8433,12 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, "platform": { "php": "^8.3" }, - "platform-dev": [], - "plugin-api-version": "2.6.0" + "platform-dev": {}, + "plugin-api-version": "2.9.0" }