Api: Type error: Argument 2 passed to Dingo\Api\Auth\Provider\OAuth2::authenticate() must be an instance of Dingo\Api\Routing\Route, null given

Created on 15 Mar 2016  路  24Comments  路  Source: dingo/api

Type error: Argument 2 passed to Dingo\Api\Auth\Provider\OAuth2::authenticate() must be an instance of Dingo\Api\Routing\Route, null given

Get this error when running php artisan clear-compiled

Only seen after updating past e842d8c5245ce2ef9f4384409ae8a775d04b2a38 in dev-master. Prior to this commit everything was working.

Most helpful comment

Hi!

I'm having the same error message in a different context:
Type error: Argument 2 passed to Dingo\Api\Auth\Provider\OAuth2::authenticate() must be an instance of Dingo\Api\Routing\Route, null given

The error only happens when running tests (phpunit). In a transformer I do:

<?php
namespace App\Api\Transformers;

use League\Fractal\TransformerAbstract;
use App\Thing;

class MyTransformer extends TransformerAbstract
{
    public function transform(Thing $thing)
    {
        $apiUser = app('Dingo\Api\Auth\Auth')->user();

The instruction app('Dingo\Api\Auth\Auth')->user(); triggers the error.

So I tried with helpers (as you mentionned above) :

<?php
namespace App\Api\Transformers;

use League\Fractal\TransformerAbstract;
use Dingo\Api\Routing\Helpers;
use App\Thing;

class MyTransformer extends TransformerAbstract
{
    use Helpers;

    public function transform(Thing $thing)
    {
        $apiUser = $this->user;

And the instruction $this->user; still triggers the error.

Do you have any advices ?

More informations:

  • It only happends in tests
  • This call to transformer is made in the setUp function of the tests (and is executed after a laravel event is triggered)
  • It appeared after a composer install
  • Tests are still passing on my other computer, I tried to composer install there, but didn't succeed to reproduce the error.

It's not blocking on my side (as tests pass on my main computer) but I guess it could learn me something, and maybe helps you improving dingo :)

:peach:

All 24 comments

same issue, after running composer update i am getting this, running php 7 and Laravel 5.1

+1

Can I see more of the stack trace please?

Also any other details you think might be relevant. Where are you registering the OAuth2 provider? Are you applying the api.auth middleware to a group of routes or just a few routes? Is it defined in the controller?

My initial reaction is why is authentication even running for you when running a Composer update or trying to clear the compiled classes.

Stack trace

[2016-03-17 07:12:13] local.ERROR: Symfony\Component\Debug\Exception\FatalThrowableError: Type error: Argument 2 passed to Dingo\Api\Auth\Provider\OAuth2::authenticate() must be an instance of Dingo\Api\Routing\Route, null given, called in /home/vagrant/Code/dev.figured.com/vendor/dingo/api/src/Auth/Auth.php on line 82 in /home/vagrant/Code/dev.figured.com/vendor/dingo/api/src/Auth/Provider/OAuth2.php:69
Stack trace:
#0 /home/vagrant/Code/dev.figured.com/vendor/dingo/api/src/Auth/Auth.php(82): Dingo\Api\Auth\Provider\OAuth2->authenticate(Object(Illuminate\Http\Request), NULL)
#1 /home/vagrant/Code/dev.figured.com/vendor/dingo/api/src/Auth/Auth.php(151): Dingo\Api\Auth\Auth->authenticate()
#2 /home/vagrant/Code/dev.figured.com/vendor/dingo/api/src/Auth/Auth.php(166): Dingo\Api\Auth\Auth->getUser(true)
#3 /home/vagrant/Code/dev.figured.com/app/Figured/Packages/Api/Http/Controllers/V1/BaseController.php(15): Dingo\Api\Auth\Auth->user()
#4 [internal function]: App\Figured\Packages\Api\Http\Controllers\V1\BaseController->__construct()
#5 /home/vagrant/Code/dev.figured.com/vendor/laravel/framework/src/Illuminate/Container/Container.php(783): ReflectionClass->newInstanceArgs(Array)
#6 /home/vagrant/Code/dev.figured.com/vendor/laravel/framework/src/Illuminate/Container/Container.php(633): Illuminate\Container\Container->build('App\\Figured\\Pac...', Array)
#7 /home/vagrant/Code/dev.figured.com/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(674): Illuminate\Container\Container->make('App\\Figured\\Pac...', Array)
#8 /home/vagrant/Code/dev.figured.com/vendor/dingo/api/src/Routing/Route.php(327): Illuminate\Foundation\Application->make('App\\Figured\\Pac...')
#9 /home/vagrant/Code/dev.figured.com/vendor/dingo/api/src/Routing/Route.php(188): Dingo\Api\Routing\Route->makeControllerInstance()
#10 /home/vagrant/Code/dev.figured.com/vendor/dingo/api/src/Routing/Route.php(171): Dingo\Api\Routing\Route->mergeControllerProperties()
#11 /home/vagrant/Code/dev.figured.com/vendor/dingo/api/src/Routing/Route.php(148): Dingo\Api\Routing\Route->setupRouteProperties(Object(Illuminate\Http\Request), Object(Illuminate\Routing\Route))
#12 /home/vagrant/Code/dev.figured.com/vendor/dingo/api/src/Routing/Router.php(696): Dingo\Api\Routing\Route->__construct(Object(Dingo\Api\Routing\Adapter\Laravel), Object(Illuminate\Foundation\Application), Object(Illuminate\Http\Request), Object(Illuminate\Routing\Route))
#13 /home/vagrant/Code/dev.figured.com/vendor/dingo/api/src/Routing/Router.php(758): Dingo\Api\Routing\Router->createRoute(Object(Illuminate\Routing\Route))
#14 /home/vagrant/Code/dev.figured.com/vendor/dingo/api/src/Console/Command/Routes.php(55): Dingo\Api\Routing\Router->getRoutes()
#15 [internal function]: Dingo\Api\Console\Command\Routes->__construct(Object(Dingo\Api\Routing\Router))
#16 /home/vagrant/Code/dev.figured.com/vendor/laravel/framework/src/Illuminate/Container/Container.php(783): ReflectionClass->newInstanceArgs(Array)
#17 /home/vagrant/Code/dev.figured.com/vendor/laravel/framework/src/Illuminate/Container/Container.php(633): Illuminate\Container\Container->build('Dingo\\Api\\Conso...', Array)
#18 /home/vagrant/Code/dev.figured.com/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(674): Illuminate\Container\Container->make('Dingo\\Api\\Conso...', Array)
#19 /home/vagrant/Code/dev.figured.com/vendor/laravel/framework/src/Illuminate/Console/Application.php(115): Illuminate\Foundation\Application->make('Dingo\\Api\\Conso...')
#20 /home/vagrant/Code/dev.figured.com/vendor/laravel/framework/src/Illuminate/Console/Application.php(129): Illuminate\Console\Application->resolve('Dingo\\Api\\Conso...')
#21 /home/vagrant/Code/dev.figured.com/vendor/laravel/framework/src/Illuminate/Support/ServiceProvider.php(178): Illuminate\Console\Application->resolveCommands(Array)
#22 [internal function]: Illuminate\Support\ServiceProvider->Illuminate\Support\{closure}(Object(Illuminate\Console\Events\ArtisanStarting))
#23 /home/vagrant/Code/dev.figured.com/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(221): call_user_func_array(Object(Closure), Array)
#24 /home/vagrant/Code/dev.figured.com/vendor/laravel/framework/src/Illuminate/Console/Application.php(46): Illuminate\Events\Dispatcher->fire('Illuminate\\Cons...')
#25 /home/vagrant/Code/dev.figured.com/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(225): Illuminate\Console\Application->__construct(Object(Illuminate\Foundation\Application), Object(Illuminate\Events\Dispatcher), '5.2.22')
#26 /home/vagrant/Code/dev.figured.com/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(107): Illuminate\Foundation\Console\Kernel->getArtisan()
#27 /home/vagrant/Code/dev.figured.com/artisan(35): Illuminate\Foundation\Console\Kernel->handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#28 {main}  

boot method in the Provider:

$this->app[Auth::class]->extend('oauth', function ($app) {
    $provider = new OAuth2($app['oauth2-server.authorizer']->getChecker());

    $provider->setUserResolver(function ($id) {
        return User::find($id);
    });

    return $provider;
});

Routes:

<?php

$config = [
    'prefix'     => 'api/v1',
    'middleware' => 'api.auth',
    'providers'  => [
        'oauth'
    ]
];

app('Dingo\Api\Routing\Router')->version('v1', $config, function ($api) {
    $api->get(
        'farms',
        'App\Figured\Packages\Api\Http\Controllers\V1\FarmsController@getIndex'
    );
...

My routes.php file looks like:

    $api = app('Dingo\Api\Routing\Router');

    $api->version('v1', function ($api) {
        $api->group(['middleware' => ['api.auth'], 'limit' => 100, 'expires' => 5], function ($api) {

    /*  ---  API JOB ROUTES --- */
    $api->get('jobs', 'App\Http\Controllers\API\V1\JobController@getJobs');
    $api->post('job', 'App\Http\Controllers\API\V1\JobController@postJob');
    $api->get('job/{job}', 'App\Http\Controllers\API\V1\JobController@getJob');
    $api->put('job/{job}', 'App\Http\Controllers\API\V1\JobController@putJob');
    $api->delete('job/{job}', 'App\Http\Controllers\API\V1\JobController@deleteJob');
   });
  });

My AppServiceProvide.php

    //        app('Dingo\Api\Auth\Auth')->extend('basic', function ($app) {
    //            return new \Dingo\Api\Auth\Provider\Basic($app['auth'], 'email');
    //        });

    app('Dingo\Api\Auth\Auth')->extend('oauth', function ($app) {
        $provider = new \Dingo\Api\Auth\Provider\OAuth2($app['oauth2-server.authorizer']->getChecker());

        $provider->setUserResolver(function ($id) {
            // Logic to return a user by their ID.
            return User::find($id);
        });

        $provider->setClientResolver(function ($id) {
            // Logic to return a client by their ID.
            return User::find($id);
        });

        return $provider;
    });

As you can see I was running some test with the basic authentication aswell and as soon as I activate it It throws me the same error but according to the Basic authenticator instead of the OAUth.

This is the error for the Basic authentication:

[Symfony\Component\Debug\Exception\FatalThrowableError] Type error: Argument 2 passed to Dingo\Api\Auth\Provider\Basic::authenticate() must be an instance of Dingo\Api\Routing\Route, null given, called in /home/vagrant/fluido-jobs/v endor/dingo/api/src/Auth/Auth.php on line 82

As a final addition I will say that I'm able to get this error if I run the php artisan optimizeaswell.

If I can get more information I will try to post it but so far that's what I've seen.

Thx.

Are you both calling $this->auth->user() in the constructor of your controllers?

I do and commenting the call to it seems to be fixing the error.
What is the explanation and work arround for it?

Thx for such a quick response on it.

yeah i'm doing this in the __constructor

    public function __construct()
    {
        $user = $this->auth->user();
        if (is_null($user)) {
            abort(401);
        }

        Auth::login($this->auth->user());
    }

Is this not the correct way to authorise users?

me too have $this->auth->user(); in __construct of controller, but as you know it was working before :neutral_face:

Is this not the correct way to authorise users?

Nope. You shouldn't even be using Laravel's authentication to log users in on your API. That will store a session. That's not how it works.

You should be using the api.auth middleware to authenticate each request.

By calling $this->auth->user() in your constructor you're attempting to authenticate. Now, I can implement some logic so that the error isn't thrown for most console calls except the api:routes command, and that's because this command news up the controller instance and will error out due to the authentication being fired.


So @richardwyke you need to change how your authenticating, as that's not how this package is intended to be used for authenticated requests.

@saqueib & @umbertix why are you using it in the constructor? I might be able to provide you with alternatives.

FYI have pushed a small fix so that you can run most other commands without error. However you will no doubt continue to encounter errors for some commands.

thanks for the fix!

the only reason we're doing that is because we have a lot of logic in the app tied to the laravel authenticated user through Auth::user() do we need to split the code for both api authentication and also standard authenticated users?

The authentication bundled with this package utilizes the Laravel authentication, however, it does not store sessions. So when you use the api.auth middleware on routes/controllers, then use $this->auth->user() inside a method of a controller you'll actually get the Illuminate\Contracts\Auth\Authenticatable instance that you usually would.

The only reason it's highly recommended you use the API authentication is that it will handle the 401 and all that for you when it's time to do so.

Oh, and you get a bunch of other authentication providers to use.

@jasonlewis I am doing $this->auth->user() in constructor because I need the current user in controllers most of methods methods, so i don't have to copy and paste same $this->auth->user() all over.

public function __construct(ApiPostRepo $postRepo, PointRepo $pointRepo)
{
        $this->user = $this->auth()->user();
}

in controllers methods

$this->user->can('EditPost') ....

pleas let me know is there best way to do this.

You don't need to set it, you can call it already as it's picked up by __get.

great :+1:

I'll be doing some updated docs in the coming days so I'll be sure to mention this as it's quite important.

Hi!

I'm having the same error message in a different context:
Type error: Argument 2 passed to Dingo\Api\Auth\Provider\OAuth2::authenticate() must be an instance of Dingo\Api\Routing\Route, null given

The error only happens when running tests (phpunit). In a transformer I do:

<?php
namespace App\Api\Transformers;

use League\Fractal\TransformerAbstract;
use App\Thing;

class MyTransformer extends TransformerAbstract
{
    public function transform(Thing $thing)
    {
        $apiUser = app('Dingo\Api\Auth\Auth')->user();

The instruction app('Dingo\Api\Auth\Auth')->user(); triggers the error.

So I tried with helpers (as you mentionned above) :

<?php
namespace App\Api\Transformers;

use League\Fractal\TransformerAbstract;
use Dingo\Api\Routing\Helpers;
use App\Thing;

class MyTransformer extends TransformerAbstract
{
    use Helpers;

    public function transform(Thing $thing)
    {
        $apiUser = $this->user;

And the instruction $this->user; still triggers the error.

Do you have any advices ?

More informations:

  • It only happends in tests
  • This call to transformer is made in the setUp function of the tests (and is executed after a laravel event is triggered)
  • It appeared after a composer install
  • Tests are still passing on my other computer, I tried to composer install there, but didn't succeed to reproduce the error.

It's not blocking on my side (as tests pass on my main computer) but I guess it could learn me something, and maybe helps you improving dingo :)

:peach:

@nicolas-t I have the exact same issue

@murwa calling app('Dingo\Api\Auth\Auth')->user() will try to authenticate the user, and then return the user. (and in our cases trigger an error)

As a workaround I used app('Dingo\Api\Auth\Auth')->user(false) it returns the user without trying to authenticate it.

I guess it's fine, because with dingo the authentication is done beforehand, in a route middleware.

Aaaah, yes! Thanks @nicolas-t

I have same issue but when I want to access authenticated user in a serviceProvider.

I have a PriceListServiceProvider and want to access logged in user in the boot method for some reason, like this :

    $user = app('Dingo\Api\Auth\Auth')->user();
    dd($user);

    if (!empty($user->settingOf('system', 'price_list_id'))) {
        $defaultPriceList = $user->settingOf('system', 'price_list_id');
    } 
    else if (!empty(Setting::of('system', 'price_list_id'))) {
        $defaultPriceList = Setting::of('system', 'price_list_id');
    } else {
        $priceList = PriceList::where('rate', 'toman')->orderBy('created_at', 'asc')->first();
        if ($priceList) {
            $defaultPriceList = $priceList->price_list_id;
        }
    }

    Config::set('price_list_id', $defaultPriceList);

But each I tun the project I got this error :

Type error: Argument 2 passed to Dingo\Api\Auth\Provider\JWT::authenticate() must be an instance of Dingo\Api\Routing\Route, null given, called in D:\wamp\www\zarsam-app\vendor\dingo\api\src\Auth\Auth.php on line 82

@ahmadbadpey : I am not sure if its available authorization when booting your service provider

For example in lumen there the sequence of boot/register of service providers were diffrenet way than Laravel

When user logged needed you could user injection off Autenticable or using: app(Autenticable::class)

I had the same error but if i run my queue:listen using php5.6 , it does not throw the error. (L5.2 , Homestead-7)
i.e.: php5.6 artisan queue:listen --tries=2

Was this page helpful?
0 / 5 - 0 ratings