From c206e33aec82e4e61ada582fae596d441748cd72 Mon Sep 17 00:00:00 2001 From: Jonatas Souza Date: Wed, 9 Aug 2023 02:11:12 -0300 Subject: [PATCH] feature/main setting up signed webkey authentication. removing unused cold. --- README.md | 4 +- app/Console/Commands/CreateSignature.php | 52 +++ app/Console/Commands/CreateUser.php | 50 --- app/Http/Controllers/Api/AuthController.php | 77 ----- app/Http/Controllers/Api/CreateToken.php | 27 -- app/Http/Controllers/Api/SendEmail.php | 9 +- app/Http/Kernel.php | 7 +- app/Http/Middleware/Authorize.php | 25 ++ app/Http/Middleware/CheckAuth.php | 34 -- app/Providers/ApiAuthProvider.php | 102 ------ app/Providers/AuthServiceProvider.php | 5 - app/Providers/AuthorizationProvider.php | 74 ++++ app/Providers/RouteServiceProvider.php | 2 +- composer.json | 3 +- composer.lock | 321 +----------------- config/auth.php | 11 +- config/jwt.php | 301 ---------------- config/laravel-mail-api-token.php | 17 + config/laravel-mail-api.php | 4 +- ...000_create_password_reset_tokens_table.php | 27 -- ..._08_19_000000_create_failed_jobs_table.php | 31 -- ...01_create_personal_access_tokens_table.php | 32 -- .../2023_07_25_184311_create_jobs_table.php | 31 -- routes/api.php | 10 +- tests/{Feature => Unit}/CommandsTest.php | 11 - tests/{Feature => Unit}/HttpTest.php | 8 +- tests/{Feature => Unit}/JobsTest.php | 1 - tests/{Feature => Unit}/MailTest.php | 1 - tests/{Feature => Unit}/TokenTest.php | 12 +- 29 files changed, 195 insertions(+), 1094 deletions(-) create mode 100644 app/Console/Commands/CreateSignature.php delete mode 100644 app/Console/Commands/CreateUser.php delete mode 100644 app/Http/Controllers/Api/AuthController.php delete mode 100644 app/Http/Controllers/Api/CreateToken.php create mode 100644 app/Http/Middleware/Authorize.php delete mode 100644 app/Http/Middleware/CheckAuth.php delete mode 100644 app/Providers/ApiAuthProvider.php create mode 100644 app/Providers/AuthorizationProvider.php delete mode 100644 config/jwt.php create mode 100644 config/laravel-mail-api-token.php delete mode 100644 database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php delete mode 100644 database/migrations/2019_08_19_000000_create_failed_jobs_table.php delete mode 100644 database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php delete mode 100644 database/migrations/2023_07_25_184311_create_jobs_table.php rename tests/{Feature => Unit}/CommandsTest.php (59%) rename tests/{Feature => Unit}/HttpTest.php (97%) rename tests/{Feature => Unit}/JobsTest.php (98%) rename tests/{Feature => Unit}/MailTest.php (96%) rename tests/{Feature => Unit}/TokenTest.php (71%) diff --git a/README.md b/README.md index fcd8533..21da08a 100644 --- a/README.md +++ b/README.md @@ -185,13 +185,13 @@ use Laravel\Sanctum\PersonalAccessToken; // from this return [ ... - 'attachments-allowed-mimetypes' => env('ATTACHMENT_MIMETYPES', ['application/pdf', 'image/*']), + 'attachmentsAllowedMimetypes' => env('ATTACHMENT_MIMETYPES', ['application/pdf', 'image/*']), ]; // to this return [ ... - 'attachments-allowed-mimetypes' => env('ATTACHMENT_MIMETYPES', '*'), + 'attachmentsAllowedMimetypes' => env('ATTACHMENT_MIMETYPES', '*'), ]; ``` diff --git a/app/Console/Commands/CreateSignature.php b/app/Console/Commands/CreateSignature.php new file mode 100644 index 0000000..2afa919 --- /dev/null +++ b/app/Console/Commands/CreateSignature.php @@ -0,0 +1,52 @@ +info('Laravel API Service'); + $this->info('Signed access token generation script.'); + $this->warn('Before moving ahead, define your access key in ./config/laravel-mail-api-token.php'); + $this->info('---------------------------------------'); + + $accessKey = $this->ask('Inform the Token Access Key'); + + $tokenAttributes = AuthorizationProvider::getTokenProperties($accessKey); + $timezone = Carbon::now()->toIso8601String(); + $this->info('tz: ' . $timezone); + $signature = AuthorizationProvider::signToken( + token: $tokenAttributes['appKey'], + timeStamp: $timezone, + secret: $tokenAttributes['appSecret'], + ); + + $this->info($signature); + + return 1; + } +} diff --git a/app/Console/Commands/CreateUser.php b/app/Console/Commands/CreateUser.php deleted file mode 100644 index 91a5c51..0000000 --- a/app/Console/Commands/CreateUser.php +++ /dev/null @@ -1,50 +0,0 @@ -ask('Define an Name'); - $email = $this->ask('Define an Email'); - $password = $this->secret('Define a Password'); - - if (User::where('email', $email)->exists()) { - $this->error('User with given email already exists!'); - - return 0; - } - - User::create([ - 'name' => $name, - 'email' => $email, - 'password' => Hash::make($password), - 'email_verified_at' => Carbon::now()->toDateTimeString(), - ]); - - return 1; - } -} diff --git a/app/Http/Controllers/Api/AuthController.php b/app/Http/Controllers/Api/AuthController.php deleted file mode 100644 index 739036f..0000000 --- a/app/Http/Controllers/Api/AuthController.php +++ /dev/null @@ -1,77 +0,0 @@ -middleware('auth:api', ['except' => ['login']]); - } - - /** - * Get a JWT via given credentials. - * - * @return \Illuminate\Http\JsonResponse - */ - public function login(Request $request) - { - $credentials = [ - 'email' => $request->getUser(), - 'password' => $request->getPassword(), - ]; - - if (! $token = auth()->attempt($credentials)) { - return response()->json(['error' => 'Unauthorized'], 401); - } - - return $this->respondWithToken($token); - } - - /** - * Log the user out (Invalidate the token). - * - * @return \Illuminate\Http\JsonResponse - */ - public function logout() - { - auth()->logout(); - - return response()->json(['message' => 'Successfully logged out']); - } - - /** - * Refresh a token. - * - * @return \Illuminate\Http\JsonResponse - */ - public function refresh() - { - return $this->respondWithToken(auth()->refresh(true)); - } - - /** - * Get the token array structure. - * - * @param string $token - * - * @return \Illuminate\Http\JsonResponse - */ - protected function respondWithToken($token) - { - return response()->json([ - 'access_token' => $token, - 'token_type' => 'bearer', - 'expires_in' => auth()->factory()->getTTL() * 60 - ]); - } -} diff --git a/app/Http/Controllers/Api/CreateToken.php b/app/Http/Controllers/Api/CreateToken.php deleted file mode 100644 index 8095a2f..0000000 --- a/app/Http/Controllers/Api/CreateToken.php +++ /dev/null @@ -1,27 +0,0 @@ -user('user'); - - $token = ApiAuthProvider::createToken($user); - - return response() - ->json($token) - ->setStatusCode(201); - } -} diff --git a/app/Http/Controllers/Api/SendEmail.php b/app/Http/Controllers/Api/SendEmail.php index 98393f2..d725a1a 100644 --- a/app/Http/Controllers/Api/SendEmail.php +++ b/app/Http/Controllers/Api/SendEmail.php @@ -6,12 +6,17 @@ use App\Http\Controllers\Controller; use App\Jobs\EmailDispatcher; use App\Jobs\FilesCleanup; +use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Bus; class SendEmail extends Controller { - public function send(Request $request) + /** + * @param Request $request + * @return JsonResponse + */ + public function __invoke(Request $request): JsonResponse { $this->validateRequest($request); @@ -52,7 +57,7 @@ public function send(Request $request) */ private function validateRequest(Request $request): void { - $allowedMimeTypes = config('laravel-mail-api.attachments-allowed-mimetypes'); + $allowedMimeTypes = config('laravel-mail-api.attachmentsAllowedMimetypes'); $rules = [ 'from' => 'required|email', diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index ab8103c..3c6f8ca 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -2,7 +2,7 @@ namespace App\Http; -use App\Http\Middleware\CheckAuth; +use App\Http\Middleware\Authorize; use App\Http\Middleware\ExpectsJsonResponse; use Illuminate\Foundation\Http\Kernel as HttpKernel; @@ -37,10 +37,9 @@ class Kernel extends HttpKernel ], 'api' => [ - // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, - \Illuminate\Routing\Middleware\ThrottleRequests::class.':api', + \Illuminate\Routing\Middleware\ThrottleRequests::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, - CheckAuth::class, + Authorize::class, ExpectsJsonResponse::class, ], ]; diff --git a/app/Http/Middleware/Authorize.php b/app/Http/Middleware/Authorize.php new file mode 100644 index 0000000..8c7da1b --- /dev/null +++ b/app/Http/Middleware/Authorize.php @@ -0,0 +1,25 @@ +path() !== 'api/token/login') { - if (! Auth::check()) { - $exception = new UnauthorizedException('Unauthorized.'); - - Log::error($exception->getMessage()); - throw $exception; - } - - Log::info('Authenticated'); - } - return $next($request); - } -} diff --git a/app/Providers/ApiAuthProvider.php b/app/Providers/ApiAuthProvider.php deleted file mode 100644 index 6f36cb7..0000000 --- a/app/Providers/ApiAuthProvider.php +++ /dev/null @@ -1,102 +0,0 @@ -toArray())->only('id', 'email')->toArray()); - - $user->tokens()->delete(); - $expiresAt = Carbon::now()->addMinutes(config('laravel-mail-api.token-time')); - $token = $user->createToken(name: "{$user->name}:{$user->password}", expiresAt: $expiresAt); - - Log::info('Token issued'); - - return [ - 'token' => $token->plainTextToken, - 'expires_at' => $expiresAt, - ]; - } catch (Exception $exception) { - $exception = new Exception('Unable to generate token. '.$exception->getMessage()); - - Log::error($exception->getMessage()); - - throw $exception; - } - } - - public static function findToken(string $token) - { - return PersonalAccessToken::findToken($token); - } - - public static function auth(Request $request) - { - if ($request->path() === 'api/token') { - return self::basicAuth($request); - } else { - return self::tokenAuth($request); - } - } - - public static function basicAuth(Request $request): Authenticatable|null - { - Log::info('Basic Auth'); - - try { - Auth::guard('user')->onceBasic(); - } catch (UnauthorizedHttpException $exception) { - Log::error($exception->getMessage()); - - throw $exception; - } - - Log::info('User authenticated.'); - - return Auth::guard('user')->user(); - } - - public static function tokenAuth(Request $request): Authenticatable|null - { - Log::info('Token validation'); - - if (is_null($token = self::findToken($request->bearerToken()))) { - $exception = new UnauthorizedHttpException('Token', 'Invalid token.'); - - Log::error($exception->getMessage()); - throw $exception; - } - - if (Carbon::parse($token->expires_at)->lessThan(Carbon::now())) { - $exception = new UnauthorizedHttpException('Token', 'Token expired.'); - - Log::error($exception->getMessage()); - throw $exception; - } - - Log::info('Token Valid'); - - return User::whereId($token->tokenable_id)->first(); - } -} diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 525fc36..e512e80 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -3,7 +3,6 @@ namespace App\Providers; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; -use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class AuthServiceProvider extends ServiceProvider @@ -23,9 +22,5 @@ class AuthServiceProvider extends ServiceProvider public function boot(): void { $this->registerPolicies(); - - Auth::viaRequest('mail-api', function (Request $request) { - return ApiAuthProvider::auth($request); - }); } } diff --git a/app/Providers/AuthorizationProvider.php b/app/Providers/AuthorizationProvider.php new file mode 100644 index 0000000..70d2f4b --- /dev/null +++ b/app/Providers/AuthorizationProvider.php @@ -0,0 +1,74 @@ +headers->get('accessKey') ?? ''; + $signedKey = $request->bearerToken(); + $timeStamp = $request->headers->get('ts') ?? ''; + $timeZone = $request->headers->get('tz') ?? ''; + + self::checkTokenExpired($timeStamp, $timeZone); + self::checkSignature($accessKey, $signedKey, $timeStamp); + } + + /** + * @param string $accessKey + * @param string $signedKey + * @param string $timeStamp + * @return void + * @throws Exception + */ + public static function checkSignature(string $accessKey, string $signedKey, string $timeStamp): void + { + $accessProperties = self::getTokenProperties($accessKey); + + $hashToken = self::signToken( + appKey: $accessProperties['appKey'], + appSecret: $accessProperties['appSecret'], + timeStamp: $timeStamp, + ); + + if (! hash_equals($hashToken, $signedKey)) { + throw new Exception('Invalid token.'); + } + } + + /** + * @param string $token + * @param string $timeStamp + * @param string $secret + * @return string + */ + public static function signToken(string $appKey, string $appSecret, string $timeStamp): string + { + return hash_hmac(config('laravel-mail-api-token.hashSignature'), $appKey . $timeStamp, $appSecret); + } + + public static function checkTokenExpired(string $timeStamp, string $timeZone): void + { + + } + + public static function getTokenProperties(string $accessKey) + { + return config('laravel-mail-api.accessTokens')[$accessKey] + ?? [ + 'appKey' => '', + 'appSecret' => '' + ]; + } +} diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 98cbd87..257eb23 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -40,7 +40,7 @@ public function boot(): void protected function configureRateLimiting(): void { RateLimiter::for('api', function (Request $request) { - return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip()); + return Limit::perMinute(60)->by($request->ip()); }); } } diff --git a/composer.json b/composer.json index e98d025..73f1171 100644 --- a/composer.json +++ b/composer.json @@ -26,8 +26,7 @@ "laravel/framework": "^10.0", "laravel/sanctum": "^3.2", "laravel/tinker": "^2.8", - "predis/predis": "^2.2", - "tymon/jwt-auth": "^2.0" + "predis/predis": "^2.2" }, "require-dev": { "fakerphp/faker": "^1.9.1", diff --git a/composer.lock b/composer.lock index 886174c..20969be 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": "03788ad1a106905e9a7453644599bf7b", + "content-hash": "6215aef923a0683a29441c218acff681", "packages": [ { "name": "brick/math", @@ -1368,146 +1368,6 @@ }, "time": "2023-02-15T16:40:09+00:00" }, - { - "name": "lcobucci/clock", - "version": "2.3.0", - "source": { - "type": "git", - "url": "https://github.com/lcobucci/clock.git", - "reference": "c7aadcd6fd97ed9e199114269c0be3f335e38876" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/lcobucci/clock/zipball/c7aadcd6fd97ed9e199114269c0be3f335e38876", - "reference": "c7aadcd6fd97ed9e199114269c0be3f335e38876", - "shasum": "" - }, - "require": { - "php": "~8.1.0 || ~8.2.0", - "stella-maris/clock": "^0.1.7" - }, - "provide": { - "psr/clock-implementation": "1.0" - }, - "require-dev": { - "infection/infection": "^0.26", - "lcobucci/coding-standard": "^9.0", - "phpstan/extension-installer": "^1.2", - "phpstan/phpstan": "^1.9.4", - "phpstan/phpstan-deprecation-rules": "^1.1.1", - "phpstan/phpstan-phpunit": "^1.3.2", - "phpstan/phpstan-strict-rules": "^1.4.4", - "phpunit/phpunit": "^9.5.27" - }, - "type": "library", - "autoload": { - "psr-4": { - "Lcobucci\\Clock\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Luís Cobucci", - "email": "lcobucci@gmail.com" - } - ], - "description": "Yet another clock abstraction", - "support": { - "issues": "https://github.com/lcobucci/clock/issues", - "source": "https://github.com/lcobucci/clock/tree/2.3.0" - }, - "funding": [ - { - "url": "https://github.com/lcobucci", - "type": "github" - }, - { - "url": "https://www.patreon.com/lcobucci", - "type": "patreon" - } - ], - "time": "2022-12-19T14:38:11+00:00" - }, - { - "name": "lcobucci/jwt", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/lcobucci/jwt.git", - "reference": "55564265fddf810504110bd68ca311932324b0e9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/lcobucci/jwt/zipball/55564265fddf810504110bd68ca311932324b0e9", - "reference": "55564265fddf810504110bd68ca311932324b0e9", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "ext-openssl": "*", - "lcobucci/clock": "^2.0", - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "infection/infection": "^0.20", - "lcobucci/coding-standard": "^6.0", - "mikey179/vfsstream": "^1.6", - "phpbench/phpbench": "^0.17", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-deprecation-rules": "^0.12", - "phpstan/phpstan-phpunit": "^0.12", - "phpstan/phpstan-strict-rules": "^0.12", - "phpunit/php-invoker": "^3.1", - "phpunit/phpunit": "^9.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "psr-4": { - "Lcobucci\\JWT\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Luís Cobucci", - "email": "lcobucci@gmail.com", - "role": "Developer" - } - ], - "description": "A simple library to work with JSON Web Token and JSON Web Signature", - "keywords": [ - "JWS", - "jwt" - ], - "support": { - "issues": "https://github.com/lcobucci/jwt/issues", - "source": "https://github.com/lcobucci/jwt/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/lcobucci", - "type": "github" - }, - { - "url": "https://www.patreon.com/lcobucci", - "type": "patreon" - } - ], - "time": "2021-09-28T19:18:28+00:00" - }, { "name": "league/commonmark", "version": "2.4.0", @@ -2530,54 +2390,6 @@ ], "time": "2023-06-14T10:37:31+00:00" }, - { - "name": "psr/clock", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/clock.git", - "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", - "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", - "shasum": "" - }, - "require": { - "php": "^7.0 || ^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Psr\\Clock\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for reading the clock.", - "homepage": "https://github.com/php-fig/clock", - "keywords": [ - "clock", - "now", - "psr", - "psr-20", - "time" - ], - "support": { - "issues": "https://github.com/php-fig/clock/issues", - "source": "https://github.com/php-fig/clock/tree/1.0.0" - }, - "time": "2022-11-25T14:36:26+00:00" - }, { "name": "psr/container", "version": "2.0.2", @@ -3243,53 +3055,6 @@ ], "time": "2023-04-15T23:01:58+00:00" }, - { - "name": "stella-maris/clock", - "version": "0.1.7", - "source": { - "type": "git", - "url": "https://github.com/stella-maris-solutions/clock.git", - "reference": "fa23ce16019289a18bb3446fdecd45befcdd94f8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/stella-maris-solutions/clock/zipball/fa23ce16019289a18bb3446fdecd45befcdd94f8", - "reference": "fa23ce16019289a18bb3446fdecd45befcdd94f8", - "shasum": "" - }, - "require": { - "php": "^7.0|^8.0", - "psr/clock": "^1.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "StellaMaris\\Clock\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Andreas Heigl", - "role": "Maintainer" - } - ], - "description": "A pre-release of the proposed PSR-20 Clock-Interface", - "homepage": "https://gitlab.com/stella-maris/clock", - "keywords": [ - "clock", - "datetime", - "point in time", - "psr20" - ], - "support": { - "source": "https://github.com/stella-maris-solutions/clock/tree/0.1.7" - }, - "time": "2022-11-25T16:15:06+00:00" - }, { "name": "symfony/console", "version": "v6.3.0", @@ -5586,90 +5351,6 @@ }, "time": "2023-01-03T09:29:04+00:00" }, - { - "name": "tymon/jwt-auth", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/tymondesigns/jwt-auth.git", - "reference": "b0868a5b00801889a9e0c81a737963d8004e708c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/tymondesigns/jwt-auth/zipball/b0868a5b00801889a9e0c81a737963d8004e708c", - "reference": "b0868a5b00801889a9e0c81a737963d8004e708c", - "shasum": "" - }, - "require": { - "illuminate/auth": "^9.0|^10.0", - "illuminate/contracts": "^9.0|^10.0", - "illuminate/http": "^9.0|^10.0", - "illuminate/support": "^9.0|^10.0", - "lcobucci/jwt": "^4.0", - "nesbot/carbon": "^2.0", - "php": "^8.0" - }, - "require-dev": { - "illuminate/console": "^9.0|^10.0", - "illuminate/database": "^9.0|^10.0", - "illuminate/routing": "^9.0|^10.0", - "mockery/mockery": ">=0.9.9", - "phpunit/phpunit": "^9.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-develop": "1.0-dev", - "dev-2.x": "2.0-dev" - }, - "laravel": { - "aliases": { - "JWTAuth": "Tymon\\JWTAuth\\Facades\\JWTAuth", - "JWTFactory": "Tymon\\JWTAuth\\Facades\\JWTFactory" - }, - "providers": [ - "Tymon\\JWTAuth\\Providers\\LaravelServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Tymon\\JWTAuth\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Sean Tymon", - "email": "tymon148@gmail.com", - "homepage": "https://tymon.xyz", - "role": "Developer" - } - ], - "description": "JSON Web Token Authentication for Laravel and Lumen", - "homepage": "https://github.com/tymondesigns/jwt-auth", - "keywords": [ - "Authentication", - "JSON Web Token", - "auth", - "jwt", - "laravel" - ], - "support": { - "issues": "https://github.com/tymondesigns/jwt-auth/issues", - "source": "https://github.com/tymondesigns/jwt-auth" - }, - "funding": [ - { - "url": "https://www.patreon.com/seantymon", - "type": "patreon" - } - ], - "time": "2023-02-16T16:29:41+00:00" - }, { "name": "vlucas/phpdotenv", "version": "v5.5.0", diff --git a/config/auth.php b/config/auth.php index 6a7aad5..1301477 100644 --- a/config/auth.php +++ b/config/auth.php @@ -10,11 +10,10 @@ | This option controls the default authentication "guard" and password | reset options for your application. You may change these defaults | as required, but they're a perfect start for most applications. - | */ 'defaults' => [ - 'guard' => 'api', + 'guard' => 'session', 'passwords' => 'users', ], @@ -31,19 +30,15 @@ | users are actually retrieved out of your database or other storage | mechanisms used by this application to persist your user's data. | - | Supported: "session", "mail-api" + | Supported: "" | */ 'guards' => [ - 'user' => [ + 'session' => [ 'driver' => 'session', 'provider' => 'users', ], - 'api' => [ - 'driver' => 'jwt', - 'provider' => 'users', - ], ], /* diff --git a/config/jwt.php b/config/jwt.php deleted file mode 100644 index f83234d..0000000 --- a/config/jwt.php +++ /dev/null @@ -1,301 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -return [ - - /* - |-------------------------------------------------------------------------- - | JWT Authentication Secret - |-------------------------------------------------------------------------- - | - | Don't forget to set this in your .env file, as it will be used to sign - | your tokens. A helper command is provided for this: - | `php artisan jwt:secret` - | - | Note: This will be used for Symmetric algorithms only (HMAC), - | since RSA and ECDSA use a private/public key combo (See below). - | - */ - - 'secret' => env('JWT_SECRET'), - - /* - |-------------------------------------------------------------------------- - | JWT Authentication Keys - |-------------------------------------------------------------------------- - | - | The algorithm you are using, will determine whether your tokens are - | signed with a random string (defined in `JWT_SECRET`) or using the - | following public & private keys. - | - | Symmetric Algorithms: - | HS256, HS384 & HS512 will use `JWT_SECRET`. - | - | Asymmetric Algorithms: - | RS256, RS384 & RS512 / ES256, ES384 & ES512 will use the keys below. - | - */ - - 'keys' => [ - - /* - |-------------------------------------------------------------------------- - | Public Key - |-------------------------------------------------------------------------- - | - | A path or resource to your public key. - | - | E.g. 'file://path/to/public/key' - | - */ - - 'public' => env('JWT_PUBLIC_KEY'), - - /* - |-------------------------------------------------------------------------- - | Private Key - |-------------------------------------------------------------------------- - | - | A path or resource to your private key. - | - | E.g. 'file://path/to/private/key' - | - */ - - 'private' => env('JWT_PRIVATE_KEY'), - - /* - |-------------------------------------------------------------------------- - | Passphrase - |-------------------------------------------------------------------------- - | - | The passphrase for your private key. Can be null if none set. - | - */ - - 'passphrase' => env('JWT_PASSPHRASE'), - - ], - - /* - |-------------------------------------------------------------------------- - | JWT time to live - |-------------------------------------------------------------------------- - | - | Specify the length of time (in minutes) that the token will be valid for. - | Defaults to 1 hour. - | - | You can also set this to null, to yield a never expiring token. - | Some people may want this behaviour for e.g. a mobile app. - | This is not particularly recommended, so make sure you have appropriate - | systems in place to revoke the token if necessary. - | Notice: If you set this to null you should remove 'exp' element from 'required_claims' list. - | - */ - - 'ttl' => env('JWT_TTL', 60), - - /* - |-------------------------------------------------------------------------- - | Refresh time to live - |-------------------------------------------------------------------------- - | - | Specify the length of time (in minutes) that the token can be refreshed - | within. I.E. The user can refresh their token within a 2 week window of - | the original token being created until they must re-authenticate. - | Defaults to 2 weeks. - | - | You can also set this to null, to yield an infinite refresh time. - | Some may want this instead of never expiring tokens for e.g. a mobile app. - | This is not particularly recommended, so make sure you have appropriate - | systems in place to revoke the token if necessary. - | - */ - - 'refresh_ttl' => env('JWT_REFRESH_TTL', 20160), - - /* - |-------------------------------------------------------------------------- - | JWT hashing algorithm - |-------------------------------------------------------------------------- - | - | Specify the hashing algorithm that will be used to sign the token. - | - */ - - 'algo' => env('JWT_ALGO', Tymon\JWTAuth\Providers\JWT\Provider::ALGO_HS256), - - /* - |-------------------------------------------------------------------------- - | Required Claims - |-------------------------------------------------------------------------- - | - | Specify the required claims that must exist in any token. - | A TokenInvalidException will be thrown if any of these claims are not - | present in the payload. - | - */ - - 'required_claims' => [ - 'iss', - 'iat', - 'exp', - 'nbf', - 'sub', - 'jti', - ], - - /* - |-------------------------------------------------------------------------- - | Persistent Claims - |-------------------------------------------------------------------------- - | - | Specify the claim keys to be persisted when refreshing a token. - | `sub` and `iat` will automatically be persisted, in - | addition to the these claims. - | - | Note: If a claim does not exist then it will be ignored. - | - */ - - 'persistent_claims' => [ - // 'foo', - // 'bar', - ], - - /* - |-------------------------------------------------------------------------- - | Lock Subject - |-------------------------------------------------------------------------- - | - | This will determine whether a `prv` claim is automatically added to - | the token. The purpose of this is to ensure that if you have multiple - | authentication models e.g. `App\User` & `App\OtherPerson`, then we - | should prevent one authentication request from impersonating another, - | if 2 tokens happen to have the same id across the 2 different models. - | - | Under specific circumstances, you may want to disable this behaviour - | e.g. if you only have one authentication model, then you would save - | a little on token size. - | - */ - - 'lock_subject' => true, - - /* - |-------------------------------------------------------------------------- - | Leeway - |-------------------------------------------------------------------------- - | - | This property gives the jwt timestamp claims some "leeway". - | Meaning that if you have any unavoidable slight clock skew on - | any of your servers then this will afford you some level of cushioning. - | - | This applies to the claims `iat`, `nbf` and `exp`. - | - | Specify in seconds - only if you know you need it. - | - */ - - 'leeway' => env('JWT_LEEWAY', 0), - - /* - |-------------------------------------------------------------------------- - | Blacklist Enabled - |-------------------------------------------------------------------------- - | - | In order to invalidate tokens, you must have the blacklist enabled. - | If you do not want or need this functionality, then set this to false. - | - */ - - 'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true), - - /* - | ------------------------------------------------------------------------- - | Blacklist Grace Period - | ------------------------------------------------------------------------- - | - | When multiple concurrent requests are made with the same JWT, - | it is possible that some of them fail, due to token regeneration - | on every request. - | - | Set grace period in seconds to prevent parallel request failure. - | - */ - - 'blacklist_grace_period' => env('JWT_BLACKLIST_GRACE_PERIOD', 0), - - /* - |-------------------------------------------------------------------------- - | Cookies encryption - |-------------------------------------------------------------------------- - | - | By default Laravel encrypt cookies for security reason. - | If you decide to not decrypt cookies, you will have to configure Laravel - | to not encrypt your cookie token by adding its name into the $except - | array available in the middleware "EncryptCookies" provided by Laravel. - | see https://laravel.com/docs/master/responses#cookies-and-encryption - | for details. - | - | Set it to true if you want to decrypt cookies. - | - */ - - 'decrypt_cookies' => false, - - /* - |-------------------------------------------------------------------------- - | Providers - |-------------------------------------------------------------------------- - | - | Specify the various providers used throughout the package. - | - */ - - 'providers' => [ - - /* - |-------------------------------------------------------------------------- - | JWT Provider - |-------------------------------------------------------------------------- - | - | Specify the provider that is used to create and decode the tokens. - | - */ - - 'jwt' => Tymon\JWTAuth\Providers\JWT\Lcobucci::class, - - /* - |-------------------------------------------------------------------------- - | Authentication Provider - |-------------------------------------------------------------------------- - | - | Specify the provider that is used to authenticate users. - | - */ - - 'auth' => Tymon\JWTAuth\Providers\Auth\Illuminate::class, - - /* - |-------------------------------------------------------------------------- - | Storage Provider - |-------------------------------------------------------------------------- - | - | Specify the provider that is used to store tokens in the blacklist. - | - */ - - 'storage' => Tymon\JWTAuth\Providers\Storage\Illuminate::class, - - ], - -]; diff --git a/config/laravel-mail-api-token.php b/config/laravel-mail-api-token.php new file mode 100644 index 0000000..a316ecf --- /dev/null +++ b/config/laravel-mail-api-token.php @@ -0,0 +1,17 @@ + env('HASH_SIGNATURE', 'sha256'), + + #access tokens for signature + 'accessTokens' => [ + 'access-key-user-1' => [ + 'appKey' => 'jwYitJJOop2v', + 'appSecret' => 'token', + ], + // unit tests purpose + 'tests' => [ + 'appKey' => 'test-token-string', + 'appSecret' => 'token', + ], + ], +]; diff --git a/config/laravel-mail-api.php b/config/laravel-mail-api.php index e661f27..0bc75be 100644 --- a/config/laravel-mail-api.php +++ b/config/laravel-mail-api.php @@ -1,8 +1,8 @@ env('TOKEN_TIME', 120), + 'tokenTime' => env('TOKEN_TIME', 120), 'language' => env('LANGUAGE', 'en'), 'template' => env('DEFAULT_TEMPLATE', 'hello-world'), - 'attachments-allowed-mimetypes' => env('ATTACHMENT_MIMETYPES', ['application/pdf', 'image/*']), + 'attachmentsAllowedMimetypes' => env('ATTACHMENT_MIMETYPES', ['application/pdf', 'image/*']), ]; diff --git a/database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php b/database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php deleted file mode 100644 index d8336e7..0000000 --- a/database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php +++ /dev/null @@ -1,27 +0,0 @@ -string('email')->primary(); - $table->string('token'); - $table->timestamp('created_at')->nullable(); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::dropIfExists('password_reset_tokens'); - } -}; diff --git a/database/migrations/2019_08_19_000000_create_failed_jobs_table.php b/database/migrations/2019_08_19_000000_create_failed_jobs_table.php deleted file mode 100644 index 667f82c..0000000 --- a/database/migrations/2019_08_19_000000_create_failed_jobs_table.php +++ /dev/null @@ -1,31 +0,0 @@ -id(); - $table->string('uuid')->unique(); - $table->text('connection'); - $table->text('queue'); - $table->longText('payload'); - $table->longText('exception'); - $table->timestamp('failed_at')->useCurrent(); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::dropIfExists('failed_jobs'); - } -}; diff --git a/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php b/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php deleted file mode 100644 index 668cd96..0000000 --- a/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php +++ /dev/null @@ -1,32 +0,0 @@ -id(); - $table->morphs('tokenable'); - $table->string('name'); - $table->string('token', 64)->unique(); - $table->text('abilities')->nullable(); - $table->timestamp('last_used_at')->nullable(); - $table->timestamp('expires_at')->nullable(); - $table->timestamps(); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::dropIfExists('personal_access_tokens'); - } -}; diff --git a/database/migrations/2023_07_25_184311_create_jobs_table.php b/database/migrations/2023_07_25_184311_create_jobs_table.php deleted file mode 100644 index 25d5a54..0000000 --- a/database/migrations/2023_07_25_184311_create_jobs_table.php +++ /dev/null @@ -1,31 +0,0 @@ -bigIncrements('id'); - $table->string('queue')->index(); - $table->longText('payload'); - $table->unsignedTinyInteger('attempts'); - $table->unsignedInteger('reserved_at')->nullable(); - $table->unsignedInteger('available_at'); - $table->unsignedInteger('created_at'); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::dropIfExists('jobs'); - } -}; diff --git a/routes/api.php b/routes/api.php index 9e1b44a..3b6afc0 100644 --- a/routes/api.php +++ b/routes/api.php @@ -13,12 +13,4 @@ | */ -#Route::post('/token', \App\Http\Controllers\Api\CreateToken::class); -Route::post('/send-message', [\App\Http\Controllers\Api\SendEmail::class, 'send']); - -Route::prefix('/token')->group(function () { - Route::post('/login', [\App\Http\Controllers\Api\AuthController::class, 'login']); -}); - -#Route::post('/logout', 'AuthController@logout'); -#Route::post('/refresh', 'AuthController@refresh'); +Route::post('/email/send', \App\Http\Controllers\Api\SendEmail::class); diff --git a/tests/Feature/CommandsTest.php b/tests/Unit/CommandsTest.php similarity index 59% rename from tests/Feature/CommandsTest.php rename to tests/Unit/CommandsTest.php index 6684ad0..40c6b61 100644 --- a/tests/Feature/CommandsTest.php +++ b/tests/Unit/CommandsTest.php @@ -1,6 +1,5 @@ assertNotNull(User::whereEmail($email)); } - public function test_failed_create_user_command() - { - $user = User::factory()->create(); - - $this->artisan('app:create-user') - ->expectsQuestion('Define an Name', fake()->name) - ->expectsQuestion('Define an Email', $user->email) - ->expectsQuestion('Define a Password', '123456') - ->assertExitCode(0); - } } diff --git a/tests/Feature/HttpTest.php b/tests/Unit/HttpTest.php similarity index 97% rename from tests/Feature/HttpTest.php rename to tests/Unit/HttpTest.php index 7dc9a2e..a23fa14 100644 --- a/tests/Feature/HttpTest.php +++ b/tests/Unit/HttpTest.php @@ -1,20 +1,16 @@ create(); try { - $token = ApiAuthProvider::createToken($user); + $token = AuthorizationProvider::createToken($user); $this->assertIsArray($token); $this->assertArrayHasKey('token', $token); @@ -32,9 +28,9 @@ public function test_should_find_auth_by_token() $user = User::factory()->create(); try { - $token = ApiAuthProvider::createToken($user); + $token = AuthorizationProvider::createToken($user); - $storedToken = ApiAuthProvider::findToken($token['token']); + $storedToken = AuthorizationProvider::findToken($token['token']); $this->assertNotNull($storedToken);