Jwt-auth: Problem with authentication

Created on 17 Jul 2015  路  20Comments  路  Source: tymondesigns/jwt-auth

Hi,
I have a problem using following code:

   public function authenticate(Request $request)
{
    $credentials = $request->only('email', 'password');     

    try {
        // verify the credentials and create a token for the user
        if (! $token = JWTAuth::attempt($credentials)) {
            return response()->json(['error' => 'invalid_credentials'], 401);
        }
    } catch (JWTException $e) {
        // something went wrong
        return response()->json(['error' => 'could_not_create_token'], 500);
    }

    // if no errors are encountered we can return a JWT
    return response()->json(compact('token'));
}

Im sending the login data via POST. The user account exists in the database. I can echo the login data in the function. For any reason I dont know, I can not authenticate, it always throws 401.
Can you please provide me a solution for that? Or any workaround?

Im using laravel 5.1._, jwt-auth 0.5._ and Apache 2.2.22 (Debian)

Best regards,
Oliver

Most helpful comment

Hey guys,
thanks for the help. What you mentioned brought me on the right track. Im building a new authentication from scratch without migrations of any existing users. So what I did for testing was to create users with non hashed passwords in the database, e.g. username: test, password: 123
It seems like the jwt authentication is just working with the laravel Hash::make function since it hashes the POST password to compare with the password from database. So I had to create a user with a laravel hashed password which worked out perfectly fine. Thanks!

All 20 comments

I had a similar issue when migrating an existing database scheme to use this library. My issue was related to the database scheme differences on the User table. Laravel was Hashing the passwords differently with a longer lenth than my database column was able to hold.

I imagine you have a similar issue that when retrieving from the database it's blowing up.

Here's a couple of things to try:

  1. Inside of app/Http/Kernel.php make sure \App\Http\Middleware\VerifyCsrfToken::class is commented out.
  2. Inside config/jwt.php make sure you have the identifier set to the primary key of your Users table.
'identifier' => 'userid' // default is set to 'id'

If you moved your User model don't forget to also update the _user_ key in config/jwt.php.
'user' => '<your User Model>',

Hey guys,
thanks for the help. What you mentioned brought me on the right track. Im building a new authentication from scratch without migrations of any existing users. So what I did for testing was to create users with non hashed passwords in the database, e.g. username: test, password: 123
It seems like the jwt authentication is just working with the laravel Hash::make function since it hashes the POST password to compare with the password from database. So I had to create a user with a laravel hashed password which worked out perfectly fine. Thanks!

Awesome! Glad you figured it out.

@tymondesigns I'm having a similar issue with @OFranke. I'm using a different model which I have set in jwt.php. However, credentials exist in the database - "vendors" table but JWTAuth::attempt($credentials) keeps returning false.

Kindly help with troubleshooting.

/*
* Authenticates the vendors | login */
public function login (request $request) {
// Gets the vendors credentials from the user's login request
$credentials['mobile_number'] = $request->get('mobile_number');
$credentials['password'] = $request->get('password');

    try {
        // Tries to authenticate vendor
        if (! $token = JWTAuth::attempt($credentials)){
            // authentication fails
            return response()->json(['success' => false], Response::HTTP_UNAUTHORIZED);
        }

    }catch (JWTException $je){
        // something went wrong whilst attempting to encode the token
        return response()->json(['error' => 'could_not_create_token'], 500);
    }catch (TokenExpiredException $e) {

        return response()->json(['token_expired'], $e->getStatusCode());

    } catch (TokenInvalidException $e) {

        return response()->json(['token_invalid'], $e->getStatusCode());

    }


    // Authentication successful; generates token
    return response()->json(compact('token'));

}

Thanks in advance.

If you are using Laravel make sure that the user passwords stored in the database are hashed with the Laravel algorithm.
Also make sure that you defined your custom user table in the laravel config.

Best regards,
Oliver

Thanks for your prompt reponse @OFranke I actually used bcrypt for the password and Config::set('auth.model', 'App\Vendor');
Config::set('auth.table', 'vendors'); sets the model and table. I've checked all I need to do but all it's still not authenticating.

I spent hours trying to figure out the same problem, thanks @OFranke !

After spending hours I have fixed this by defining primary key in the User model class as

protected $primaryKey = 'user_id';

My User table primary key was different than just defining "id".

I am having same problem as @jidesakin . Have been stuck on this for days.

My problems is in retrieving the user from JWT token.

JWTAuth::parseToken()->authenticate();

Is always returning false. When I look in JWTAuth.php I find the authenticate method is using AuthInterface byId() method to authenticate the user, but as I search through my codes, I can find no implementation as to this method.

public function authenticate($token = false)
    {
        $id = $this->getPayload($token)->get('sub');

        if (! $this->auth->**byId($id)**) {
            return false;
        }

        return $this->auth->user();
    }

The implementation of byId() can be found in IlluminateAuthAdapter. It simply calls Auth::onceUsingId(), which is a Laravel function. Are you certain your token has a subject matching a user's ID?

I think that was my problem. I was trying to create a new user with an id of 1. It seems authenticate byId() will look into your db at some point (I don't know, does it?) and try and retrieve this user, which doesn't exist yet. So it will return false.

Thinking this is the source of my problem. Will test with a user in the DB and see if this solves the problem.

Yep, in most cases Auth::onceUsingId($id) calls User::find($id), which will make a DB call to find the user.

You need the user to exist in order to authenticate them. This is true for the base Laravel authentication (how can you log in as a user that doesn't exist?), but even more so for JWTs because they usually only store the user's ID and no other information about them.

Thanks @tdhsmith . Think I have enough info to move forward. Will post solution if/when I find one.

Hello guys,

I would like to share so that others can save a lot of time.

I was using postman to test the API. The password I entered in the form is not the one being sent to the server.

Postman seemed to be using a cashed password from an earlier session to register the user. So when I tried to log on, it failed all the time.

Postman may have a bug or I misinterpreted the UI. The lesson here is to use different method to test from client-end too.

cheers

Solution...

If your code is correct, then also if your getting output:
{
"error": "invalid_credentials"
}

Just Follow this Steps:---------------

first step check:

dd($request->only('email', 'password')); or dd($credentials);
// output should be like this..

array:2 [
"email" => "[email protected]"
"password" => "test123"
]

second step check:

dd($token);
// output should be:

false

Third step check:

1) Inside of app/Http/Kernel.php make sure App\Http\Middleware\VerifyCsrfToken::class is commented out.
2) Inside config/jwt.php make sure you have the identifier set to the primary key of your Users table.

'identifier' => 'userid' // default is set to 'id'

Last Step Goto: App\Configauth.php

On line number: 70 Change Model Location where your saved model(User)
for example: App\Model\Myuser\User

and

On line number: 71 Change Table Name to what you have set in your model(User)
for example: protected $table = 'my_user';

_'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\Myuser\User::class,
'table' => 'my_user'
],_

It may help you....

I have an issue about changing $primaryKey. After changing primaryKey in User Model to 'user_id, JWT creates a token but cannot authenticate the user as returning 'user_not_found'. When I look up the token, sub value is just my user's id, not user's user_id. Then I changed the jwt-auth\srcconfigconfig.php file identifier from id to user_id. However still in the token, sub is my id column. Why is it not working?
User Model:
protected $primaryKey = 'user_id';

public $incrementing = false;

Config.php:
'identifier' => 'user_id',

@jidesakin I have samme problem, did you find the answer?

The problem causing this is:
In your database your user password is been stored as plain text. Ensure to hash or bcrypt your password before storing in your database.

Hello i'm facing a 401 Unauthorized Error, it worked fine in my localhost environment, then when i uploaded the code to my live server i get the error after authentication and getting the token to use to make api calls. But the confusion is, it works fine in my other domain hosted by another hosting site, ( i used this to test it before uploading to my main hosting site). But now it's uploaded to iPage, i get the 401 error, and it's the exact same code as the one in my other hosting server. Any ideas?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

functionpointdaniel picture functionpointdaniel  路  3Comments

gandra picture gandra  路  3Comments

gamelife1314 picture gamelife1314  路  3Comments

marciomansur picture marciomansur  路  3Comments

shah-newaz picture shah-newaz  路  3Comments