How to bind user object to request in a middleware

eldblz picture eldblz · Sep 9, 2016 · Viewed 11.3k times · Source

i'm writing an application in Laravel Spark 1.0 (Laravel 5.2). I wrote a custom middleware for agent (api) authentication. This is the code:

<?php

namespace App\Http\Middleware;

use App\Agent;
use Closure;
use Illuminate\Http\Request;

class AgentAuth
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if( isset($request->token) &&  !empty($request->token) )
        {
            $agent = Agent::where('token', '=', $request->token)->first();

            if( $agent != NULL )
            {
                $team = $agent->Team()->first();
                $user = $team->User()->first();

                $request->merge(['team' => $team ]);
                $request->merge(['user' => $user ]);

                return $next($request);
            }
            else {
                return response('Unauthorized 2.', 401);
            }

        }
        else {
            return response('Unauthorized 1.', 401);
        }
    }
}

In the default laravel authentication the user object is injected in the request (see laravel docs): https://laravel.com/docs/5.2/authentication#retrieving-the-authenticated-user

So you can retrieve the user using:

$request->user();

Spark obviously use this method to check if user subscription is valid (laravel\spark\src\Http\Middleware\VerifyUserIsSubscribed):

if ($this->subscribed($request->user(), $subscription, $plan, func_num_args() === 2)) {
            return $next($request);
        }

And it's not working because, with my middleware, you can retrieve the user using: $request->user; but not with the laravel defaults $request->user();

How should i inject the user object into the request?

Thank you in advance

EDIT:

Laravel in the service provider (Illuminate\Auth\AuthServiceProvider@registerRequestRebindHandler)

Use this code to bind object user to the request:

/**
     * Register a resolver for the authenticated user.
     *
     * @return void
     */
    protected function registerRequestRebindHandler()
    {
        $this->app->rebinding('request', function ($app, $request) {
            $request->setUserResolver(function ($guard = null) use ($app) {
                return call_user_func($app['auth']->userResolver(), $guard);
            });
        });
    }

I tried to insert this code, with the appropriate correction, in the middleware but i can't figure out how to make it work.

Answer

jmadsen picture jmadsen · Sep 12, 2016

I don't have a copy of Spark to try this & ensure what I'm doing is correct for you, but I think this will help:

1) An assumption - I believe you are saying that yes, this line will get you the user you want:

$user = $team->User()->first();

and you merely want to bind it to the request so that you can access this user later in your app via:

$request->user()

2) If this is true, then all I did was simplify the code you provided to add:

$request->merge(['user' => $user ]);

//add this
$request->setUserResolver(function () use ($user) {
    return $user;
});

// if you dump() you can now see the $request has it
dump($request->user());

return $next($request);

I also $request->user() in the route closure, and it is there.

The app rebinding was a little strange to me, and didn't seem necessary. I'm not sure that anything would really need this for what you are doing.