Implement authentication endpoints

This commit is contained in:
Daniel_I_Am 2021-09-02 12:18:31 +02:00
parent 5cfa98653e
commit af00f64cf7
6 changed files with 200 additions and 10 deletions

View File

@ -0,0 +1,81 @@
<?php
namespace App\Console\Commands;
use App\Http\Services\AuthService;
use App\Models\AuthenticationToken;
use Carbon\Carbon;
use Illuminate\Console\Command;
class AuthenticationCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'auth:escalate';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Escalate user to a management session';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$authTokens = AuthenticationToken::select('id', 'token', 'authenticated', 'valid_until')->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;
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace App\Http\Controllers;
use App\Http\Services\AuthService;
use Illuminate\Http\Request;
class AuthenticationController extends Controller
{
private $authService;
public function __construct(AuthService $authService)
{
$this->authService = $authService;
}
public function isAuthenticated()
{
return [
'status' => $this->authService->isAuthenticated()
];
}
public function requestAuthentication()
{
$token = $this->authService->generateToken();
return response()->json($token);
}
}

View File

@ -2,25 +2,47 @@
namespace App\Http\Services; namespace App\Http\Services;
use App\Models\AuthenticationToken;
use Carbon\Carbon;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
class AuthService class AuthService
{ {
/**
* Check whether the user is authenticated
*
* @return boolean
*/
public function isAuthenticated() 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();
} }
} }

View File

@ -0,0 +1,21 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class AuthenticationToken extends Model
{
use HasFactory;
protected $fillable = [
'token',
'valid_until',
];
protected $casts = [
'valid_until' => 'datetime',
'authenticated' => 'boolean',
];
}

View File

@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateAuthenticationTokensTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('authentication_tokens', function (Blueprint $table) {
$table->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');
}
}

View File

@ -23,3 +23,5 @@ Route::get('/blog/recent', [\App\Http\Controllers\BlogArticleController::class,
Route::get('/blog/popular', [\App\Http\Controllers\BlogArticleController::class, 'popular']); Route::get('/blog/popular', [\App\Http\Controllers\BlogArticleController::class, 'popular']);
Route::resource('/blog', \App\Http\Controllers\BlogArticleController::class)->except(['create', 'edit']); 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']);