Adldap2 / Adldap2-Laravel

LDAP Authentication & Management for Laravel
MIT License
911 stars 184 forks source link

Return value of Adldap\Laravel\Resolvers\UserResolver::getAppAuthProvider() must implement interface Illuminate\Contracts\Auth\UserProvider, null returned #691

Open saabarukyatto opened 5 years ago

saabarukyatto commented 5 years ago

Hi, I'm having a weird behavior with the Auth attempt method and adldap with 0 google search results.

So to begin what I need is check written credentials in an API controller function to make sure that the request was indeed posted by the legitimate owner of the logged in account.

To do that I need to attempt a login when already authenticated by the API guard.

I initially tried Auth:attempt($credentials); (Worked before implementing the adldap module) but for some reason now does not exist anymore.

So after looking online I found this method to call the web guard to attempt the login: Auth::guard('web')->attempt(['username' => <username>, 'password' => <password>], false, false);

But I'm getting this weird error message:

Return value of Adldap\Laravel\Resolvers\UserResolver::getAppAuthProvider() must implement interface Illuminate\Contracts\Auth\UserProvider, null returned

What I am doing wrong ? The ldap module works flawlessly apart from this quirk.

-S

stevebauman commented 5 years ago

Hi @saabarukyatto,

I'm not sure I understand your issue. You mention:

So to begin what I need is check written credentials in an API controller function to make sure that the request was indeed posted by the legitimate owner of the logged in account.

So you're trying to authenticate a user that is already logged into your application via the api guard?

I'll need to see your full code and your config/auth.php file to help you further.

saabarukyatto commented 5 years ago

Hi,

my auth.php is as follows :

return [

    /*
    |--------------------------------------------------------------------------
    | Authentication Defaults
    |--------------------------------------------------------------------------
    |
    | This option controls the default authentication "guard" and password
    | reset options for your application. You may change these defaults
    | as required, but they're a perfect start for most applications.
    |
    */

    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],

    /*
    |--------------------------------------------------------------------------
    | Authentication Guards
    |--------------------------------------------------------------------------
    |
    | Next, you may define every authentication guard for your application.
    | Of course, a great default configuration has been defined for you
    | here which uses session storage and the Eloquent user provider.
    |
    | All authentication drivers have a user provider. This defines how the
    | users are actually retrieved out of your database or other storage
    | mechanisms used by this application to persist your user's data.
    |
    | Supported: "session", "token"
    |
    */

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'passport',
            'provider' => 'users',
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | User Providers
    |--------------------------------------------------------------------------
    |
    | All authentication drivers have a user provider. This defines how the
    | users are actually retrieved out of your database or other storage
    | mechanisms used by this application to persist your user's data.
    |
    | If you have multiple user tables or models you may configure multiple
    | sources which represent each model / table. These sources may then
    | be assigned to any extra authentication guards you have defined.
    |
    | Supported: "database", "eloquent" and now ldap
    |
    */

    'providers' => [
        'users' => [
            'driver' => 'ldap',
            'model' => App\User::class,
        ],
        //'users' => [
        //    'driver' => 'database',
        //    'table' => 'users',
        //],
    ],

    /*
    |--------------------------------------------------------------------------
    | Resetting Passwords
    |--------------------------------------------------------------------------
    |
    | You may specify multiple password reset configurations if you have more
    | than one user table or model in the application and you want to have
    | separate password reset settings based on the specific user types.
    |
    | The expire time is the number of minutes that the reset token should be
    | considered valid. This security feature keeps tokens short-lived so
    | they have less time to be guessed. You may change this as needed.
    |
    */

    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
        ],
    ],

];

And here's an abbreviated version of the function in which I stumbled upon the issue :

public function mycCriticalFunction(Request $request){

      //Check that the user has a minimum right level
      if(Auth::user()->right_level < XXX){

        //Log that illegal attempt

        //Return error that the user rights are insufficient
        return response()->json([
            'status' => 'FAIL',
            "message" => "Your account doesn't have the rights."
        ]);

      }

      //get parameters
      $parametersRequest = json_decode($request->getContent(),true);

      //Try to log in to make sure the actual owner of the account is sending the request (If the page is left open on the admin's laptop and he's away we don't want someone to just trigger the function)
      $authenticatedUser = Auth::guard('web')->attempt(['username' => $parametersRequest ['username'], 'password' => $parametersRequest ['password']], false, false);

      //If authentication attempt failed
      if(!$authenticatedUser){

        //Return error
        return response()->json([
            'status' => 'FAIL',
            'message' => 'Bad credentials.'
        ]);

      }

      //More checks

      //The active parts of the function

      //Return Success
      return response()->json([
          'status' => 'OK'
      ]);

    }

As you can see we are in the API and the user is authenticated by its guard. What i want to do is force the user to provide his credentials anyway since its a critical function.

And as said in my previous post, I'm getting this weird error message:

Return value of Adldap\Laravel\Resolvers\UserResolver::getAppAuthProvider() must implement interface Illuminate\Contracts\Auth\UserProvider, null returned

Why can't I "attempt()" in this context ?

stevebauman commented 5 years ago

Hi @saabarukyatto, that's strange. The UserResolver::getAppAuthProvider() method is supposed to return your default guard provider, but it seems to be returning null...

Can you try calling dd(Auth::guard()->getProvider()) at the top of your function you posted above and let me know what is returned?

saabarukyatto commented 5 years ago

I'm getting "null" and nothing else.

stevebauman commented 5 years ago

Strange... Something isn't configured correctly, because it should return your default guards provider.

Can you try flushing your config cache using php artisan config:clear?

Also, this seems to be an API controller? What middleware is being applied to this controller?

saabarukyatto commented 5 years ago

Hi, sorry for the late reply.

I tried flushing the cache and it did not change the outcome of the dd(Auth::guard()->getProvider()) command.

The controller is indeed an API controller. The middleware used is passport.

MattApril commented 5 years ago

Did you ever figure this out? I just started my own attempt at using Passport and Adldap as well, and ran into this issue.

saabarukyatto commented 5 years ago

Here's how I solved it.

//Try to log in
$authenticatedUser = Adldap::auth()->attempt($parametersRequest['username'],$parametersRequest['password'], false, false);

//If authentication attempt failed
if(!$authenticatedUser){

    //Error

}

Don't forget to

use Adldap\Laravel\Facades\Adldap;