From 8bb46c34ebb88bbaea6a7c76faa7314e2c98c25e Mon Sep 17 00:00:00 2001 From: dogukanoksuz Date: Mon, 29 Jan 2024 13:35:15 +0000 Subject: [PATCH] feature: Secure JWT token and cookies system --- app/Http/Controllers/API/AuthController.php | 45 +++++++++++++--- app/Http/Kernel.php | 4 +- .../Middleware/CookieJWTAuthenticator.php | 25 +++++++++ app/Http/Middleware/EncryptCookies.php | 1 + app/Http/Middleware/LimanTokenUploadCheck.php | 52 ------------------- app/Http/Middleware/TusAuthenticated.php | 6 +-- routes/web.php | 5 +- 7 files changed, 70 insertions(+), 68 deletions(-) create mode 100644 app/Http/Middleware/CookieJWTAuthenticator.php delete mode 100644 app/Http/Middleware/LimanTokenUploadCheck.php diff --git a/app/Http/Controllers/API/AuthController.php b/app/Http/Controllers/API/AuthController.php index 145854c8..ec31bd7c 100644 --- a/app/Http/Controllers/API/AuthController.php +++ b/app/Http/Controllers/API/AuthController.php @@ -21,6 +21,7 @@ use Illuminate\Auth\Events\PasswordReset; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Cookie; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Password; @@ -181,11 +182,15 @@ public function setupTwoFactorAuthentication(Request $request) * * @return \Illuminate\Http\JsonResponse */ - public function logout() + public function logout(Request $request) { + $deleteToken = Cookie::forget('token', '/', $request->getHost()); + $deleteCurrentUser = Cookie::forget('currentUser', '/', $request->getHost()); auth('api')->logout(); - return response()->json(['message' => 'User successfully signed out']); + return response()->json(['message' => 'User successfully signed out']) + ->withCookie($deleteToken) + ->withCookie($deleteCurrentUser); } /** @@ -575,13 +580,17 @@ protected function createNewToken($token, Request $request = null) 'user_agent' => $request->userAgent(), ]); - return response()->json([ - 'access_token' => $token, - 'token_type' => 'bearer', - 'expires_in' => auth('api')->factory()->getTTL() * 60, + $return = [ 'expired_at' => (auth('api')->factory()->getTTL() * 60 + time()) * 1000, 'user' => [ - ...User::find(auth('api')->user()->id)->toArray(), + ...User::find(auth('api')->user()->id, [ + 'id', + 'name', + 'email', + 'locale', + 'status', + 'username' + ])->toArray(), 'last_login_at' => Carbon::now()->toDateTimeString(), 'last_login_ip' => $request->ip(), 'permissions' => [ @@ -592,7 +601,27 @@ protected function createNewToken($token, Request $request = null) 'view_logs' => Permission::can(auth('api')->user()->id, 'liman', 'id', 'view_logs'), ], ], - ]); + ]; + + return response()->json($return)->withCookie(cookie( + 'token', + $token, + auth('api')->factory()->getTTL() * 60, + null, + $request->getHost(), + true, + true, + false + ))->withCookie(cookie( + 'currentUser', + json_encode($return), + auth('api')->factory()->getTTL() * 60, + null, + $request->getHost(), + true, + false, + false + )); } /** diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index b70d12f8..3e4a478e 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -18,11 +18,12 @@ class Kernel extends HttpKernel Middleware\TrimStrings::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, Middleware\TrustProxies::class, + Middleware\EncryptCookies::class, + Middleware\CookieJWTAuthenticator::class, ]; protected $middlewareGroups = [ 'web' => [ - Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \App\Http\Middleware\APILogin::class, @@ -55,7 +56,6 @@ class Kernel extends HttpKernel 'extension' => \App\Http\Middleware\Extension::class, 'block_except_limans' => \App\Http\Middleware\BlockExceptLimans::class, 'google2fa' => \PragmaRX\Google2FALaravel\MiddlewareStateless::class, - 'upload_token_check' => \App\Http\Middleware\LimanTokenUploadCheck::class, ]; protected $middlewarePriority = [ diff --git a/app/Http/Middleware/CookieJWTAuthenticator.php b/app/Http/Middleware/CookieJWTAuthenticator.php new file mode 100644 index 00000000..b124bc90 --- /dev/null +++ b/app/Http/Middleware/CookieJWTAuthenticator.php @@ -0,0 +1,25 @@ +hasCookie('token')) { + $request->headers->set('Authorization', 'Bearer ' . $request->cookie('token')); + } + + return $next($request); + } +} diff --git a/app/Http/Middleware/EncryptCookies.php b/app/Http/Middleware/EncryptCookies.php index 15c4e54f..9edaec3b 100644 --- a/app/Http/Middleware/EncryptCookies.php +++ b/app/Http/Middleware/EncryptCookies.php @@ -19,5 +19,6 @@ class EncryptCookies extends Middleware protected $except = [ // We are using this in order to allow WebSSH to read unencrypted xsrf cookie. '_xsrf', + 'currentUser' ]; } diff --git a/app/Http/Middleware/LimanTokenUploadCheck.php b/app/Http/Middleware/LimanTokenUploadCheck.php deleted file mode 100644 index 9cf5f81e..00000000 --- a/app/Http/Middleware/LimanTokenUploadCheck.php +++ /dev/null @@ -1,52 +0,0 @@ -token) { - $token = $request->token; - } else if ($request->headers->get('Extension-Token')) { - $token = $request->headers->get('Extension-Token'); - } - - if (! $token) { - if (auth('api')->check()) { - return $next($request); - } - - return response()->json([ - 'status' => 'error', - 'message' => 'Extension-Token header is missing.', - ], 401); - } - - $obj = Token::where('token', $token)->first(); - if (! $obj) { - return response()->json([ - 'status' => 'error', - 'message' => 'Extension-Token is invalid.', - ], 401); - } - - Log::info('Extension-Token is valid. User ip: ' . $request->ip); - - return $next($request); - } -} diff --git a/app/Http/Middleware/TusAuthenticated.php b/app/Http/Middleware/TusAuthenticated.php index a1f1a198..b413b44c 100644 --- a/app/Http/Middleware/TusAuthenticated.php +++ b/app/Http/Middleware/TusAuthenticated.php @@ -23,7 +23,7 @@ class TusAuthenticated implements TusMiddleware */ public function handle(Request $request, Response $response) { - if (auth()->check()) { + if (auth('api')->check()) { return; } @@ -39,12 +39,12 @@ public function handle(Request $request, Response $response) return true; } - throw new UnauthorizedHttpException('Extension-Token header is missing.'); + throw new UnauthorizedHttpException('', 'Extension-Token header is missing.'); } $obj = Token::where('token', $token)->first(); if (! $obj) { - throw new UnauthorizedHttpException('Extension-Token is invalid.'); + throw new UnauthorizedHttpException('', 'Extension-Token is invalid.'); } Log::info('Extension-Token is valid. User ip: ' . request()->ip); diff --git a/routes/web.php b/routes/web.php index 852869ef..7e347eed 100644 --- a/routes/web.php +++ b/routes/web.php @@ -36,8 +36,7 @@ $response = $server->serve(); return $response->send(); }) - ->where('any', '.*') - ->middleware(['upload_token_check']); + ->where('any', '.*'); Route::post('/upload_info', function () { request()->validate([ @@ -59,7 +58,7 @@ } return $info; -})->middleware(['upload_token_check']); +}); Route::get( '/eklenti/{extension_id}/public/{any}',