Unintuitive nature of Laravel’s viaRemember()
A very particular problem on my hands — make sure we are not allowing access to a disabled user. The check (is user disabled or not) is performed against another service via API call.
Fairly simple task on the surface, but who does not like a good edge case?
Steve (our fictional character) has signed in with “Remember Me” (by default the cookie expired in +5 years). Two days later Steve’s account is disabled by the system administrator. Unsuspecting Steve comes back to the platform five days later, authentication process recognises a valid “Remember Me” cookie and allows access.
I trust this being not an issue for a proper authentication/authorisation package, not in my case, though — I was dealing with legacy.
I took the 1st stab at creating a route middleware. The logic was simple — if you have been allowed access viaRemember()
then we check if your account is disabled. In a nutshell:
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->viaRemember()) { # is user disabled? API call to another service.
# yes, back to login and challenge for credentials. } return $next($request);
}
To my surprise, viaRemember()
in this case, was always returning false
. As seen by this google-query, this is a fairly common “issue”. It seems a lot of coders finding themselves puzzled when it comes to Auth::viaRemember()
.
You’ll find the best answer here.
To summarise:
Auth::viaRemember()
goes afterAuth::check()
.- Nothing else is different when compared to credentials-driven authentication process/flow.
I took a 2nd stab at expanding an existing route middleware responsible for protecting routes from unauthorised access. In a nutshell:
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) { if (Auth::guard($guard)->viaRemember()) { # is user disabled? API call to another service.
# yes, back to login and challenge for credentials. }
# original code.
} return $next($request);
}
I did not like the end result, felt to “crowded”, which lead me to the 3rd and final stab.
A beauty with Auth::check()
is that it will return true
in both cases:
- valid session cookie
- valid “Remember Me” cookie.
These leads to a natural flow where viaRemember()
is best to be used.
- As a result of valid
Auth::check()
we’ll have a successful authentication and thus - an event will be fired which we can listen for
App\Listeners\LogSuccessfulLogin
and - determinate if successful authentication was caused by “Remember Me” or not.
public function handle(Login $event)
{
if (Auth::guard($event->guard)->viaRemember()) {
# is user disabled? API call to another service.
# yes, back to login and challenge for credentials.
}
}
Conclusion.
If you need to determinate if successful authentication was caused by “Remember Me” do that as App\Listeners\LogSuccessfulLogin
callback.