0

One part of the goal here is to deepen my knowledge about the framework, so even if this isn’t “the right way”, I’d still like to try a solution to check if I should proceed with sanctum or passport.

Basic setup:

  • Laravel 8.37
  • Sanctum 2.14
  • PHP 8

Frontend – custom login screen. Backend – authentication mechanism. (all in Laravel, but different endpoints)

Up till now, I’ve managed to:

  • Build the frontend login page;
  • Send the information to my API;
  • My API checks user / password and creates a sanctum token for that user in personal_access_tokens table;
  • API sends information back to the frontend; Something like: loginToken: 123|xxxyyyzzz

Here’s where I’m having difficulties and not being able to access the right access route I want too.

Back in my frontend controller, I grab the token and redirect to a web “Sanctum secured” web route.

Example: AdminLoginController.php

            $loginToken = $arrAuthenticationCheckJson['loginToken'];

            return redirect($returnURL)
                ->header('Authorization', 'Bearer ' . $loginToken)
                ->header('Accept', 'application/json')
                ->with('messageSuccess', 'Login successful'));

My routes: routes\web.php

// Protected routes.
Route::group(['middleware' => 'auth:sanctum'], function () {
    Route::get('/system/dashboard/',[AdminDashboardController::class, 'adminDashboard'])->name('admin.dashboard');

    
});

Returns me a 401 status and redirects me to the login route. I’ve watched something about XSRF-TOKEN cookie (https://youtu.be/QwjzjksfLMo), but am not sure if it interferes with anything. Also, not sure if I can set the headers this way or if I should store the returned token in a session and set the header in a middleware.

Is there any way I could make this work with my current logic?

Jorge Mauricio
  • 411
  • 6
  • 18

2 Answers2

0

Laravel put everything automatically into returning object. You don't need to add anything manually. So remove two ->header()

return redirect($returnURL)->with('messageSuccess', 'Login successful'));

Not only, but arguably the best way of protecting routes is to use middleware. Create a new one, register it to route middleware array on App\Http\Kernel.php, and use it in route:

Route::group(['middleware' => ['auth:sanctum', 'dashboard']], function () {
    Route::get('/system/dashboard/',[AdminDashboardController::class, 'adminDashboard'])->name('admin.dashboard');
});

In middleware check if the current user is allowed to access to dashboard.

Finally, please use Laravel 10. I don't know why you have started with an old version, but not a good idea.

Bulent
  • 3,307
  • 1
  • 14
  • 22
0

It’s not exactly what I wanted, but here what I did to build a workaround, so I’m not marking as the right answer.

Important: When testing route security, I noticed that cleaning up all caches before each try, helped me debug.

php artisan route:clear
php artisan cache:clear
php artisan config:clear

Other important considerations:

  • If testing from postman, be sure to copy the output token and not the one registered in the personal_access_tokens table.

  • In my custom user model (not using laravel migration), be sure to define the table in the class property (reference: https://stackoverflow.com/a/30159291/2510785): public $table = 'users_table';

My workaround was storing the token in a session (frontend) and building a middleware which sets the header with the Bearer token that runs before the sanctum auth.

  • Storing the session (frontend), after I receive the data from the API:

$loginToken = $arrAuthenticationCheckJson['loginToken'];
session(['user_admin_login_token' => $loginToken]);
session()->save();
    /**
     * Responsible for prioritizing the middleware
     *
     * @var array
     */
    protected $middlewarePriority = [
        \App\Http\Middleware\SetHeadersTokenWeb::class,
    ];
  • My middleware to set the header with the token stored in the session:
<?php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class SetHeadersTokenWeb
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
     * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
     */
    public function handle(Request $request, Closure $next)
    {
        // user_admin token
        $userAdminLoginToken = session('user_admin_login_token');
        if ($userAdminLoginToken) {
            $request->headers->set('Authorization', 'Bearer ' . $userAdminLoginToken);
        }

        return $next($request);
    }
}

My web route: routes\web.php

    Route::group(['middleware' => ['setHeaders.token.web', 'auth:sanctum']], function () {
{
        
        Route::get('/system/dashboard/',[AdminDashboardController::class, 'adminDashboard'])->name('admin.dashboard');
    });

I´m still interest in knowing how to build the redirect with the headers from inside the controller. Probably, another method.

To @Bulent´s point: I don’t think he understood that I was working with 2 separate endpoints (frontend and API to receive the token), so I would need to set the header someway in my frontend. Also, I’m using Laravel 8 because I didn’t start this project today. I’ve been working on this migration slowly for the past 2 years, and wouldn’t make any sense to waste time migrating for version 9, then version 10 if I still hadn’t mastered the fundamentals.

Jorge Mauricio
  • 411
  • 6
  • 18