I'm trying to display 404 page based upon user login, for which I'm trying to get the logged in user id from sessions.
But session session()->all() always returns empty array and also auth()->id(); & Auth::id(); are also empty value.
That's because in app/Http/Kernel.php the protected $middleware array doesn't have the middleware for the session.
What you can do is to move the \Illuminate\Session\Middleware\StartSession::class, middleware from the web middlware group to the global $middleware array.
Related
I am trying to use the current route in middleware in Laravel 5.7 using the following line of code:
$route = Route::current();
But I get a null value for $route. Any ideas?
The route couldn't be available yet because the router hasn't been yet called. That's depends on what middlewares are called before your middleware.
I think that, in a before middleware, you can try with: $route = $request->path(); just to be sure and not depending on the Router being booted or not.
You just want to change where your middleware is registered in app/Http/Kernel.php if you need access to the Route facade.
I'm betting that your middleware is in the protected $middleware array. It should be in one of your $middlewareGroups usually web or api. Or if you need it for a specific route you can add it to the $routeMiddleware array.
For example, I wanted to access Route from within my HandleInertiaRequests middleware so I had to move to $middlewareGroups like shown in this screenshot:
I am using this package for maintenance but to define what user can have access to the site during down time and what user can't I have issue.
during passed few days I was searching and I read a lot, that because main controller loads after middleware it can't detect user status whether is login or not. (I have no idea on that I just saw that repeatedly)
Anyway here is the issue:
I want allow users with role of Admin access to the site in down time, And visitors, other group of users don't.
What I did so far
based on package documentation I've made custome file in App\Exemptions\AdminExemption.php with this data:
<?php
namespace App\Exemptions;
use Auth; use Config; use App\User; use MisterPhilip\MaintenanceMode\Exemptions\MaintenanceModeExemption;
class AdminExemption extends MaintenanceModeExemption {
public function isExempt()
{
if (Auth::check() && Auth::user()->role == 'Admin') {
return true;
}
else {
return false;
}
//if user is logged and it's admin show the site
//if user is logged and isn't admin hide the site
//if user isn't logged (is visitor) hide the site
} }
I register this file in package config file config\maintenancemode.php
'exemptions' => [
App\Exemptions\AdminExemption::class,
],
and replaced package class with laravel default in Kernel
protected $middleware = [
// \App\Http\Middleware\CheckForMaintenanceMode::class,
\MisterPhilip\MaintenanceMode\Http\Middleware\CheckForMaintenanceMode::class,
//others...
]
Issue
Auth::check() or auth()->user() or Auth::user() none of this can detect logged user and assume the user is not login (is visitor). So the website is shut for everyone even admins.
Question
How can I get the real status of my current user in AdminExemption.php file?
Status
Is user (is admin) show the site
Is user (isn't admin) don't show the site
Is not user (visitor) don't show the site
Any idea?
You've registered the middleware in the main middleware stack, which will occur before it gets to the middleware groups. You'll likely want to move the middleware lower down in the Kernel into the web middleware stack. This is because Laravel will only be aware of a logged in user if there is a session - and the session is only started in the web stack.
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,
],
];
You'll need to place the middleware after the StartSession middleware - but you're probably best just to pop it on to the end there, and then the logged in status should be available in your middleware.
I have a React SPA in the same Laravel project. The login/signup/logout and all other js views are in the js folder and use axios api calls for all POST/GET requests. I want to use the default Laravel session based web authentication for the embedded SPA, since it's in the same project folder and it will be the only javascript client accessing it. This api does not need to be open to the public, just for this react app, and it's an SPA for the speed and good user experience instead of full page reloads.
I've tried using Passport before, and for over a month, I still can't get it to work as intended. I do not want to deal with tokens, access tokens, refresh tokens, revoking tokens, CSRF, etc. Just the out of the box simple Laravel session based auth that works so easily on web, but want it to work on my react app. The only blade file is the index.blade.php which includes the react app.js
Any idea how we can accomplish this?
UPDATE 1:
After implementing #ceejayoz's suggestion:
You have to add the various Session/Cookie middlewares in
app/Http/Kernel.php (stuff like
\Illuminate\Session\Middleware\StartSession::class) to the API routes.
I added to $middlewareGroups.api to match the web middleware in app/Http/Kernel.php:
'api' => [
'throttle:60,1',
'bindings',
// Newly added middleware to match web middleware
\App\Http\Middleware\EncryptCookies::class
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
I realized there are two issues that occurred:
In the sessions table, even if not logged in, when loading app home page (or any page), multiple sessions are inserted into the sessions table. Shouldn't a new single session be inserted into this table only after user login?
After user log in, when refreshing the page manually in the browser and a call is made to a protected route, I get a 401 Unauthenticated which points me to this method in Illuminate/Auth/GuardHelpers.php:
public function authenticate() {
if (! is_null($user = $this->user())) {
return $user;
}
throw new AuthenticationException; // throws this 401 exception on logged in page refresh when fetching data from private route
}
Some additional notes:
In config/auth.php I updated the guards.api.driver to session instead of token.
In routes/api.php I have the protected routes wrapped in auth middleware like this: Route::group(['middleware' => 'auth'], function() { PRIVATE ROUTES HERE }
In config/session.php I have 'domain' => '.mydomain.com'
I am sending back these headers with each axios api request like this:
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
let token = document.head.querySelector('meta[name="csrf-token"]');
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
Any idea how we can fix these 2 issues?
Looks like your session was not persistent.
Check if you changed any values in config/session.php that might create problems.
You can check default sesion config values here
From the comments, #Wonka solved his problem by changing
'same_site' => 'strict'
to
'same_site' => null
It's doable (and I've done the same myself for some apps).
By default, the routes in routes/api.php don't have sessions available, but you can add the various Session/Cookie middlewares in app/Http/Kernel.php (stuff like \Illuminate\Session\Middleware\StartSession::class) to the API routes.
You can, as #ljubadr suggested, also put the API routes right in routes/web.php instead, although that'd probably mean you'd need to make other changes (like removing CSRF protection from the web routes).
I am trying to create a custom error page in Laravel 5.3. I wanted the retrieve some variable stored in the Session like Session::get("username"), however what I get is an empty variable.
How am I suppose to get any Session variable in a custom error page in Laravel or is it not possible?
As Laravel did not find the route, you did not pass through the middleware \Illuminate\Session\Middleware\StartSession (which is by default in web middleware group), so your session is not started.
To have your session initialized, move \Illuminate\Session\Middleware\StartSession::class, from web to $middleware in Kernel.php:
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Session\Middleware\StartSession::class,
],
Middlewares in $midleware are always run so your session will be initialized, even if the route is not found.
I'm trying to access the Auth class from within the render method of the App\Exceptions\Handler class (app/Exceptions/Handler.php) to determine if the User is currently logged in, using the Auth::check() method.
This worked fine in 5.1, but I've upgraded to 5.2 and it no longer works.
To debug this, I've been printing Auth::user() to the logs (which returns NULL), then returning a redirect() to another view.
Then from the view/controller the redirect goes to, printing the same Auth::user() to the logs, which works as expected and returns the logged in user.
So it seems there's no problem accessing the Auth class or the user() method from within the Exceptions\Handler class, it's just that it returns NULL for some reason, whereas other parts of the app return the User..
Thanks for any info on this!
This happens because StartSession middleware is inside $middlewareGroups (the application's route middleware groups), so you don't have access to the authenticated user because the middlewares that initialize your session starts later in the lifecycle than the ExceptionHandler.
In app\Kernel.php file, move this line:
\Illuminate\Session\Middleware\StartSession::class,
from $middlewareGroups to the global stack $middleware. These middleware are run during every request to your application so, after this, Auth::user() will works.
WARNING: With this solution you will not be able to use the cookie session driver. Works well with file and others.
UPDATE:
If you still need to use StartSession inside global stack $middleware and also you need cookie session driver, you must move three middlewares from $middlewareGroup to $middleware in the next order:
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class
After some research, it seems the 404 errors are the only culprits. If it's a 500 error, Auth::user() works. So, in my routes.php file, I added this at the bottom
Route::any('{page}', 'ErrorController#Error404')->where('page', '(.*)');
to catch any unhandled endpoints. In that ErrorController#Error404 method, I can access the Auth class. So whatever logic you have in your App\Exceptions\Handler, you can duplicate it in the ErrorController#Error404 method. (Or better: extract it to some other entity that can be referenced in both places.)