feat(middleware): add authentication and admin middleware for role-based access control

- Introduced AuthMiddleware to handle user authentication via bearer tokens and API tokens, with a placeholder for token validation.
- Added AdminMiddleware to enforce admin role checks, currently accepting user ID 1 as an admin.
- Created BaseMiddleware as an abstract class for shared middleware functionality.
- Implemented CorsMiddleware to manage CORS headers and preflight responses.

These additions enhance the application's security and access control mechanisms, laying the groundwork for a robust middleware architecture.
This commit is contained in:
Yury Pikhtarev 2025-06-23 01:23:15 +04:00
commit 9a1e17de8d
No known key found for this signature in database
4 changed files with 203 additions and 0 deletions

View file

@ -0,0 +1,52 @@
<?php
declare(strict_types=1);
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Http\JsonResponse;
/**
* Admin Authorization Middleware
*
* Example middleware showing how to implement role-based authorization
* using Illuminate HTTP components
*/
class AdminMiddleware
{
/**
* Handle an incoming request
*
* @param Request $request
* @param Closure $next
* @return Response|JsonResponse
*/
public function handle(Request $request, Closure $next): Response|JsonResponse
{
// Check if user is authenticated first
$userId = $request->attributes->get('authenticated_user_id');
if (!$userId) {
if ($request->expectsJson()) {
return new JsonResponse(['error' => 'Authentication required'], 401);
}
return new Response('Authentication required', 401);
}
// TODO: Implement actual admin role check
// For now, accept user ID 1 as admin
if ($userId !== 1) {
if ($request->expectsJson()) {
return new JsonResponse(['error' => 'Admin access required'], 403);
}
return new Response('Admin access required', 403);
}
return $next($request);
}
}

View file

@ -0,0 +1,55 @@
<?php
declare(strict_types=1);
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Http\JsonResponse;
/**
* Authentication Middleware
*
* Example middleware showing how to implement authentication
* using Illuminate HTTP components
*/
class AuthMiddleware
{
/**
* Handle an incoming request
*
* @param Request $request
* @param Closure $next
* @return Response|JsonResponse
*/
public function handle(Request $request, Closure $next): Response|JsonResponse
{
// Example authentication check
$token = $request->bearerToken() ?? $request->input('api_token');
if (!$token) {
if ($request->expectsJson()) {
return new JsonResponse(['error' => 'Authentication required'], 401);
}
return new Response('Authentication required', 401);
}
// TODO: Implement actual token validation
// For now, accept any token that starts with 'valid_'
if (!str_starts_with($token, 'valid_')) {
if ($request->expectsJson()) {
return new JsonResponse(['error' => 'Invalid token'], 401);
}
return new Response('Invalid token', 401);
}
// Add user info to request for use in controllers
$request->attributes->set('authenticated_user_id', 1);
return $next($request);
}
}

View file

@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
abstract class BaseMiddleware
{
/**
* Handle an incoming request.
*/
public function handle(Request $request, Closure $next): Response
{
$request = $this->before($request);
$response = $next($request);
return $this->after($request, $response);
}
/**
* Process request before passing to next middleware
*/
protected function before(Request $request): Request
{
return $request;
}
/**
* Process response after middleware chain
*/
protected function after(Request $request, Response $response): Response
{
return $response;
}
}

View file

@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class CorsMiddleware
{
private array $allowedOrigins;
private array $allowedHeaders;
private array $allowedMethods;
public function __construct(
array $allowedOrigins = ['*'],
array $allowedHeaders = ['Content-Type', 'Authorization', 'X-Requested-With'],
array $allowedMethods = ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']
)
{
$this->allowedOrigins = $allowedOrigins;
$this->allowedHeaders = $allowedHeaders;
$this->allowedMethods = $allowedMethods;
}
public function handle(Request $request, Closure $next): Response
{
if ($request->getMethod() === 'OPTIONS') {
return $this->createPreflightResponse($request);
}
$response = $next($request);
return $this->addCorsHeaders($response, $request);
}
private function createPreflightResponse(Request $request): Response
{
$response = new Response('', 200);
return $this->addCorsHeaders($response, $request);
}
private function addCorsHeaders(Response $response, Request $request): Response
{
$origin = $request->headers->get('Origin', '');
if (in_array('*', $this->allowedOrigins) || in_array($origin, $this->allowedOrigins)) {
$response->headers->set('Access-Control-Allow-Origin', $origin ?: '*');
}
$response->headers->set('Access-Control-Allow-Methods', implode(', ', $this->allowedMethods));
$response->headers->set('Access-Control-Allow-Headers', implode(', ', $this->allowedHeaders));
$response->headers->set('Access-Control-Max-Age', '86400');
return $response;
}
}