Okay so I'm running laravel 5.2 and trying to generate a token that is valid on a socket.io server. However I seem to fail horrible at this, (not sure if this is a problem with me or this library) so some help would be much appreciated!
On my laravel I have some simple lines:
$user = App\User::find(1);
$token = JWTAuth::fromUser($user);
And then I use this token when making the socket io connection from the client:
var socket = io.connect('http://localhost:8085', {
'query': 'token={{$token}}'
});
Simple socketio server:
var io = require('socket.io')();
var socketioJwt = require("socketio-jwt");
io.use(socketioJwt.authorize({
secret: 'supersecretkey',
handshake: true
}));
io.on('connection', function(socket){
console.log('connected!');
});
io.listen(8085);
console.log('socketio-server listening on *:8085');
However this gives me:
{
message: "invalid signature",
code: "invalid_token",
type: "UnauthorizedError"
}
So I instead of using socketio-jwt library, I also tried interfacing it directly against jsonwebsocket which gives me invalid signature as well.
I use the same key on both places and my jwt.php config file looks like this:
<?php
return [
'secret' => 'supersecretkey',
'ttl' => 60,
'refresh_ttl' => 20160,
'algo' => 'HS256',
'user' => 'App\User',
'identifier' => 'id',
'required_claims' => ['iat', 'exp', 'nbf', 'sub', 'jti'],
'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true),
'providers' => [
'user' => 'Tymon\JWTAuth\Providers\User\EloquentUserAdapter',
'jwt' => 'Tymon\JWTAuth\Providers\JWT\NamshiAdapter',
'auth' => 'Tymon\JWTAuth\Providers\Auth\IlluminateAuthAdapter',
'storage' => 'Tymon\JWTAuth\Providers\Storage\IlluminateCacheAdapter'
]
];
So what am I missing? I also tried to decode the jwt on the https://jwt.io/ website, but that doesn't work either. Help is very much appreciated!
cool story bro
Sorry, I accidentally opened it without context, it's added.
And at some point I also got jwt malformed, just trying to replicate that. But any help would be appreciated.
I just tried another library, https://github.com/lcobucci/jwt and I have no problems generating a token that will get validated from the socketio server.
$signer = new Lcobucci\JWT\Signer\Hmac\Sha256();
$token = (new Lcobucci\JWT\Builder())->setIssuer('http://rpanel.local')
->setIssuedAt(time())
->setNotBefore(time())
->setExpiration(time() + 3600)
->set('uid', 1)
->sign($signer, 'supersecretkey')
->getToken();
Could this be an issue with the underlying namshi/jose library?
No problem.. reopened.. I'll take a look when I can
Could you post an example of a failing JWT with its key?
Sure.
Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJzdWIiOjEsImlzcyI6Imh0dHA6XC9cL3JwYW5lbC5sb2NhbFwvc2VydmVyXC8xIiwiaWF0IjoiMTQ2NTk3NDM4NCIsImV4cCI6IjE0NjU5Nzc5ODQiLCJuYmYiOiIxNDY1OTc0Mzg0IiwianRpIjoiYzdjZTFmN2M0Y2Q5NDExNGQzODZiYjk1OTc0ZWU5YTcifQ.OGVmZjFhMDM4OGViMzVhNjc3NmJjNjM0ZmIyNTFlOTYyYzExOTMzNmI3ZTY4YTZkZGY3OTcyYmRiODg5NGE0OQ
Key: supersecretkey
Edit:
Validating this key as from my understanding should work great over at jwt.io since it uses HS256 encryption. But it fails with invalid signature over there.
Here's a simple validation directly against jsonwebtoken for nodejs that fails:
var jwt = require('jsonwebtoken');
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJzdWIiOjEsImlzcyI6Imh0dHA6XC9cL3JwYW5lbC5sb2NhbFwvc2VydmVyXC8xIiwiaWF0IjoiMTQ2NTk3NDM4NCIsImV4cCI6IjE0NjU5Nzc5ODQiLCJuYmYiOiIxNDY1OTc0Mzg0IiwianRpIjoiYzdjZTFmN2M0Y2Q5NDExNGQzODZiYjk1OTc0ZWU5YTcifQ.OGVmZjFhMDM4OGViMzVhNjc3NmJjNjM0ZmIyNTFlOTYyYzExOTMzNmI3ZTY4YTZkZGY3OTcyYmRiODg5NGE0OQ";
try {
var decoded = jwt.verify(token, 'supersecretkey');
console.log(decoded);
} catch(err) {
console.log(err);
}
Fails with:
{ JsonWebTokenError: invalid signature
at Object.JWT.verify (/home/grenadecx/www/rpanel/server/node_modules/jsonwebtoken/index.js:219:17)
at Object.<anonymous> (/home/grenadecx/www/rpanel/server/rpanel-server.js:50:20)
at Module._compile (module.js:541:32)
at Object.Module._extensions..js (module.js:550:10)
at Module.load (module.js:458:32)
at tryModuleLoad (module.js:417:12)
at Function.Module._load (module.js:409:3)
at Function.Module.runMain (module.js:575:10)
at startup (node.js:160:18)
at node.js:449:3 name: 'JsonWebTokenError', message: 'invalid signature' }
Does this sound like it could be the same as the issue I just submitted, #765?
@grenadecx Ok well I can confirm that jwt.io and jsonwebtoken don't accept it for some reason, but I'm not sure why yet.
I manually verified that the signature _looks_ valid based on the given payload and header, though:
$payload = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJzdWIiOjEsImlzcyI6Imh0dHA6XC9cL3JwYW5lbC5sb2NhbFwvc2VydmVyXC8xIiwiaWF0IjoiMTQ2NTk3NDM4NCIsImV4cCI6IjE0NjU5Nzc5ODQiLCJuYmYiOiIxNDY1OTc0Mzg0IiwianRpIjoiYzdjZTFmN2M0Y2Q5NDExNGQzODZiYjk1OTc0ZWU5YTcifQ';
$hmac = hash('sha256', $payload);
// $hmac == '8eff1a0388eb35a6776bc634fb251e962c119336b7e68a6ddf7972bdb8894a49'
$signature = rtrim(strtr(base64_encode($hmac), '+/', '-_'), '=');
// $signature == 'OGVmZjFhMDM4OGViMzVhNjc3NmJjNjM0ZmIyNTFlOTYyYzExOTMzNmI3ZTY4YTZkZGY3OTcyYmRiODg5NGE0OQ'
// (which is exactly the same as the one in the token you gave, so it should pass)
I did find one big discrepancy: your payload has escaping backslashes before the forward slashes:
// Your payload:
echo(base64url_decode('eyJzdWIiOjEsImlzcyI6Imh0dHA6XC9cL3JwYW5lbC5sb2NhbFwvc2VydmVyXC8xIiwiaWF0IjoiMTQ2NTk3NDM4NCIsImV4cCI6IjE0NjU5Nzc5ODQiLCJuYmYiOiIxNDY1OTc0Mzg0IiwianRpIjoiYzdjZTFmN2M0Y2Q5NDExNGQzODZiYjk1OTc0ZWU5YTcifQ'));
// {"sub":1,"iss":"http:\/\/rpanel.local\/server\/1","iat":"1465974384","exp":"1465977984","nbf":"1465974384","jti":"c7ce1f7c4cd94114d386bb95974ee9a7"}
// The one jwt.io builds from those claims:
echo(base64url_decode('eyJzdWIiOjEsImlzcyI6Imh0dHA6Ly9ycGFuZWwubG9jYWwvc2VydmVyLzEiLCJpYXQiOiIxNDY1OTc0Mzg0IiwiZXhwIjoiMTQ2NTk3Nzk4NCIsIm5iZiI6IjE0NjU5NzQzODQiLCJqdGkiOiJjN2NlMWY3YzRjZDk0MTE0ZDM4NmJiOTU5NzRlZTlhNyJ9'));
// {"sub":1,"iss":"http://rpanel.local/server/1","iat":"1465974384","exp":"1465977984","nbf":"1465974384","jti":"c7ce1f7c4cd94114d386bb95974ee9a7"}
The extra slashes then disappear to javascript because / isn't a metacharacter, which is an important point, but I don't know why this would be relevant during the signature validation. (it should verify the signature of the base64-ed payload directly, not decode it to a string, then reencode it)
I'll prod a little more. Do you know why your iss has backslashes in it though? The default iss comes from request()->url(), which on my machine doesn't have any...
Thanks for taking a look.
I've no idea why I have baskslashes in the url. I mean, I don't do anything funky with it, I'm running the basic configuration file and all I do is the JWTAuth::fromUser function with a user and then insert the token with {{$token}} in the javascript.
How imporant is the iss? Seems like it can basically be anything and still give a valid signature?
Actually I'm thinking the backslash thing was a red herring. The way I calculated the signature was wrong, so it's not a good sign that namshi/jose agreed with me.
iss isn't actually checked by this library's validators, but some services use it to identify where requests are coming from for example. If you're building both ends of the communication, it isn't required by any means. You'd have to take it out of your jwt.required_claims as well as call JWTAuth::factory()->setDefaultClaims to exclude it. But don't do that yet because I don't think that's the problem anymore...
Do you know what version of namshi/jose you have installed? (run composer show namshi/jose)
It's possible you're hitting namshi/JOSE#36. It's been fixed in this library since #126 (i.e. jwt-auth v0.5.4), but it's possible you haven't updated or are running a really old version. (What jwt-auth version _are_ you running by the way?)
The odd thing--and the reason I think that's the issue--is that your signature is the base64url encoded version of the HMAC _hex string_. But you should be taking the base64url of the HMAC's actual _binary value_.
Otherwise it's doing a weird conversion that's basically useless (base64 is mostly about making binary data consumable as text, but hex is already text). It also explains why your signature was weirdly long (base64 is 4x denser than hex, and base64-ing hex makes it another 3/4ths as dense).
Yeah I also found it weird that the token as so long compared to other libraries when generating the same amount of data.
namshi/jose
name : namshi/jose
descrip. : JSON Object Signing and Encryption library for PHP.
keywords : JSON Web Signature, JSON Web Token, JWS, json, jwt, token
versions : * 2.0.3
tymon/jwt-auth
name : tymon/jwt-auth
descrip. : JSON Web Token Authentication for Laravel 4 and 5
keywords : Authentication, JSON Web Token, auth, jwt, laravel, tymon
versions : * 0.5.0
I was using the documentation when installing just a few days ago, but I can try updating to 0.5.4 or whatever the latest is and see if that solves it.
I'll report back in a bit :)
Okay so I updated to tymon/jwt-auth 0.5.9 which updated the namshi/jose to 5.0.2 and it solved my problem.
Not sure why I was using an older version since the documentation says to install 0.5.*. I really appreciate the help and wish ya the best!
Most helpful comment
cool story bro