How to add custom claims?
| Q | A
| ----------------- | ---
| Bug? | no?
| New Feature? | no
| Framework | Laravel
| Framework version | 5.6
| Package version | 1.0.0-rc.2
| PHP version | 7.1.3
Trying to add custom claims to my token:
$token = JWTAuth::attempt($credentials, ['role' => 'test']);
result - not working,
$user = User::first();
$token = JWTAuth::fromUser($user, ['role' => 'test']);
result - not working,
$token = JWTAuth::customClaims(['foo' => 'bar'])->attempt($credentials);
result - not working
this should work
I'm getting user data only.
I believe that in rc2, custom claims must be implemented via the JWTSubject interface in the User model with the getJWTCustomClaims method. That allows for claims on the User model if needed which was not available having it tied to attemptin prior versions.
It is still not working, I've set inside User model:
public function getJWTCustomClaims()
{
return [
'foo' => 'bar',
];
}
and then trying many ways:
$token = JWTAuth::attempt($credentials);
$token = JWTAuth::getPayload();
and it's giving error:
"message": "A token is required",
"exception": "Tymon\\JWTAuth\\Exceptions\\JWTException",
"file": "C:\\www2\\medpraca2\\vendor\\tymon\\jwt-auth\\src\\JWT.php",
"line": 331,
Why there is no documentation how to use it?
I get one step closer, using this:
$user = User::first();
$token = JWTAuth::fromUser($user);
$payload = JWTAuth::setToken($token)->getPayload();
it gives my new $payload, but now I cannot access to user from the token, because calling
http://127.0.0.1:8000/api/auth/user
gives me:
exception:"Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException"
file:"C:\www2\medpraca2\vendor\tymon\jwt-auth\src\Http\Middleware\BaseMiddleware.php"
line:74
message:"Wrong number of segments"
and my header is like:
Authorization: Bearer {"iss":"http://127.0.0.1:8000/api/auth/login","iat":1532569847,"exp":1532571647,"nbf":1532569847,"jti":"efkS4XcSM4llfrAX","sub":1,"prv":"87e0af1ef9fd15812fdec97153a14e0b047546aa","foo":"bar"}
instead of:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vMTI3LjAuMC4xOjgwMDAvYXBpL2F1dGgvbG9naW4iLCJpYXQiOjE1MzI1NzAzNjUsImV4cCI6MTUzMjU3MjE2NSwibmJmIjoxNTMyNTcwMzY1LCJqdGkiOiJ6YklPZjQyM2hTQ2pwZ1l3Iiwic3ViIjoxLCJwcnYiOiI4N2UwYWYxZWY5ZmQxNTgxMmZkZWM5NzE1M2ExNGUwYjA0NzU0NmFhIiwiZm9vIjoiYmFyIn0.gPVIGR_vSC6iAOrfxoVLS2amYdYoETi1FNNShX0j7RU
when I was using simple:
$user = User::first();
$token = JWTAuth::fromUser($user);
$payload = $token;
I made it this way:
$user = User::first();
$token = JWTAuth::fromUser($user);
$payload = JWTAuth::setToken($token)->getPayload();
$newToken = JWTAuth::encode($payload);
return response(['status' => 'success'])->header('Authorization', $newToken);
and this is still not working :disappointed:
only primary user data is available, without 'foo': 'bar', despite adding this to User model
public function getJWTCustomClaims()
{
return [
'foo' => 'bar',
];
}
Why it is not working?
It looks like you are mixing and matching version calls. If you install using"
composer require tymon/jwt-auth:1.0.0-rc.2
... then follow the rest of the installation guide here and quick start here EXACTLY, it should work with any payload. It does for us using Laravel 5.5 or 5.6. If not check the Laravel log and make sure nothing else is going on.
I'm pretty sure I'm doing it correctly (for my level of experience).
As I can see:
Authorization: Bearer {"iss":"http://127.0.0.1:8000/api/auth/login","iat":1532569847,"exp":1532571647,"nbf":1532569847,"jti":"efkS4XcSM4llfrAX","sub":1,"prv":"87e0af1ef9fd15812fdec97153a14e0b047546aa","foo":"bar"}
'foo':'bar' is in correct place (?). Then I encode it and return it to spa app. My plugin is reading user data, but without "foo":"bar".
Maybe there is a problem with websanova/vue-auth plugin that is recovering my token, but I'm not so experienced to check this out...
@gileneusz
I tried this, you write in the User model
public function getJWTCustomClaims()
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email
];
}
with
protected $fillable = [
'id',
'name',
'email',
];
result:

What version of JWT AUth shows in your composer.json file? Also, where and how are you creating and returning the token?
@genyded
"tymon/jwt-auth": "^1.0.0-rc.2",
Do not do anything other than the above
Follow this guide. If you followed the above example, it does not actually invoke Auth which is what sets this. You need to either call attempt() or login() per the guide. There is some stuff in the code above from older versions.
@genyded exactly
Change code in file config/auth.php
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
.....
'guards' => [
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
Login API
public function login(LoginRequest $request)
{
$credentials = $request->only('email', 'password');
try {
if (!JWTAuth::attempt($credentials)) {
return response()->json([
'message' => 'invalid_credentials',
'data' => null
], 401);
}
} catch (JWTException $e) {
return response()->json([
'message' => 'could_not_create_token',
'data' => null
], 500);
}
$user = auth()->user();
$data['token'] = auth()->claims([
'user_id' => $user->id,
'name' => $user->name,
'email' => $user->email,
])->attempt($credentials);
$data['user'] = $user;
return response()->json([
'message' => 'Success',
'data' => $data
]);
}
Have you tested this?
$token = JWTAuth::customClaims(['role' => 'test'])->fromUser($user);
Seems to be the way to go.
I use -v 1.0
You have test :
encode: auth()->claims(['foo' => 'bar'])->login($user);
decode $payload = auth()->payload(); $payload->toArray();
use auth()->userOrFail() only decode $user don`t claims(['foo' => 'bar'])
My english is bad , haha.
@gileneusz
In User Model define method if not
public function getJWTCustomClaims()
{
return ['payload_name' => 'payload_value'];
}
If you want to add some user information to the payload, you can simply add this in the User model:
public function getJWTCustomClaims()
{
return [
'role' => $this->role
];
}
This way you will be able to take and pass user role through the token
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.
If you want to add some user information to the payload, you can simply add this in the User model:
public function getJWTCustomClaims() { return [ 'role' => $this->role ]; }This way you will be able to take and pass user role through the token
Solved the issue for me, even if i don't understand why the customClaims way which is described here is not working (anymore?). It would be a nicer solution in my case as i have mutliple "user" models which all have the same getJWTCustomClaims content (share a global var now).
Most helpful comment
Have you tested this?
$token = JWTAuth::customClaims(['role' => 'test'])->fromUser($user);Seems to be the way to go.