skip to Main Content

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: routesweb.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?

2

Answers


  1. Chosen as BEST ANSWER

    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 = [
            AppHttpMiddlewareSetHeadersTokenWeb::class,
        ];
    
    • My middleware to set the header with the token stored in the session:
    <?php
    namespace AppHttpMiddleware;
    
    use Closure;
    use IlluminateHttpRequest;
    
    class SetHeadersTokenWeb
    {
        /**
         * Handle an incoming request.
         *
         * @param  IlluminateHttpRequest $request
         * @param  Closure(IlluminateHttpRequest): (IlluminateHttpResponse|IlluminateHttpRedirectResponse) $next
         * @return IlluminateHttpResponse|IlluminateHttpRedirectResponse
         */
        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: routesweb.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.


  2. 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 AppHttpKernel.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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search