tymondesigns / jwt-auth

🔐 JSON Web Token Authentication for Laravel & Lumen
https://jwt-auth.com
MIT License
11.23k stars 1.55k forks source link

laravel 5.3 + Tymon\JWTAuth = How to create token with own authentication #851

Open Rah1x opened 7 years ago

Rah1x commented 7 years ago

Im building a Restful api, except that I DONT want to use Laravel's User authentication model (instead I use my own).

So im on stuck here:

$this->jwt_token = JWTAuth::attempt(['email'=>$email, 'pass'=>$pass])

which gives me the following 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 **\vendor\laravel\framework\src\Illuminate\Auth\SessionGuard.php on line 387

So how do I solve this? any idea? Thanks

jrosczyk commented 7 years ago

Here's a basic way:

Create token

$customClaims = ['fruit' => 'apple', 'herb' => 'basil'];
$payload = JWTFactory::make($customClaims);
$token = JWTAuth::encode($payload);
return redirect('http://someurl?token='.$token);

Authenticate token

$token= $request->id;
JWTAuth::setToken($token);

try { 
    if (! $claim = JWTAuth::getPayload()) {
        return response()->json(array('message'=>'user_not_found'), 404);
    }
} catch (\Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {
    return response()->json(array('message'=>'token_expired'), $e->getStatusCode());
} catch (\Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {
    return response()->json(array('message'=>'token_invalid'), $e->getStatusCode());
} catch (\Tymon\JWTAuth\Exceptions\JWTException $e) {
    return response()->json(array('message'=>'token_absent'), $e->getStatusCode());
}

// the token is valid and we have exposed the contents
return response()->json(array('message'=>'success', 'fruit'=>$claim['fruit'], 'herb'=>$claim['herb']));
francisrod01 commented 7 years ago

There's a problem because JWTAuth::setToken() should not be called statically.

smarques84 commented 7 years ago

@francisrod01 So whats the correct way to achieve such scenario? I also need to this since the database i am connecting is already has a users table with different column names and hashing algorithm for the password so i would like to avoid using Eloquent and authenticate the user my self and generate the token of that.

@jrosczyk Where does the authenticate token code goes in lumen? I known the create token is on the "AuthController.php"

If there is a good tutorial on this please provide a link

jrosczyk commented 7 years ago

@smarques84 The authenticate token code can also go in the controller as a new function, or be middleware, or even go in the route... it all depends on how you want to set it up.

Basically... the user pings your app, and your app generates the data and encodes it in a jwt token, then returns it to them in the header, json, or url. They then are responsible to retrieve your token and pass it back to you (within a minute). Then your app decodes the token (to retrieve the data) and returns the data as json.

Create token

Route

Route::get('produce/all', 'ProduceController@all');

Produce Controller
public function all() {
  $customClaims = Produce::all();
  $payload = JWTFactory::make($customClaims);
  $token = JWTAuth::encode($payload);
  return response()->json([
    'token' => $token
  ]);
}

Authenticate token

Route

Route::get('token/{id}', function () {})->middleware('verify.jwt');

Verify Middleware
$token= $request->id;
JWTAuth::setToken($token);

try { 
    if (! $claim = JWTAuth::getPayload()) {
        return response()->json(array('message'=>'user_not_found'), 404);
    }
} catch (\Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {
    return response()->json(array('message'=>'token_expired'), $e->getStatusCode());
} catch (\Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {
    return response()->json(array('message'=>'token_invalid'), $e->getStatusCode());
} catch (\Tymon\JWTAuth\Exceptions\JWTException $e) {
    return response()->json(array('message'=>'token_absent'), $e->getStatusCode());
}

// the token is valid and we have exposed the contents
return response()->json($claim);
smarques84 commented 7 years ago

@jrosczyk Thanks for answering the problem is that i am having an hard time trying to implement this scenario. The only example/tutorial with jwt that i tried and works with default config is this one: https://github.com/krisanalfa/lumen-jwt

The problem is trying to adapt that project to avoid using eloquent and needing the Laravel Users table created on the Microsoft database. Following your tutorial i can generate the token. But when i try to authenticate with the token i get the following error with jwt engine set to "database" in config/auth.php

"message": "Undefined index: table"

And this one with jwt engine set to default "eloquent": lumen_jwt.users' doesn't exist (SQL: select * fromuserswhereusers.id= 0 limit 1)"

This is driving me crazy!

jrosczyk commented 7 years ago

I believe you will still need to have a model class for your users table, even if it is different than the Laravel/Lumen setup. You'll also need to specify the location of your User model and how to find the user within the table in the config/jwt.php file.

Maybe https://github.com/tymondesigns/jwt-auth/issues/184 will help.

zulfaqarzahri commented 6 years ago

You need to use fromUser()

$user = Auth::user();
$customClaims = ['foo' => 'bar', 'baz' => 'bob'];
$token = JWTAuth::fromUser($user, $customClaims);

then just return $token

mwleinad commented 4 years ago

Is this even possible with the new version 1.0? JWTAuth::fromUser; is not taking $customClaims and JWTFactory::make($customClaims); is only taking a boolean :/

thanks

I actually found the solution mere minutes after I posted.

//Working with the newest release
JWTFactory::customClaims($customClaims);
$payload = JWTFactory::make($customClaims);
$token = JWTAuth::encode($payload);
stale[bot] commented 3 years ago

Is this still relevant? If so, what is blocking it? Is there anything you can do to help move it forward?

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.