16

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.

Jeff Puckett
  • 37,464
  • 17
  • 118
  • 167
eldblz
  • 758
  • 3
  • 11
  • 24

4 Answers4

47

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.

jmadsen
  • 3,635
  • 2
  • 33
  • 49
  • 1
    that stuff is useful than your logged user has diff type of Object with diff realization, like user of class Agency, user of type Agent, each user logged has own methods and all of theses extends User class – dmitri Jan 27 '19 at 21:03
3

You could use the auth system if that model implements the right interface, to log them in for the request.

Auth uses a rebinder to assign the userResolver on request. (So you get $request->user() from it). Check Illuminate\Auth\AuthServiceProvider@registerRequestRebindHandler to see how its setting that resolver.

$request->setUserResolver(....)
lagbox
  • 48,571
  • 8
  • 72
  • 83
  • I'm not using Auth because i actually autenticate the Agent not the User (the agent has a relationship with the user) I saw the registerRequestRebindHandler method but frankly i don't understand exactly how it works. And so i can't make it work in my middleware – eldblz Sep 10 '16 at 08:26
2

This is a very useful question. I was having trouble with the selected solution though. In my middleware I could successfully see $request->user(), however it was failing when using gates, namely in the Access/Gate class:

protected function raw($ability, $arguments = [])
{
    if (! $user = $this->resolveUser()) {
        return false;
    }

    // ...

This function is always returning false :/

So I did it as suggested here (http://laravel-recipes.com/recipes/230/setting-the-currently-authenticated-user), namely:

$usr = new User();
$usr->setAttribute('id', $request->user_id);
Auth::setUser($usr);

And it appears to be working without using setUserResolver().

Thanks

mils
  • 1,878
  • 2
  • 21
  • 42
0

If you have the user ID you can easily authenticate the user with \Illuminate\Support\Facades\Auth::onceUsingId($user_id)

This updates the $request object. For example:

public function test(Request $request)
{
    Auth::onceUsingId(19);
    $next = new \App\Http\Controllers\OtherController();
    return $next->otherMethod($request);
}
miker
  • 101
  • 7