Auth::user() is null in new route - laravel

i'm using laravel 6 and have 2 route in my app; index and dashboard.
My routes/web is:
Auth::routes();
Route::middleware(['auth'])->group(function () {
Route::get('/index', 'todoApp\TodoController#index')->name('index');
Route::get('/dashboard', 'todoApp\Dashboard#dashboard')->name('dashboard');
});
i added dashboard route recently.
Auth::user() is null when i dump it in dashboard route but doesn't in index. What's the

Your Controller is instantiated before the middleware stack has ran; this is how Laravel can know what middleware you have set via the constructor. Because of this you will not have access to the authenticated user or sessions at this point. Ex:
public function __construct()
{
$this->user = Auth::user(); // will always be null
}
If you need to assign such a variable or access this type of information you would need to use a controller middleware which will run in the stack after the StartSession middleware:
public function __construct()
{
$this->middleware(function ($request, $next) {
// this is getting executed later after the other middleware has ran
$this->user = Auth::user();
return $next($request);
});
}
When the dashboard method is called, the middleware stack has already passed the Request all the way through to the end of the stack so all the middleware needed for Auth to be functioning and available has already ran at that point which is why you have access to Auth::user() there.

I think that this has something to do with the 'web' middleware. If you take a look into the Kernel.php (In app\Http) you will find the web middleware group.
This will show you that it actually calls a middleware called StartSession. Based on your route file (where web is not included as a middleware) I would think that you don't have a session in your Controller and there for no access to it.
I don't quite understand why this only happens in your /dashboard route, because the issue should also be in your /index route (unless you added the web middleware somewhere in your TodoController).
I think that this should do the trick:
Route::middleware(['web', 'auth'])->group(function () {
Route::get('/index', 'todoApp\TodoController#index')->name('index');
Route::get('/dashboard', 'todoApp\Dashboard#dashboard')->name('dashboard');
});

If you fire php artisan make:auth command.
It's doesn't matter where you define because of it's only define auth route
Route::middleware(['auth'])->group(function () {
Route::get('/index', 'todoApp\TodoController#index')->name('index');
Route::get('/dashboard', 'todoApp\Dashboard#dashboard')->name('dashboard');
});
Auth::routes();

Related

Auth::check fails in middleware

Can somebody explain why this strange behavior of Laravel is happening? Basically, I am trying to create a middleware for my application
public function handle(Request $request, Closure $next)
{
if (auth()->check()) {
$expires = Carbon::now()->addMinute(2);
\Illuminate\Support\Facades\Cache::put('user-is-online-' . Auth::user()->id, true, $expires);
}
return $next($request);
}
}
But auth()->check it is keep failing and not returning true , (user is authenticated) , auth()->check is working in other places like web routes and controllers method but why not here ?
If you are using auth middleware to protect your routes, then make sure this auth middleware is set to run before your middleware, otherwise auth()->check() will return false. Try php artisan route:list and check the orders of middlewares for your specified route.

Laravel auth middleware returns route not defined

I'm new to laravel and I'm trying to secure some routes wherein only authenticated users can access it.
I've followed instructions on grouping my web routes on an auth middle ware, so I did my routes/web.php it like this...
Route::group(['middleware' => 'auth'], function () {
Route::get('/feed', [FeedController::class, 'feed']);
Route::get('/profile', [ProfileController::class, 'profile']);
});
Route::get('/', [LandingController::class, 'landing']);
and my App/Http/Middleware/Authenticate.php like this....
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('/');
}
}
but when I access these guarded routes unauthenticated, it gives me error saying
Symfony\Component\Routing\Exception\RouteNotFoundException
Route [/] not defined.
Can someone point me on the right way here?

Laravel Routing Order Multiple "Homepages" Based On Auth

I have a Laravel routing file (web.php) like so:
Route::group(['middleware' => ['auth']], function () {
Route::get('/', function () {
return 'Hello World';
});
});
Route::get('/', 'Auth\LoginController#showLoginForm')->name('login');
In my application the unauthenticated homepage must go to the login screen. When authenticated, the homepage changes. However, if I run this code and login - I get an infinite redirect because the LoginController has this line:
protected $redirectTo = '/';
So basically, even thought Laravel should read the routes file top to bottom, it seems this isn't applying in my case (maybe because of the ::group()) or I am doing something wrong.
How can I accomplish a homepage that goes to the login form while also redirecting back to the same url (/) for authenticated users for a different authenticated view (and no redirect loop).
Thanks!
I would handle this inside a guest middleware that checks for an authenticated user. For this case you'll want an authenticated guard check first:
use Illuminate\Contracts\Auth\Guard;
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
public function handle($request, Closure $next)
{
if ($this->auth->check()) {
return redirect('/home');
}
return $next($request);
}
Apply the guest middleware to the login endpoint:
Route::get('/', 'Auth\LoginController#showLoginForm')
->middleware('guest')
->name('login');
Note: Only apply the guest middleware to guest routes, otherwise you run the risk of redirect loops.
Why not handle this in your view?
You can simply remove one of the route declaration from your web.php.
Then go ahead with conditional rendering.
#auth
Show Home page
#endauth
#guest
Show Login
#endguest
I guess middleware does not prevent request from hitting the routes,
It rather prevents request from going through.
You can't use middleenter code hereware to decide with route to hit, thereby the loop.
When you're thinking in terms of bottom down processing, laravel has already registered every declared routes.

Apply Auth Middleware to All Laravel Routes

What is the correct way to authenticate all routes except login and register when I apply auth middleware in all controllers? Is there a way to apply auth middleware in one place and exclude login, register routes?
You can group all your authenticated routes like following, laravel provides a default middleware for auth and guest users
Route::group(['middleware' => ['auth']], function () {
Route::get('home', 'HomeController#index');
Route::post('save-user', 'UserController#saveUser');
Route::put('edit-user', 'UserController#editUser');
});
The above route names are just made up, please follow a proper naming convention for your routes and controllers. Also read about middlewares over here and about routing over here
you can apply middlewares in the routes.php file, what you need to do is to put all your routes on a group, and add the middleware 'auth' ( except the Auth::routes() which are already configured), for example :
Route::middleware(['first', 'second'])->group(function () {
Route::get('/', function () {
// Uses first & second Middleware
});
Route::get('user/profile', function () {
// Uses first & second Middleware
});
});
more information can be found in the docs: https://laravel.com/docs/5.7/routing#route-group-middleware
You can add middleware to your whole web.php route file by adding the middleware to your routes mapping in RouteServiceProvider.
Go to app/Providers/RouteServiceProvider.php and in mapWebRoutes(), change middleware('web') to middleware(['web', 'auth']):
protected function mapWebRoutes()
{
Route::middleware(['web', 'auth'])
->namespace($this->namespace)
->group(base_path('routes/web.php'));
}
This is (not?) totally unrelated but here's an example of a clean way to handle a lot of route files instead of throwing all your routes into a single web.php file:
Create a new method mapAdminRoutes():
protected function mapAdminRoutes()
{
Route::middleware(['web', 'auth:admin'])
->namespace('App\Http\Controllers\Admin')
->name('admin.')
->group(base_path('routes/admin.php'));
}
Map it:
public function map()
{
$this->mapWebRoutes();
$this->mapAdminRoutes(); // <-- add this
...
}
Create an admin.php file in your routes folder, then create your routes for Admin:
<?php
use Illuminate\Support\Facades\Route;
// This route's name will be 'admin.dashboard'
Route::get('dashboard', 'DashboardController#dashboard')->name('dashboard');
// This route's name will be 'admin.example'
Route::get('example', 'ExampleController#example')->name('example');
...
Now you can configure everything in 1 place, like prefix, name, middleware and namespace.
Check php artisan route:list to see the results :)

Listing middleware in kernel.php

I have an admin middlware AdminMiddleware.php
public function handle($request, Closure $next, $guard = null)
{
if(Auth::check())
{
if($request->user()->is_admin==1)
{
return $next($request);
}
return redirect('/login');
}
else
{
return redirect('/login');
}
}
And i have some routes under adminmiddleware:
Route::group(['middleware' => ['App\Http\Middleware\Adminmiddleware']], function () {
//admin routes
});
Working properly. And i'm litte confused on Registering middleware? Why should i register. Only for alias or something more effective?
For $routeMiddleware and $middlewareGroups, they are mostly for aliasing. As you mentioned, you can don't register it and use it just fine in your route file.
It's more on conveniency for your to swap the implementation shall you need to.
IMO, register it so that you can swap the middleware implementation at any point of time without going into your route configuration file to change it - which is more error prone than one central location to change.
Registering middleware is loading the class with each request automatically. You're telling Laravel to load and register it, so you could use it in routes and controllers without initializing it manually. Same with console commands, service providers etc. You must register before using them.
If you want a middleware to run during every HTTP request to your application, simply list the middleware class in the $middleware property of your app/Http/Kernel.php class.

Resources