withRouting( using: function () { Route::middleware('web') ->group(base_path('routes/web-admin.php')); Route::middleware('web') ->group(base_path('routes/web-portfolio.php')); Route::middleware('web') ->group(base_path('routes/web-api.php')); Route::middleware('web') ->group(base_path('routes/web.php')); Route::middleware('api') ->group(base_path('routes/api.php')); }, channels: __DIR__.'/../routes/channels.php', commands: __DIR__.'/../routes/console.php', ) ->withMiddleware(function (Middleware $middleware) { $middleware->use([ HandleCors::class, PreventRequestsDuringMaintenance::class, ValidatePostSize::class, TrustProxies::class, TrimStrings::class, ConvertEmptyStringsToNull::class, ]); $middleware->group('web', [ EncryptCookies::class, FrameGuard::class, AddQueuedCookiesToResponse::class, StartSession::class, AuthenticateSession::class, ShareErrorsFromSession::class, PreventRequestForgery::class, SubstituteBindings::class, CreateFreshApiToken::class, 'restricted', ]); $middleware->group('oauth-web', [ EncryptCookies::class, FrameGuard::class, AddQueuedCookiesToResponse::class, StartSession::class, ShareErrorsFromSession::class, PreventRequestForgery::class, SubstituteBindings::class, CreateFreshApiToken::class, ]); $middleware->group('api', [ EnsureFrontendRequestsAreStateful::class, 'throttle:api', 'bindings', GrantFirstPartyToken::class, ]); $middleware->preventRequestForgery(except: [ 'oauth/token', ]); $middleware->alias([ 'api.admin' => ApiAdmin::class, 'admin' => Admin::class, 'auth' => Authenticate::class, 'auth.basic' => AuthenticateWithBasicAuth::class, 'bindings' => SubstituteBindings::class, 'cache.headers' => SetCacheHeaders::class, 'can' => Authorize::class, 'dangerzone' => RequirePassword::class, 'localization' => Localization::class, 'guest' => RedirectIfAuthenticated::class, 'signed' => ValidateSignature::class, 'throttle' => ThrottleRequests::class, 'interstitial' => AccountInterstitial::class, 'scopes' => CheckToken::class, 'scope' => CheckTokenForAnyScope::class, 'restricted' => RestrictedAccess::class, ]); }) ->withSchedule(function (Schedule $schedule) { require __DIR__.'/scheduledtasks.php'; }) ->withExceptions(function (Exceptions $exceptions) { $exceptions->shouldRenderJsonWhen( fn (Request $request) => $request->is('api/*') || $request->expectsJson(), ); $exceptions->dontReport([ OAuthServerException::class, ConnectionException::class, ]); $exceptions->dontFlash([ 'password', 'password_confirmation', ]); $exceptions->reportable(function (BadMethodCallException $e) { return app()->environment() !== 'production'; }); $exceptions->reportable(function (ConnectionException $e) { return app()->environment() !== 'production'; }); // A login-flow form submitted from a tab whose CSRF token is stale // (the session was regenerated by a login or a pending step elsewhere) // lands on wherever the session actually is instead of a 419. // // The handler rewrites TokenMismatchException into an HttpException(419) // (keeping the original as the previous exception) in prepareException() // before render callbacks run, so this must key on the rewritten type // and identify the CSRF case via status code + previous exception. // Returning null for anything else lets the JSON Throwable callback below // continue to handle XHR/JSON login requests as a 419. $exceptions->render(function (HttpException $e, Request $request) { if ($e->getStatusCode() !== 419 || ! $e->getPrevious() instanceof TokenMismatchException) { return null; } if ($request->wantsJson() || ! $request->is('login', 'login/*')) { return null; } if (Auth::check()) { return redirect('/i/web'); } if ($step = PendingLoginService::step($request)) { return redirect()->route('login', ['step' => $step]); } return redirect()->route('login')->withErrors([ 'login' => __('Your sign-in session expired. Please sign in again.'), ]); }); $exceptions->render(function (Throwable $e, $request) { if ($request->wantsJson()) { if ($e instanceof HttpResponseException) { return $e->getResponse(); } if ($e instanceof AuthenticationException) { return response()->json( ['error' => $e->getMessage()], 401, ); } if ($e instanceof ValidationException) { return response()->json([ 'message' => $e->getMessage(), 'errors' => $e->validator->getMessageBag(), ], $e->status); } $isHttp = $e instanceof HttpExceptionInterface; return response()->json( ['error' => $e->getMessage()], $isHttp ? $e->getStatusCode() : 500, $isHttp ? $e->getHeaders() : [], ); } }); }) ->create();