I'm creating a Laravel site for a small business. There's a public front-end and a 'admin panel' for managing data, customer information and a blog.
I have created a 'Public Controller' for managing requests made on the public routes (home page, privacy policy, gallery, etc.) which does not implement the Auth middleware, and I have separate controllers for things like the blog and dashboard which do implement the Auth middleware and do usual CRUD.
There are two layouts - one 'admin' and one 'user', the difference being the way the navbar is displayed and the wrapping elements around the content @yield. Both layouts @include a 'head' layout which has the tags, including the CSRF token.
My problem is that whenever I go to pages that aren't '/login', '/admin' or '/dashboard' (Dashboard is accessible once Authenticated), I get an error in console about the CSRF token.
The CSRF token is visible in the HTML on all of the pages, Auth and non-Auth, but it's only on '/login' (And the other default Auth pages provided by make:auth) and '/dashboard' that the system doesn't throw a fit about it.
I've tried:
- Re-writing the tag to make sure there's no typos
- Someone's suggestion to change app.js line of
let token = document.head.querySelector('meta[name="csrf-token"]');
to
let token = $('meta[name="csrf-token"]').attr('content');
- I've tried php artisan config:clear and composer dump-autoload
- I've tried adding the Auth middleware to PublicController.php
web.php
Route::get('/admin', function () {
if ( Auth::user() ) {
return redirect('dashboard');
} else {
return view('auth.login');
}
});
Auth::routes();
Route::get('/', 'PublicController@index')->name('home');
Route::get('/dashboard', 'DashController@index')->name('dashboard.index');
user.blade.php (The 'public' layout for non auth routes) AND admin.blade.php (The 'private' layout for auth routes[internal]):
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
@include('layouts.head')
<body>
<div id="app">
...
head.blade.php:
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>@yield('title')</title>
<script src="{{ asset('js/app.js') }}" ></script>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js">/script>
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
@yield('css')
publicController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PublicController extends Controller
{
/**
* Show the home page
*
* @return \Illuminate\Contracts\Support\Renderable
*/
public function index()
{
return view('home');
}
}
DashController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class DashController extends Controller
{
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* @return \Illuminate\Contracts\Support\Renderable
*/
public function index()
{
return view('dashboard.index');
}
}
I'm probably overlooking something obvious but I'm really not sure where to go now since I've tried every answer on google now despite there being a clear correlation between the pages you don't need to be auth'ed playing up with CSRF and those that check if you're an Auth user being fine, even though both include the same 'head' layout which has CSRF in it.
EDIT
The Kernel.php by request
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array
*/
protected $middleware = [
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**
* The application's route middleware groups.
*
* @var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array
*/
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
/**
* The priority-sorted list of middleware.
*
* This forces non-global middleware to always be in the given order.
*
* @var array
*/
protected $middlewarePriority = [
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\Authenticate::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
];
}