Issue
Is this feature included in the SPA Authentication? By reading the docs on Laravel Sanctum, it doesn't look like it, but at the same time, this is a common feature (used if user reset password or if you want only one login instance from a user) so I thought that it must be included...
After searching, I found this:
use Illuminate\Support\Facades\Auth;
Auth::logoutOtherDevices($currentPassword);
but you'll need to uncomment this middleware in the web before you can use this.
'web' => [
// ...
\Illuminate\Session\Middleware\AuthenticateSession::class,
// ...
],
However this only works on web and not on api. So I googled again how to have the same functionality with api and I found this youttube video. Here's what the guy did:
- Create his own middleware (ex. AuthenticateSessionSPA.php).
- Copy everything in AuthenticateSession and paste it in the new middleware. Change namespace and class name.
- Create private variable with value of 'sanctum' (ex. private $driver = 'sanctum')
- Replace all $this->auth->getDefaultDriver() with $this->driver. So the code will use the sanctum driver instead.
The file looks like this:
<?php
namespace App\Http\Middleware\Custom;
use Closure;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Contracts\Auth\Factory as AuthFactory;
class AuthenticateSessionSPA
{
private $driver = 'sanctum';
/**
* The authentication factory implementation.
*
* @var \Illuminate\Contracts\Auth\Factory
*/
protected $auth;
/**
* Create a new middleware instance.
*
* @param \Illuminate\Contracts\Auth\Factory $auth
* @return void
*/
public function __construct(AuthFactory $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (! $request->hasSession() || ! $request->user()) {
return $next($request);
}
if ($this->guard()->viaRemember()) {
$passwordHash = explode('|', $request->cookies->get($this->auth->getRecallerName()))[2] ?? null;
if (! $passwordHash || $passwordHash != $request->user()->getAuthPassword()) {
$this->logout($request);
}
}
if (! $request->session()->has('password_hash_'.$this->driver)) {
$this->storePasswordHashInSession($request);
}
if ($request->session()->get('password_hash_'.$this->driver) !== $request->user()->getAuthPassword()) {
$this->logout($request);
}
return tap($next($request), function () use ($request) {
if (! is_null($this->guard()->user())) {
$this->storePasswordHashInSession($request);
}
});
}
/**
* Store the user's current password hash in the session.
*
* @param \Illuminate\Http\Request $request
* @return void
*/
protected function storePasswordHashInSession($request)
{
if (! $request->user()) {
return;
}
$request->session()->put([
'password_hash_'.$this->driver => $request->user()->getAuthPassword(),
]);
}
/**
* Log the user out of the application.
*
* @param \Illuminate\Http\Request $request
* @return void
*
* @throws \Illuminate\Auth\AuthenticationException
*/
protected function logout($request)
{
$this->guard()->logoutCurrentDevice();
$request->session()->flush();
throw new AuthenticationException('Unauthenticated.', [$this->driver]);
}
/**
* Get the guard instance that should be used by the middleware.
*
* @return \Illuminate\Contracts\Auth\Factory|\Illuminate\Contracts\Auth\Guard
*/
protected function guard()
{
return $this->auth;
}
}
And this works wonderfully, I can now use Auth::logoutOtherDevices($currentPassword) in my api.
So my question is if this is safe? I'm just a jr. dev (6 months) and I'm not that confident in this solution since I found it from someone on the net and not from the docs. I'm wondering maybe the laravel devs didn't implement it because they have reasons like security?
What are your thoughts on this method? If you don't agree with this, how would you implement logging out from other devices in a project that has a SPA frontend and Laravel api?
Solution
Doesn't look like this is included in Laravel Sanctum SPA Authentication. So I just did my original answer found on the youtube video
Answered By - jove0610
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.