Laravel and Passport Authentication via HTTPonlycookies

  laravel, oauth, php, vue.js

I am new to laravel and trying to do a simple Authentication project using the laravel/passport package provided by the laravel team and I have no problem with sending the token via a httponly cookie and receiving it from a frontend framework Vuejs. I am able to get the authentication working by storing the token into a localstorage on the browser but all the blogs and documentations I have read suggest not to use localstorage for storing a jwt token and most of them suggest to use httponly cookie because it is not accessible from javascript.

and for my layers of authentication use

  1. a proxyRequest util class
  2. an Authcontroller
  3. I do not use the default controller I have a person model
  4. I have a Cors middleware for allowing requests

proxyRequest class

    <?php
    
     namespace AppUtilities;
     // use IlluminateSupportFacadesHttp;
    
    class ProxyRequest {
    public function grantPasswordToken(string $email, string $password)
    {
        $params = [
            'grant_type' => 'password',
            'username' => $email,
            'password' => $password,
        ];
    
        return $this->makePostRequest($params);
    }
    
    public function refreshAccessToken()
    {
        $refreshToken = request()->cookie('refresh_token');
    
        abort_unless($refreshToken, 403, 'Your refresh token is expired.');
    
        $params = [
            'grant_type' => 'refresh_token',
            'refresh_token' => $refreshToken,
        ];
    
        return $this->makePostRequest($params);
    }
    
    protected function makePostRequest(array $params)
    {
        $params = array_merge([
            'client_id' => config('services.passport.password_client_id'),
            'client_secret' => config('services.passport.password_client_secret'),
            'scope' => '',
        ], $params);
    
        $proxy = Request::create('oauth/token', 'post', $params);
        $resp = json_decode(app()->handle($proxy)->getContent());
    
        $this->setHttpOnlyCookie($resp->refresh_token);
    
        return app()->handle($proxy)->getContent();
        return $resp;
    }
    
      protected function setHttpOnlyCookie(string $refreshToken)
      {
        cookie()->queue(
            'refresh_token',
            $refreshToken,
            14400, // 10 days
            null,
            null,
            false,
            true // httponly
        );
      }
    }```

### Authcontroller
<?php

namespace AppHttpControllersApi;

use IlluminateHttpRequest;
use AppHttpControllersController;
use AppPerson;
// use AppPerson;
// use AppPerson;
use IlluminateSupportFacadesValidator;
use IlluminateSupportFacadesHash;
use IlluminateSupportFacadesAuth;
use Cookie;
use AppUtilitiesProxyRequest;

class AuthController extends Controller
{


protected $proxy;

public function __construct(ProxyRequest $proxy)
{
    $this->proxy = $proxy;
}

public function user(Request $request)
{   
    if (Auth::guard('api')->check()) {
        return $request->user('api');
    }
    
    return "not auth";
}
public function register(Request $request)
{
    // $this->validate(request(), [
    //     'name' => 'required',
    //     'email' => 'required|email',
    //     'password' => 'required',
    // ]);

    $user = Person::create([
        'f_name' => $request->name,
        'email' => $request->email,
        'password' => Hash::make($request->password),
    ]);

    $resp = $this->proxy->grantPasswordToken(
        $user->email,
        $request->password
    );

    // return response([
    //     'token' => $resp->access_token,
    //     'expiresIn' => $resp->expires_in,
    //     'message' => 'Your account has been created',
    // ], 201);
    return response()->json($resp);
}


public function check() {
    return "Authenticated";
}

public function refreshToken()
{
    $resp = $this->proxy->refreshAccessToken();

    return response([
        'token' => $resp->access_token,
        'expiresIn' => $resp->expires_in,
        'message' => 'Token has been refreshed.',
    ], 200);
}
public function logout(Request $request)
{
    $token = $request->user()->token();
    $token->delete();

    // remove the httponly cookie
    cookie()->queue(cookie()->forget('refresh_token'));

    return response([
        'message' => 'You have been successfully logged out',
    ], 200);
        return $request->all();
}
public function login(Request $request)
{
    $user = Person::where('email', $request->email)->first();

    abort_unless($user, 404, 'User not found.');
    abort_unless(
        Hash::check($request->password, $user->password),
        403,
        'Password or mail address not correct.'
    );

    $resp = $this->proxy->grantPasswordToken($user->email, $request->password);
   
    return response([
        'token' => $resp->access_token,
        'expiresIn' => $resp->expires_in,
        'message' => 'You have been logged in',
    ], 200);
}


}```

routes

    ```
Route::middleware('guest')->group(function () {
    Route::post('register', '[email protected]')->name('register');
    Route::post('login', '[email protected]')->name('login');
    Route::post('refresh-token', '[email protected]')->name('refreshToken');
}); 

Route::middleware('auth:api')->group(function () {
    Route::post('logout', '[email protected]')->name('logout');
});```

middlewares

    protected $middleware = [
        AppHttpMiddlewareaddCookieToHeader::class,
        AppHttpMiddlewareCheckForMaintenanceMode::class,
        IlluminateFoundationHttpMiddlewareValidatePostSize::class,
        AppHttpMiddlewareTrimStrings::class,
        IlluminateFoundationHttpMiddlewareConvertEmptyStringsToNull::class,
        AppHttpMiddlewareTrustProxies::class,
        AppHttpMiddlewareCors::class,
        IlluminateCookieMiddlewareAddQueuedCookiesToResponse::class,

    ];```
when I hut the login and register routes I am able to generate a token but if i try to logout 
i just get a response that says {message: "UnAuthenticated"}.

I couldnt find anything regarding this on the internet. 

Source: Laravel

Leave a Reply