Jwt-auth: Auth methods not working with sentinel on laravel 5.5

Created on 30 Nov 2017  路  22Comments  路  Source: tymondesigns/jwt-auth

Unfortunately I'm getting error:
Type error: Argument 1 passed to Illuminate\Auth\EloquentUserProvider::validateCredentials() must be an instance of Illuminate\Contracts\Auth\Authenticatable, instance of App\User given, called in /vagrant/Code/vendor/laravel/framework/src/Illuminate/Auth/SessionGuard.php on line 379

I've tried some solutions from the web, like for example changing:

'auth' => Tymon\JWTAuth\Providers\Auth\Sentinel::class,

But unfortunately none of them helped.
Would be really glad to know how to handle this problem....

Most helpful comment

@llioor thanks for the hint.
Actually I did that before and googled and unfortunately have not found a solution yet.
Maybe you will see something in my LoginController, where I get errors from...

namespace App\Api\V1\Controllers;

use Symfony\Component\HttpKernel\Exception\HttpException;
use Tymon\JWTAuth\JWTAuth;
use App\Http\Controllers\Controller;
use App\Api\V1\Requests\LoginRequest;
use Tymon\JWTAuth\Exceptions\JWTException;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Auth;

class LoginController extends Controller
{
    /**
     * Log the user in
     *
     * @param LoginRequest $request
     * @param JWTAuth $JWTAuth
     * @return \Illuminate\Http\JsonResponse
     */
    public function login(LoginRequest $request, JWTAuth $JWTAuth)
    {
        $credentials = $request->only(['email', 'password']);
        try {

            $token = Auth::guard()->attempt($credentials);
//            dd($token);
            if(!$token) {

                throw new AccessDeniedHttpException();
            }

        } catch (JWTException $e) {

            throw new HttpException(500);
        }

        return response()
            ->json([
                'status' => 'ok',
                'token' => $token,
                'expires_in' => Auth::guard()->factory()->getTTL() * 60
            ]);
    }
}

Btw I get $token=TRUE instead of real value via dd in this code. And the code errors in response() where factory method is invoked...

All 22 comments

Make sure you are implementing "Illuminate\Contracts\Auth\Authenticatable" and using "Illuminate\Auth\Authenticatable"

1264

use Illuminate\Notifications\Notifiable;
use Illuminate\Auth\Authenticatable;
use Cartalyst\Sentinel\Users\EloquentUser;
use Tymon\JWTAuth\Contracts\JWTSubject as AuthenticatableUserContract;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;

class User extends EloquentUser implements AuthenticatableUserContract, AuthenticatableContract
{
    use Notifiable, Authenticatable;

Thanks for the hint @llioor, it is working now in my test env with sentinel, dingo, jwt and laravel 5.5.
So you were absolutely right, about this...
Now I need to figure out, why do I get 500 with "Method factory does not exist." while invoking "Auth::guard()->factory()->getTTL()" , but that's definitely another topic....

@chilio with pleasure... we have to help each other ;)
About ur new issue, try to search online... try to use composer dump-autoload and try again.

@llioor thanks for the hint.
Actually I did that before and googled and unfortunately have not found a solution yet.
Maybe you will see something in my LoginController, where I get errors from...

namespace App\Api\V1\Controllers;

use Symfony\Component\HttpKernel\Exception\HttpException;
use Tymon\JWTAuth\JWTAuth;
use App\Http\Controllers\Controller;
use App\Api\V1\Requests\LoginRequest;
use Tymon\JWTAuth\Exceptions\JWTException;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Auth;

class LoginController extends Controller
{
    /**
     * Log the user in
     *
     * @param LoginRequest $request
     * @param JWTAuth $JWTAuth
     * @return \Illuminate\Http\JsonResponse
     */
    public function login(LoginRequest $request, JWTAuth $JWTAuth)
    {
        $credentials = $request->only(['email', 'password']);
        try {

            $token = Auth::guard()->attempt($credentials);
//            dd($token);
            if(!$token) {

                throw new AccessDeniedHttpException();
            }

        } catch (JWTException $e) {

            throw new HttpException(500);
        }

        return response()
            ->json([
                'status' => 'ok',
                'token' => $token,
                'expires_in' => Auth::guard()->factory()->getTTL() * 60
            ]);
    }
}

Btw I get $token=TRUE instead of real value via dd in this code. And the code errors in response() where factory method is invoked...

Same issue here. After upgrading to Laravel 5.5 and jwt 1.0.0-rc1
:(
I get an error... factory doesn't exist.
If I change Auth::guard()->factory()->getTTL() to a number (random), all works.
WEIRD. Any idea?

@pbvarsok please note that token is not right also, $token = TRUE (absolutely wrong, and causes security flaws).
So this is definitely no go for production....

I know.. Im just saying that I have a problem with that... the factory() method... I will not go in production with that.

I have finally solved this problem, with tips from @llioor.
Use use Illuminate\Support\Facades\Auth; in your controllers to get more info in your ide.
Unless you change your defaults in config/auth.php, which in my case needed to be web, you'll need to select the proper guard ('api') in all of your api controllers, in order for this to work.
You can achieve this by Auth::guard('api')->...
Otherwise, just change the defaults to api and everything should work right out of the box.

I'm also getting the 'Method factory does not exist.' exception when trying to log in with Postman.

In my project I'm using a custom guard called 'admins'. Might that be the cause of the problem?

Yes definetely.
You should change it in all your api controllers to Auth::guard('api')->logout(); for example

Thanks! That fixed it. :)

Thanks, changing to 'api' guard fixes it.

But I would actually like to use 'web' guard. So how is this possible?

@simplenotezy for api routes you need to use 'api' guard.
You need to define separate routes for web and api, since you cannot use both guards on the same route.

If you're _still_ having trouble with Method factory does not exist,

try adding in api into the respondWithToken method in AuthController:

        return response()->json([
            'access_token' => $token,
            'token_type' => 'bearer',
            'expires_in' => auth('api')->factory()->getTTL() * 60
        ]);

A closer look reveals in the Laravel framework that auth() does accept an argument with an appropriate guard if given one:

https://github.com/laravel/framework/blob/6a5eb9023b1353abdb36d52d5e6ae3290f477af1/src/Illuminate/Foundation/helpers.php#L148-L155

Hey,

Sorry to message on a closed issue - but I followed the instructions of adding Auth::guard('api')

But now get the error "message": "Cannot use Auth as Auth because the name is already in use", "exception": "Symfony\\Component\\Debug\\Exception\\FatalErrorException",

@naknode but in that case, you will not get access token, you will get a boolean value for access token, any solution for that?

@PrafullaKumarSahu Not sure. But you can take a look at this project where I have that solution: http://github.com/delaford/website

@naknode, Thank you so much for your kind help.

I am able to make both API and web work now, but if I am changing

Route::group([

    'middleware' => 'api',
    'prefix'     => 'auth',

], function ($router) {
    Route::post('login', 'Auth\AuthController@login');
    Route::post('logout', 'Auth\AuthController@logout');
    Route::post('refresh', 'Auth\AuthController@refresh');
    Route::post('me', 'Auth\AuthController@me');
});

to

Route::group([

    'middleware' => 'api',
    'prefix'     => 'auth',

], function ($router) {
    Route::post('login', 'Auth\AuthController@login');
    Route::post('logout', 'Auth\AuthController@logout');
    Route::post('refresh', 'Auth\AuthController@refresh');
    Route::middleware('auth')->post('me', 'Auth\AuthController@me');
});

It is giving me response "unauthenticated", but I want to retrieve the records only when user is authenticated, how this will work.

@naknode
Changing Route::middleware('auth')->post('me', 'Auth\AuthController@me');to Route::middleware('jwt.auth')->post('me', 'Auth\AuthController@me'); solves the problem. If it is not the correct way, please let me know, how I should progress.

@PrafullaKumarSahu Not sure why you changed the last to have middleware('auth') since it's all covered. It should be either GET/POST and then you should have your appropriate guard.

@naknode I was getting unauthenticated for auth middleware, Could you please tell me, what I should have done there?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

johncloud200 picture johncloud200  路  3Comments

hfalucas picture hfalucas  路  3Comments

gamelife1314 picture gamelife1314  路  3Comments

kofi1995 picture kofi1995  路  3Comments

marciomansur picture marciomansur  路  3Comments