Search code examples
phplaravelrestlaravel-passport

Laravel Passport TokenGuard::__construct() must implement interface


I'm creating a rest api with Laravel and Laravel Passport. I try to access a route protected with the default laravel api auth middleware:

Route::middleware('auth:api')->get('/user', function (Request $request) {
    return $request->user();
});

Route::prefix('auth')->group(function () {
    Route::post('login', 'Auth\ApiAuthController@login');
});

In the request header I pass Authorization: Bearer <my_secret_token> but I get this exception:

Argument 1 passed to Illuminate\Auth\TokenGuard::__construct() must implement interface Illuminate\Contracts\Auth\UserProvider, null given, called in /Users/markusheinemann/Projekte/Lycus/application/vendor/laravel/framework/src/Illuminate/Auth/AuthManager.php on line 162

Here my request header:

{
  content-type: "application/json",
  x-requested-with: "XMLHttpRequest",
  authorization: "********",
  user-agent: "PostmanRuntime/7.13.0",
  accept: "*/*",
  cache-control: "no-cache",
  postman-token: "ebfa3211-958d-4042-ab6a-a488847fc2f7",
  host: "localhost",
  accept-encoding: "gzip, deflate",
  connection: "keep-alive"
}

Here my token creating process:

public function login(LoginRequest $request)
{
    $credentials = $request->only(['email', 'password']);

    if(!Auth::attempt($credentials)) {
        return response()->json(['message' => trans('auth.failed')], 401);
    }

    $token = $request->user()->createToken('Lycus Frontend Client');
    $token->token->save();

    return response()->json([
        'accessToken' => $token->accessToken,
        'expiresAt' => $token->token->expires_at,
    ]);
}

Has anyone an idea why I get this error?


Solution

  • Make sure your user model uses:

    class User extends Authenticatable 
    { 
        use HasApiTokens; 
    }
    

    ---EDIT----

    I have seen that login code in some guides on the internet, I personally think it is better to resend the request to the Passport API and let it login and create the tokens.

    $request->validate([
        'email'    => 'required|string|email',
        'password' => 'required|string'
    ]);
    
    $http = new Client();
    
    try {
        $response = $http->post('/oauth/token', [
            'form_params' => [
                'grant_type'    => 'password',
                'client_id'     => 2,
                'client_secret' => 'secret_key_from_passport_client',
                'username'      => $request->email,
                'password'      => $request->password,
            ]
        ]);
    
        return $response->getBody();
    } catch (BadResponseException $e) {
        return response()->json([], 422);
    }
    

    ---EDIT--- If you move User to other namespace don't forget to change in auth.php

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