1

I am using jwt-auth library, which injects AuthManager using type-hinting:

use Illuminate\Auth\AuthManager;
class Basic extends Authorization
{

public function __construct(AuthManager $auth, $identifier = 'email')
    {
        $this->auth = $auth;
        $this->identifier = $identifier;
    }

The problem is that if I used the middleware jwt.auth:

app('Dingo\Api\Routing\Router')->version('v1', ['middleware' => ['jwt.auth'] , 'prefix' => 'api', 'providers' => ['jwt']], function ($api) {
    $api->get('protected', function () {

       $token = JWTAuth::getToken();
       return $token;
    });
});

I get this error:

{"message":"Unresolvable dependency resolving [Parameter #0 [ <required> $app ]] in class Illuminate\\Auth\\AuthManager","status_code":500,"debug":{"line":839,"file":"\/share\/vendor\/illuminate\/container\/Container.php","class":"Illuminate\\Contracts\\Container\\BindingResolutionException"

So, the question is, how to properly inject the AuthManager ? why $app was not resolved?

simo
  • 23,342
  • 38
  • 121
  • 218

2 Answers2

6

Try injecting AuthManager in your bootstrap/app.php file:

/*
|--------------------------------------------------------------------------
| Register Service Providers
|--------------------------------------------------------------------------
|
| Here we will register all of the application's service providers which
| are used to bind services into the container. Service providers are
| totally optional, so you are not required to uncomment this line.
|
*/

$app->register(App\Providers\AppServiceProvider::class);
$app->register(App\Providers\EventServiceProvider::class);

// Injecting goes here
$app->singleton(Illuminate\Auth\AuthManager::class, function ($app) {
    return $app->make('auth');
});

Explanation

We know that Illuminate\Auth\AuthManager will be resolved automatically if we run Illuminate\Auth\AuthServiceProvider. See:

Illuminate\Auth\AuthServiceProvider@registerAuthenticator

So, we must run this service provider before we want to use AuthManager. But Lumen is slightly different. I see that Illuminate\Auth\AuthManager isn't registered yet in:

Laravel\Lumen\Application::$availableBindings

Which is it's a hack to make Lumen run faster when the container wants to resolved the resource, see:

Laravel\Lumen\Application@make

So, basically, if you want to resolve Illuminate\Auth\AuthManager class and it's dependency, you may register it's class bindings first before you use it.

Update

We know that

Laravel\Lumen\Application::$availableBindings

property is in public visibility, so this works too:

/*
|--------------------------------------------------------------------------
| Register Service Providers
|--------------------------------------------------------------------------
|
| Here we will register all of the application's service providers which
| are used to bind services into the container. Service providers are
| totally optional, so you are not required to uncomment this line.
|
*/

$app->register(App\Providers\AppServiceProvider::class);
$app->register(App\Providers\EventServiceProvider::class);

$app->availableBindings['Illuminate\Auth\AuthManager'] = 'registerAuthBindings';
$app->alias('auth', 'Illuminate\Auth\AuthManager');

Update 2

I understand that there's lot of problems if we want to implements JWT Authentication in Lumen with this library. So, I make a bootstrapped (clean start) Lumen Application that integrated well with this library. Please check out my repo. I'll add explanation about which one and why we should change the code later. Cheers.

krisanalfa
  • 6,268
  • 2
  • 29
  • 38
  • $app->singleton(Illuminate\Auth\AuthManager::class, means when ever the AuthManager is used, it will use the same instance, but can you please explain the code $app->make('auth') ? – simo Mar 07 '16 at 15:58
  • Hi @simo, I updated the answer. Is it clear enough? Just tell me when you need more clear explanation, I'll help you to dig deeper into Lumen kernel if you want. – krisanalfa Mar 07 '16 at 16:17
  • Thanks Krisa very much for explanation, I will try the solution once I reach the office, I am very experienced with OOP, but needs to learn more on Laravel and lumen frameworks.. Could not find good resources on the architecture for them.. – simo Mar 07 '16 at 17:02
  • Thanks Krisan, it worked, I didn't get the error message correctly, I thought that AuthManager was resolved, but $app var was not injected into it.. – simo Mar 08 '16 at 07:23
  • 1
    @simo Glad to help you, Sir – krisanalfa Mar 08 '16 at 15:25
  • Thanks @Krisan , I have put your solution at the issue in the repo's issue, but I still have an issue there https://github.com/tymondesigns/jwt-auth/issues/561 , I added it there sense its a repo related issue.. do you know how to solve it too? – simo Mar 08 '16 at 15:32
  • 1
    Hi @simo, I updated the answer. Sorry for the late reply, I just arrived at home. If you need something, you can contact me in my email. I really glad to help people. – krisanalfa Mar 08 '16 at 17:14
  • Thanks @Krisan, I will test your repo soon, very appreciated. – simo Mar 09 '16 at 07:17
0

I experienced this with SessionManager with the same unresolvable $app variable when registering the existing Laravel SessionServiceProvider.

After reading @krisanalfa's answer, I tried to peek at the values of $availableBindings which can be found in Application.php and it looks like this:

public $availableBindings = [
      'auth' => 'registerAuthBindings',
      'auth.driver' => 'registerAuthBindings',
      'Illuminate\Auth\AuthManager' => 'registerAuthBindings',

      'Illuminate\Contracts\Cache\Factory' => 'registerCacheBindings',
      'Illuminate\Contracts\Cache\Repository' => 'registerCacheBindings',
      ....
];

The value of each keys represents the methods that is going to be used to load the implementations which is also inside the Application.php.

If you need to load the configuration and register the binding:

protected function registerAuthBindings()
{
    $this->singleton('auth', function () {
        return $this->loadComponent('auth', 'Illuminate\Auth\AuthServiceProvider', 'auth');
    });

    $this->singleton('auth.driver', function () {
        return $this->loadComponent('auth', 'Illuminate\Auth\AuthServiceProvider', 'auth.driver');
    });

   ...
}

But if the service doesn't need any configuration, you just register it like:

protected function registerEventBindings()
{
    $this->singleton('events', function () {
        $this->register('Illuminate\Events\EventServiceProvider');

        return $this->make('events');
    });
}

Source at the time of this writing: https://github.com/laravel/lumen-framework/blob/5.8/src/Application.php

Hope this helps others in the future. This took me lots of hours.

captainskippah
  • 1,350
  • 8
  • 16