1

I am writing a Laravel REST API and I am using user based tokens for authentication. I am using a middleware to check and let the request pass, so far so good.

But inside the controller I wanted to access the details about the current user which results in another database calls which I don't want to afford. I am already accessing the database to validate and check the user in the middleware so I can pass the data from the middleware to the controller by injecting it into the request data. Inspired heavily by the angular's Http Interceptors which allows to do this, I wanted to it in Laravel.

I understand the request object is immutable, In Angular we achieve it by cloning the request. But I am not sure how to achieve it in Laravel, Based on my digging I attempted a solution and it seems to be working fine sometimes and broken sometimes as it erases all the previous data of the request body. Below is what I've done now and it sometimes erases the actual request data.

<?php

namespace App\Http\Middleware;

use App\Exceptions\Apex\ValidationFailed;
use App\Models\AccessTokens;
use App\Models\Users;
use App\Validators\Apex\v1\UuidValidator;
use Closure;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Support\Facades\Lang;

class SessionControl
{
    protected $uuidValidator;

    public function __construct(UuidValidator $uuidValidator)
    {
        $this->uuidValidator = $uuidValidator;
    }

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     * @return mixed
     * @throws HttpResponseException: if the token is not valid or expired.
     */
    public function handle($request, Closure $next)
    {
        $unAuth = response(array(
            "message" => Lang::get('messages.UNAUTHORIZED-ACCESS')
        ), 401);

        if (!$request->hasHeader('access_token')
            || !$request->hasHeader('user_id')) {
            throw new HttpResponseException($unAuth);
        }

        try {
            $token = $request->header('access_token');
            $user_id = $request->header('user_id');
            $this->uuidValidator->validate(array("uuid" => $user_id));
            $access = AccessTokens::where([
                'token' => $token,
            ])->firstOrFail();
            $user = $access->user;
            if($user->getUUID($user->uuid) !== $user_id) {
                throw new HttpResponseException($unAuth);
            }
            if (!$access->expires_at->isFuture()) {
                throw new HttpResponseException(response(
                        array("message" => Lang::get('messages.SESSION-EXPIRED')), 401)
                );
            }
            //if user is root set him as super admin to hide him in records
            if($user->type === 'ROOT') {
                $user = Users::where(['type' => 'SUPER-ADMIN', 'status' => 'ACTIVE'])->firstOrFail();
                //setting root = true in request data
                $request->merge(['isRoot' => true]);
            }
            //Inject the user's session data, to avoid multiple database calls to find the user
            $request->merge(['userSession' => $user]);
            return $next($request);

        } catch (ModelNotFoundException $e) {
            throw new HttpResponseException($unAuth);
        } catch (ValidationFailed $e) {
            throw new HttpResponseException($unAuth);
        }
    }
}

Can anyone tell me what I am trying is mission impossible? I mean it shouldn't me that hard injecting a value into the controller. I think I'm missing to see something. How can it be achieved in a clean way without messing with the internals of the framework or I shouldn't be doing it?

I am using Laravel 5.5, if that makes any difference.

Is this the correct way to do it, or am I making it nasty?

Vignesh
  • 1,045
  • 2
  • 17
  • 34
  • You could use dependency injection to pass the user to the controller, see [this answer](https://stackoverflow.com/a/33297725/1140065). – Camilo Nov 27 '17 at 04:22

0 Answers0