jsonwebtoken decode returns null - node.js

using jsonwebtoken
https://www.npmjs.com/package/jsonwebtoken
var jwt = require('jsonwebtoken');
var token = httpResponse.headers["x-authorization-bearer"].trim();
var decoded = jwt.decode(token);
console.log(token); // eyJ0eXAiOiJKV1QiLCJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.WTMwOGJudHBDTVM3Rm52clBPOGFPUQ.UbXYtb5KppbGYn3AkyOkCg.ljnC5I8q3qThn-NHY6qBqkFhSS9hNiR_pviIFB1zNVmp5Z2wOx0MON2sWRsDF__uSJ-PdI7QaM6djdflbTvKyPWbtKV6g_VDOU-lF6XKMI96BMK41mmBiJSNyDNxE5hqB4X_qWeCYMif8tf583bcKvkrxyuUTsRwvR2Xdo6yl9dyapYGhvKar2TtogOR9-jlFADfPL07ih0YjPYTo2gAWGzrVR6tNuyoRJolYd0ixon5nZ1aP5TdcbPrNcWmGfmuIfWN12BdiEtfrVYDNV7xwmNWfuxke0Uev5VAlIATg_U.1X6R6y9IK3n8NAexswUQKQ
console.log(decoded); // null

The JWT you've given has 4 . characters, but according to jwt.io:
JSON Web Tokens consist of three parts separated by dots (.), which are:
Header
Payload
Signature
Therefore, a JWT typically looks like the following.
xxxxx.yyyyy.zzzzz
The decode function in jsonwebtoken first calls out to a decode function in jws, which validates against the following RegEx:
/^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/
Given that your token contains 4 . characters, this validation fails and returns null, which propagates up to your call site.

If you are trying to instantiate the JSON Web token you wont get the unique token value.In fact you may end up with {} empty inject.
We can make use of the jsonwebtoken in below fashion.
eg. const token = jwt.sign(payload,SECRET_KEY,{algorithm,expireIn})

Related

Generate a JWT in Node using inputs like jwt IO

I have a header, payload, and a public/private key. I can plug these all into JWT.io and it works as expected, but I'm struggling how to use these same variables with a node library like jsonwebtoken or other similar options. They seem to take a secret and sign a payload as far as I can see, which doesn't seem to line up with my inputs. I need to dynamically generate this token request so I must have the function in Node.
Thanks for any tips.
Have a look at the jsonwebtoken NPM package, which offers amongst other methods, a sign method:
var jwt = require('jsonwebtoken');
var privateKey = fs.readFileSync('private.key');
var payload = { foo: 'bar' };
var token = jwt.sign(payload, privateKey, { algorithm: 'RS256' });
As #jps has pointed out, you need the private key to sign and the public key to verify.
The header will be automatically generated and will include both properties (alg and typ) you have mentioned in your comment. You can add additional properties by passing them in the options.header parameter.
I'm struggling how to use these same variables with a node library
import * as jose from 'jose';
const privateKey = await jose.importPKCS8(privateKeyPEM); // private key just like on jwt.io
const jwt = await new jose.SignJWT(payload) // payload just like on jwt.io
.setProtectedHeader(header) // header just like on jwt.io
.sign(privateKey);
Of course there's more to be discovered if you need it.

How to check JsonWebToken (JWT) in Headers?

I have a middleware to protect a route. And I am checking whether the token is present in headers or not??
if(req.headers.authorization && req.headers.authorization.startsWith('Bearer')){
token = req.headers.authorization.split(" ")[1]
}
*My Question is is it necessary to add something like already did in above code by adding Bearer? is it something that enhance token presence checking or it is just a way.
i think this way should also work
if(req.headers.authorization){
token = req.headers.authorization
}
What will be the difference between these two?
What will be the difference between these two?
if(req.headers.authorization && req.headers.authorization.startsWith('Bearer')){
token = req.headers.authorization.split(" ")[1]
}
It will check if the authorization header exits and assign the authorization string including bearer with it and you need to segregate it first to verify the token
if(req.headers.authorization){
token = req.headers.authorization
}
It will check the authorization exists or not and if it does, it includes the Bearer. It is fine to check, however, not needed unless you follow same approach for all the APIs
You should do this:
const jwt = require('jsonwebtoken');
const verifyToken = async (req, res, next) => {
const { authorization } = req.headers;
const token = authorization.split(' ')[1];
try {
const jt = await jwt.verify(token, 'key');
//do something
} catch (error) {
res.status(401).send("Unauthorized");
}
}
module.exports = verifyToken;
1. The difference between the 2 code.
The 2 codes have the same objective: get the JWT in the header Authorization. They will behave differently based on the way you send the JWT in the request.
2. Explain
Usually, we send the JWT token to the server by using Bearer Authentication. In this mode :
The client must send this token in the Authorization header when
making requests to protected resources:
Authorization: Bearer [[token]]
(Source : https://swagger.io/docs/specification/authentication/bearer-authentication/)
So, to retrieve the token from the request, we must :
Firstly, ensure that the request has the Authorization header in the right format
Secondly, split the authorization header by space, and the token is the second element of the array.
That is what the first version does.
(Note: It should check whether the header contains a space or not before splitting the string
if(req.headers.authorization && req.headers.authorization.startsWith('Bearer ')){
token = req.headers.authorization.split(" ")[1]
}
)
3. Conclusion
The first version is based on a popular standard and should be use with a small modification :)

Storing an array in a cookie in nodeJS

I was wondering if it is possible to store an array in a cookie in nodeJS. For example I can set a cookie using the following code res.cookie('Name', "John", { maxAge: 900000});. My question is it possible to store and array of names instead of one name. For example res.cookie('Name', ["john","mark"], { maxAge: 900000});
No, you can't. But you can do something better: store the array in a Json Web Token (JWT).
A JWT is a token in which you can store information in JSON format. You can do it this way:
var jwt = require('jsonwebtoken');
var token = jwt.sign({ Name: ["john","mark"] }, 'YOUR-SECRET-KEY');
Now you have your array of names inside the token variable (and encrypted with your secret key). You can put this token in a cookie:
res.cookie('jwt', token, { maxAge: 900000});
And the user can't edit the cookie information without knowing the secret key you used on the server to create the token.
When you want to decode the information from the token on the user's cookies, you just have to do:
var decoded = jwt.verify(req.cookies.jwt, 'YOUR-SECRET-KEY');
console.log(decoded.Name)
//output: ["john","mark"]
Here is the npm package. Surely you can just encrypt your cookies with any other method, but the pro point of using JWT is that you can store the information like a simple JSON. And then send the token on the cookie.

nodejs jsonwebtoken verify error with some tokens

I've got a java service that generates json web tokens signed with RS256.
Then a service in node verifies the tokens with the public key using the jsonwebtoken module.
The problem is that some tokens work and some do not. According to jwt.io every token is correct.
This an example code with a working one and a failing one
var sanitize = function(data){
return data.replace(/\+/g, '-').replace(/\//g, '_').replace(/=*$/g, '')
}
var jwtGood = sanitize("eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1c2VybmFtZSI6InBlbGF5by11c2VybmFtZTMiLCJlbWFpbCI6InBlbGF5by5yYW1vbisxMkBjbG91ZGRpc3RyaWN0LmNvbSIsInJvbGVzIjpbIlJPTEVfVVNFUiJdLCJpZCI6InVhb2V1YW9lb2FldTMiLCJpYXQiOjE0NTYxNDkwMjR9.tmvgtpuyuUiql2aYeR38kGTeQUwyb7XZr6Df2iv09_nxDn4HltHZm7Fvbj07ZQ5Hh_DmvlqZHz7EVSV6mERdjkohxf8tt9-J6NW_ftnUurCfLIzCcqEJ4xlKOzIgGsGrRd4ZUhw2hs4ZNTIscUb37csvKV-jPdSdQ-TxzuWZen4QnEUGvyg0VhdlU90TGZmpzobfpbHMQ3C0qhGRDMjghgej8zjWHbRDFRIGtAHLDbYVMiQRdI_GODIco2uSVh0_9PATSeRhFosHf3P3R4ohyBMrn9rxmBW4bQyFEMXWtsl4_PrKsdsaTtKjVQ2YuL5GjKQJqkWp6vx2vIxRabHz7w==");
var jwtBad = sanitize("eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1c2VybmFtZSI6InBlbGF5by11c2VybmFtZSIsImVtYWlsIjpudWxsLCJyb2xlcyI6WyJST0xFX1VTRVIiXSwiaWQiOm51bGwsImlhdCI6MTQ1NjMwMTUwN30=.X_vogPRHoE-ws2DxB8Q3wlm5JCQdOvuedhUC-1BlGa9qPdg5nmAGLoLuuGmQZ9r2yUD45OqKQ8_PVd05b0gQBhlIIWtQsXMSWypN6o43noZqMG6aM-GeAK-edDg2C7zw0yGQDD1BNLKBeWc8lNPzJAqQV0il_lg6bytIeN2LMAgxj78RZro3snkXN4woe6afCefW78z3KiOIQ2qI3pcA6Kf4j9NErHwfe9BP2dnV3mXTOZ8SIds_C9JWb7nt9o6Z4oCpskmXxhRCpP4ptTS0krGKfzfhYMKj2e7uOwS1pV4MdpQBeLlhZaGn3pmG5kwl3ZzEeIANfE7N8a9LofmFsQ==");
var jsonwebtoken = require('jsonwebtoken');
var fs = require('fs');
var pubKey = fs.readFileSync('public.pem');
console.log(jwtGood);
jsonwebtoken.verify(jwtGood, pubKey,{ algorithms: ['RS256'] },function(err, decoded){
console.log(err,decoded);
});
console.log(jwtBad);
jsonwebtoken.verify(jwtBad, pubKey,{ algorithms: ['RS256'] },function(err, decoded){
console.log(err,decoded);
});
The main difference just by looking at them is the "=" character at the end of the encoded payload. Working one payload ends in "MjR9." and failing one in "wN30=."
Removed the "=" by hand (as i did with the ending ones) but, according to jwt.io, without it the token is not verified.
Tried some more sanitize functions but they didn't work.
My guess is that there is a base64 encoding issue here but I can't find it.

Decrypt or Validate Signature on Azure Mobile Services Token on the server side

After following the guide for creating a custom identity provider for azure mobile services I can easily generate the appropriate tokens. The code is pretty simple and looks like this:
var userAuth = {
user: { userId : userId },
token: zumoJwt(expiry, aud, userId, masterKey)
}
response.send(200, userAuth);
The definitions for the parameters and code for zumoJwt are located at the link. Azure automatically decodes the token and populates the user on the request object which is what I'd like to simulate.
Basically I'd like to to decrypt the token on the serverside via Node (not .net).
What I ended up doing to validate the token is the following (boiled down). This seems to be about what the azure mobile services is doing on routes that require authorization.
var jws = require('jsw'); // https://github.com/brianloveswords/node-jws
function userAuth() {
var token = ''; // get token as header or whatever
var key = crypto.createHash('sha256').update(global.masterKey + "JWTSig").digest('binary');
if (!jws.verify(token,key)) {
// invalid token logic
} else {
var decode = jws.decode(token)
req.user = {
userId: decode.payload.uid.split(';')[0].split('::')[0]
};
next();
}
}
app.use(authChecker);
The tokens aren't really encrypted - they're just signed. The tokens have the JWT format (line breaks added for clarity):
<header>, base64-encoded
"."
<envelope>, base64-encoded
"."
<signature>, base64-encoded
If you want to decode (not decrypt) the token in node, you can split the value in the . character, take the first two members, base64-decode them (var buffer = new Buffer(part, 'base64')), and convert the buffer to string (buffer.toString('utf-8')).
If you want to validate the token, just follow the same steps you need to re-sign the first two parts of the token (header + '.' + envelope) with the master key, in the same way that the token was created, and compare it with the signature you received on the original token.

Resources