From af00f64cf73fe8f47a18433b452280517d2c61b0 Mon Sep 17 00:00:00 2001 From: Daniel-I-Am Date: Thu, 2 Sep 2021 12:18:31 +0200 Subject: [PATCH] Implement authentication endpoints --- .../Commands/AuthenticationCommand.php | 81 +++++++++++++++++++ .../Controllers/AuthenticationController.php | 29 +++++++ app/Http/Services/AuthService.php | 42 +++++++--- app/Models/AuthenticationToken.php | 21 +++++ ...339_create_authentication_tokens_table.php | 35 ++++++++ routes/api.php | 2 + 6 files changed, 200 insertions(+), 10 deletions(-) create mode 100644 app/Console/Commands/AuthenticationCommand.php create mode 100644 app/Http/Controllers/AuthenticationController.php create mode 100644 app/Models/AuthenticationToken.php create mode 100644 database/migrations/2021_09_02_093339_create_authentication_tokens_table.php diff --git a/app/Console/Commands/AuthenticationCommand.php b/app/Console/Commands/AuthenticationCommand.php new file mode 100644 index 0000000..4e07056 --- /dev/null +++ b/app/Console/Commands/AuthenticationCommand.php @@ -0,0 +1,81 @@ +whereDate('valid_until', '>', Carbon::now())->get(); + + $this->table(['id', 'token', 'authenticated', 'valid_until'], $authTokens); + + $response = $this->ask('Token ID to escalate:'); + + if (strlen($response) === 0) { + $this->info('Nothing entered, exiting.'); + return 0; + } + + if (!is_numeric($response)) { + $this->info('Invalid input entered, exiting.'); + return 1; + } + + $id = (int)$response; + $token = AuthenticationToken::find($id); + + if ($token === null) { + $this->info('Invalid token ID given, exiting.'); + return 1; + } + + $targetRole = $this->choice('Should this token be a manager or normal user?', ['user', 'manager']); + $authState = ['manager' => true, 'user' => false][$targetRole]; + + $token->authenticated = $authState; + $token->save(); + + if ($authState) { + $this->info('Token ' . $id . ' escalated to manager.'); + } else { + $this->info('Token ' . $id . ' deescalated to user.'); + } + + return 0; + } +} diff --git a/app/Http/Controllers/AuthenticationController.php b/app/Http/Controllers/AuthenticationController.php new file mode 100644 index 0000000..5b524df --- /dev/null +++ b/app/Http/Controllers/AuthenticationController.php @@ -0,0 +1,29 @@ +authService = $authService; + } + + public function isAuthenticated() + { + return [ + 'status' => $this->authService->isAuthenticated() + ]; + } + + public function requestAuthentication() + { + $token = $this->authService->generateToken(); + return response()->json($token); + } +} diff --git a/app/Http/Services/AuthService.php b/app/Http/Services/AuthService.php index 52ca0ac..12c73d1 100644 --- a/app/Http/Services/AuthService.php +++ b/app/Http/Services/AuthService.php @@ -2,25 +2,47 @@ namespace App\Http\Services; +use App\Models\AuthenticationToken; +use Carbon\Carbon; +use Illuminate\Support\Facades\Hash; +use Illuminate\Support\Str; + class AuthService { - /** - * Check whether the user is authenticated - * - * @return boolean - */ public function isAuthenticated() { - return false; + $auth = request()->header('Authorization'); + + if ($auth === null) { + return false; + } + + $authToken = AuthenticationToken::where('token', $auth)->where('valid_until', '>', Carbon::now())->first(); + + if ($authToken === null) { + return false; + } + + return $authToken->authenticated; } - public function authenticate() + public function generateToken() { - session()->put('auth', true); + return AuthenticationToken::create([ + 'token' => Hash::make(Str::random(32)), + 'valid_until' => Carbon::now()->addDay(), + ]); } - public function logout() + public function authenticate(AuthenticationToken $token) { - session()->remove('auth'); + $token->authenticated = true; + $token->save(); + } + + public function logout(AuthenticationToken $token) + { + $token->authenticated = false; + $token->save(); } } diff --git a/app/Models/AuthenticationToken.php b/app/Models/AuthenticationToken.php new file mode 100644 index 0000000..97ceaa5 --- /dev/null +++ b/app/Models/AuthenticationToken.php @@ -0,0 +1,21 @@ + 'datetime', + 'authenticated' => 'boolean', + ]; +} diff --git a/database/migrations/2021_09_02_093339_create_authentication_tokens_table.php b/database/migrations/2021_09_02_093339_create_authentication_tokens_table.php new file mode 100644 index 0000000..bcb5dee --- /dev/null +++ b/database/migrations/2021_09_02_093339_create_authentication_tokens_table.php @@ -0,0 +1,35 @@ +id(); + $table->timestamps(); + + $table->string('token', 60); // The right size to store a hash + $table->boolean('authenticated')->default(false); + $table->dateTime('valid_until'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('authentication_tokens'); + } +} diff --git a/routes/api.php b/routes/api.php index ab553f8..9546d1b 100644 --- a/routes/api.php +++ b/routes/api.php @@ -23,3 +23,5 @@ Route::get('/blog/recent', [\App\Http\Controllers\BlogArticleController::class, Route::get('/blog/popular', [\App\Http\Controllers\BlogArticleController::class, 'popular']); Route::resource('/blog', \App\Http\Controllers\BlogArticleController::class)->except(['create', 'edit']); +Route::get('/auth', [\App\Http\Controllers\AuthenticationController::class, 'isAuthenticated']); +Route::post('/auth', [\App\Http\Controllers\AuthenticationController::class, 'requestAuthentication']);