diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 81c5076..531394b 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -14,8 +14,9 @@ class Kernel extends HttpKernel * @var array */ protected $middleware = [ + \App\Http\Middleware\TrustHosts::class, \App\Http\Middleware\TrustProxies::class, - \App\Http\Middleware\CheckForMaintenanceMode::class, + \App\Http\Middleware\PreventRequestsDuringMaintenance::class, \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \App\Http\Middleware\TrimStrings::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php index 17a84dc..e473b04 100644 --- a/app/Http/Middleware/Authenticate.php +++ b/app/Http/Middleware/Authenticate.php @@ -3,6 +3,7 @@ namespace App\Http\Middleware; use Illuminate\Auth\Middleware\Authenticate as Middleware; +use Illuminate\Support\Facades\Session; class Authenticate extends Middleware { @@ -10,12 +11,28 @@ class Authenticate extends Middleware * Get the path the user should be redirected to when they are not authenticated. * * @param \Illuminate\Http\Request $request - * @return string + * @return string|null + * @phpcs:disable Squiz.Commenting.FunctionComment.TypeHintMissing */ protected function redirectTo($request) { - if (! $request->expectsJson()) { - return route('login'); + $logins = [ + 'backend' => route('bo.login') + ]; + if (!$request->expectsJson()) { + // * Notify must login + Session::flash('warning', trans('Veuillez vous connecter pour continuer')); + + foreach ($request->route()->gatherMiddleware() as $middleware) { + if (\is_string($middleware) and strpos($middleware, 'auth:') !== false) { + $route = $logins[str_replace('auth:', '', $middleware)] ?? null; + if ($route) { + return $route; + } + } + } + return route('bo.login'); } + abort(401); } } diff --git a/app/Http/Middleware/CheckForMaintenanceMode.php b/app/Http/Middleware/CheckForMaintenanceMode.php deleted file mode 100644 index 9037ddf..0000000 --- a/app/Http/Middleware/CheckForMaintenanceMode.php +++ /dev/null @@ -1,16 +0,0 @@ - */ - protected $except = [ - ]; + protected $except = []; } diff --git a/app/Http/Middleware/PreventRequestsDuringMaintenance.php b/app/Http/Middleware/PreventRequestsDuringMaintenance.php new file mode 100644 index 0000000..842e4b9 --- /dev/null +++ b/app/Http/Middleware/PreventRequestsDuringMaintenance.php @@ -0,0 +1,15 @@ + + */ + protected $except = []; +} diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php index 6e2a96b..6713099 100644 --- a/app/Http/Middleware/RedirectIfAuthenticated.php +++ b/app/Http/Middleware/RedirectIfAuthenticated.php @@ -3,6 +3,7 @@ namespace App\Http\Middleware; use Closure; +use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class RedirectIfAuthenticated @@ -10,15 +11,22 @@ class RedirectIfAuthenticated /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request - * @param \Closure $next - * @param string|null $guard - * @return mixed + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * @param string|null ...$guards + * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse */ - public function handle($request, Closure $next, $guard = null) + public function handle(Request $request, Closure $next, ...$guards) { - if (Auth::guard($guard)->check()) { - return redirect('/home'); + $logins = [ + 'web' => route('bo.eleveurs.index') + ]; + $guards = empty($guards) ? [null] : $guards; + + foreach ($guards as $guard) { + if (Auth::guard($guard)->check()) { + return \redirect()->to($logins[$guard]); + } } return $next($request); diff --git a/app/Http/Middleware/TrimStrings.php b/app/Http/Middleware/TrimStrings.php index 5a50e7b..88cadca 100644 --- a/app/Http/Middleware/TrimStrings.php +++ b/app/Http/Middleware/TrimStrings.php @@ -9,9 +9,10 @@ class TrimStrings extends Middleware /** * The names of the attributes that should not be trimmed. * - * @var array + * @var array */ protected $except = [ + 'current_password', 'password', 'password_confirmation', ]; diff --git a/app/Http/Middleware/TrustHosts.php b/app/Http/Middleware/TrustHosts.php new file mode 100644 index 0000000..7186414 --- /dev/null +++ b/app/Http/Middleware/TrustHosts.php @@ -0,0 +1,20 @@ + + */ + public function hosts() + { + return [ + $this->allSubdomainsOfApplicationUrl(), + ]; + } +} diff --git a/app/Http/Middleware/TrustProxies.php b/app/Http/Middleware/TrustProxies.php index b7f30ff..78de7a0 100644 --- a/app/Http/Middleware/TrustProxies.php +++ b/app/Http/Middleware/TrustProxies.php @@ -2,7 +2,7 @@ namespace App\Http\Middleware; -use Fideloper\Proxy\TrustProxies as Middleware; +use Illuminate\Http\Middleware\TrustProxies as Middleware; use Illuminate\Http\Request; class TrustProxies extends Middleware @@ -10,14 +10,19 @@ class TrustProxies extends Middleware /** * The trusted proxies for this application. * - * @var array|string + * @var array|string|null */ - protected $proxies = "*"; + protected $proxies; /** * The headers that should be used to detect proxies. * * @var integer */ - protected $headers = Request::HEADER_X_FORWARDED_ALL; + protected $headers = + Request::HEADER_X_FORWARDED_FOR | + Request::HEADER_X_FORWARDED_HOST | + Request::HEADER_X_FORWARDED_PORT | + Request::HEADER_X_FORWARDED_PROTO | + Request::HEADER_X_FORWARDED_AWS_ELB; } diff --git a/app/Http/Middleware/VerifyCsrfToken.php b/app/Http/Middleware/VerifyCsrfToken.php index 6990b6d..70e23e1 100644 --- a/app/Http/Middleware/VerifyCsrfToken.php +++ b/app/Http/Middleware/VerifyCsrfToken.php @@ -6,18 +6,10 @@ use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware; class VerifyCsrfToken extends Middleware { - /** - * Indicates whether the XSRF-TOKEN cookie should be set on the response. - * - * @var boolean - */ - protected $addHttpCookie = true; - /** * The URIs that should be excluded from CSRF verification. * - * @var array + * @var array */ - protected $except = [ - ]; + protected $except = []; } diff --git a/app/Http/Middleware/XssSanitizer.php b/app/Http/Middleware/XssSanitizer.php index 955d285..2dce94e 100644 --- a/app/Http/Middleware/XssSanitizer.php +++ b/app/Http/Middleware/XssSanitizer.php @@ -38,6 +38,7 @@ class XssSanitizer } } else { $input = strip_tags($input); + $input = \filter_var($input, FILTER_SANITIZE_STRING); } }); $request->merge($inputs); diff --git a/app/Lib/ToolboxHelper.php b/app/Lib/ToolboxHelper.php index 644c52b..71276b1 100644 --- a/app/Lib/ToolboxHelper.php +++ b/app/Lib/ToolboxHelper.php @@ -176,4 +176,42 @@ abstract class ToolboxHelper ); return $text; } + + /** + * * Register CSP report URI + * + * Put this function inside RouteServiceProvider, + * and call it in RouteServiceProvider::boot + * + * ! Use this in conjonction with kwaadpepper/exception-handler + * + * @return void + */ + public static function cspReportRoute() + { + // * CSP REPORT URI, Please add /csp-report to VerifyCsrfToken $except middleware + \Illuminate\Support\Facades\Route::post('/csp-report', function () { + $isCspRequest = request()->header('Content-Type') === 'application/csp-report'; + if (!$isCspRequest or !request()->json('csp-report') or !is_array(request()->json('csp-report'))) { + abort(401); + } + // * Flatten if needed + $cspReport = collect(request()->json('csp-report')) + ->flatMap(function ($v, $k) { + return [$k => is_array($v) ? collect($v)->flatten()->implode(', ') : $v]; + })->all(); + // * Filter array keys + $cspReport = collect(array_intersect_key($cspReport, [ + 'blocked-uri' => '', 'document-uri' => '', 'original-policy' => '', + 'referrer' => '', 'violated-directive' => '' + ])); + report(new \Illuminate\Http\Client\HttpClientException(sprintf( + "CSP REPORT for %s : \n %s", + $cspReport->get('document-uri'), + $cspReport->implode("\n") + ))); + })->middleware('throttle:5,2') + ->withoutMiddleware(\App\Http\Middleware\VerifyCsrfToken::class) + ->name('cspReportUri'); + } } diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 7a6bcf1..348d111 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -2,9 +2,13 @@ namespace App\Providers; +use App\Lib\ToolboxHelper; use App\Models\CafelEggBreeder; use App\Models\CafelPoultryBreeder; +use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\RateLimiter; use Illuminate\Support\Facades\Route; class RouteServiceProvider extends ServiceProvider @@ -25,6 +29,20 @@ class RouteServiceProvider extends ServiceProvider */ public function boot() { + $this->configureRateLimiting(); + + $this->routes(function () { + Route::middleware('web') + ->namespace($this->namespace) + ->group(base_path('routes/web-bo.php')); + + Route::middleware('web') + ->namespace($this->namespace) + ->group(base_path('routes/web-fo.php')); + }); + + ToolboxHelper::cspReportRoute(); + Route::bind('breeder', function ($value) { /** @var \App\Models\CafelEggBreeder|null */ if (!($breeder = CafelEggBreeder::whereCafelCode($value)->first())) { @@ -33,50 +51,19 @@ class RouteServiceProvider extends ServiceProvider } return $breeder; }); + parent::boot(); } /** - * Define the routes for the application. + * Configure the rate limiters for the application. * * @return void */ - public function map() + protected function configureRateLimiting() { - $this->mapApiRoutes(); - - $this->mapWebRoutes(); - } - - /** - * Define the "web" routes for the application. - * - * These routes all receive session state, CSRF protection, etc. - * - * @return void - */ - protected function mapWebRoutes() - { - Route::middleware('web') - ->namespace($this->namespace) - ->group(base_path('routes/web.php')); - Route::middleware('web') - ->namespace($this->namespace) - ->group(base_path('routes/web-bo.php')); - } - - /** - * Define the "api" routes for the application. - * - * These routes are typically stateless. - * - * @return void - */ - protected function mapApiRoutes() - { - Route::prefix('api') - ->middleware('api') - ->namespace($this->namespace) - ->group(base_path('routes/api.php')); + RateLimiter::for('web', function (Request $request) { + return Limit::perMinute(150)->by(optional($request->user())->id ?: app('clientIp')); + }); } } diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index e11f70e..2730f44 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -8,7 +8,7 @@
{{ __('Connexion') }}
-
+ @csrf
diff --git a/resources/views/back/layout/header.blade.php b/resources/views/back/layout/header.blade.php index ef4616e..f4292da 100644 --- a/resources/views/back/layout/header.blade.php +++ b/resources/views/back/layout/header.blade.php @@ -18,7 +18,7 @@ @guest @if (Route::has('register'))
diff --git a/routes/web-bo.php b/routes/web-bo.php index 9df4975..073fc03 100644 --- a/routes/web-bo.php +++ b/routes/web-bo.php @@ -4,14 +4,15 @@ use App\Http\Controllers\Bo\BreederController; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Route; -Auth::routes([ - 'verify' => false, - 'register' => false, - 'reset' => false -]); - -Route::prefix('bo')->name('bo.')->middleware('auth')->group(function () { - Route::resource('eleveurs', BreederController::class)->only(['index', 'show']) +Route::prefix('bo')->name('bo.')->group(function () { + Auth::routes([ + 'verify' => false, + 'register' => false, + 'reset' => false + ]); + Route::middleware('auth')->group(function () { + Route::resource('eleveurs', BreederController::class)->only(['index', 'show']) ->parameter('eleveurs', 'breeder'); - Route::redirect('/', '/bo/eleveurs'); + Route::redirect('/', '/bo/eleveurs'); + }); }); diff --git a/routes/web.php b/routes/web-fo.php similarity index 100% rename from routes/web.php rename to routes/web-fo.php