JWT gives JsonWebTokenError "invalid token" - node.js

I have used jsonwebtoken for token verification in my Node Application .
Here jwt.sign works perfectly . But when jwt.verify gives following error
"auth": false,
"message": {
"name": "JsonWebTokenError",
"message": "invalid token"
}
}
Here is my Post and Get Router
router.post('/signup',(req,res)=>{
const body = _.pick(req.body,['username','email_id','name','college','password','dob','gender','city','joinedOn','bio']);
User.findOne({'username':body.username},function(err,user){
if(err){
res.status(404).send(err)
}else if(user){
res.status(404).send('User with Username Exists')
}else{
var user = new User(body);
user.save().then((user) => {
var token = jwt.sign({ username: user.username},'secret', {
"algorithm": "HS256",
expiresIn: 86400 // expires in 24 hours
});
res.status(200).send({ auth: true, token: token });
}, (e) => {
res.status(400).send(e)
})
}
})
});
router.get('/me', VerifyToken, function(req, res) {
User.findOne({username:req.username}, function (err, user) {
if (err) return res.status(500).send(err);
if (!user) return res.status(404).send("No user found.");
res.status(200).send(user);
});
});
Below is verifyToken Function
function verifyToken(req, res, next) {
var token = req.headers['x-access-token'];
if (!token)
return res.status(403).send({ auth: false, message: 'No token provided.' });
console.log(token)
jwt.verify(token,'secret', function(err, decoded) {
if (err)
return res.status(500).send({ auth: false, message: err });
//req.username = decoded.username;
console.log(decoded)
next();
});
}
I can't figure out what's wrong in my program .Any suggestions would be appreciated .
Thanks

If you are passing in a token to your jwt.verify function like so Bearer *************...., ensure to split the token first before passing it in to jwt by doing
const token = req.headers.authorization.split(' ')[1];
jwt.verify(token)
Hope this helps someone.

My Code is true . The mistake I was doing that I was giving access token with double quote("token") in Postman. That's why postman was giving me following error
"auth": false, "message": { "name": "JsonWebTokenError", "message": "invalid token" } }

I had the same issue. Basically the token should not have brearer information. When I stripped it out it started working as expected.
For instance:
Failed when I used brearer *************....
Worked when I used *************....

I had a similar error because I persisted the token in localStorage with JSON.stringify, which adds two double quotes to the token, hence resulting in an invalid token when verifying it.
// What caused the error
localStorage.setItem('jwt', JSON.stringify(token));
Solution, either omit JSON.stringify, or parse the token when verifying:
localStorage.setItem('jwt', token);
// or
const token = JSON.parse(localStorage.getItem('jwt'));

const token = req.header('token');
try {
const decoded = jwt.verify(JSON.parse(token), privateKey);
console.log(decoded)
} catch(err) {
console.log('err', err)
}

when you pass token from service convert into JSON.parse(token) from local storage then pass to verify

Related

Refreshing JWT access token with refresh token within single middleware function on a post route

I'm trying to learn JWT authentication in express and one thing that I'm came across this code from Github
that this guy has initialised an middleware function to authenticate and check expiry of access token as per below:
app.post("/protected", auth, (req, res) => {
return res.json({ message: "Protected content!" });
})
async function auth(req, res, next) {
let token = req.headers["authorization"];
token = token.split(" ")[1]; //Access token
jwt.verify(token, "access", async (err, user) => {
if (user) {
req.user = user;
next();
} else if (err.message === "jwt expired") {
return res.json({
success: false,
message: "Access token expired"
});
} else {
console.log(err);
return res
.status(403)
.json({ err, message: "User not authenticated" });
}
});
}
and a separate route for refreshing the access token with the help of refresh token
app.post("/refresh", (req, res, next) => {
const refreshToken = req.body.token;
if (!refreshToken || !refreshTokens.includes(refreshToken)) {
return res.json({ message: "Refresh token not found, login again" });
}
// If the refresh token is valid, create a new accessToken and return it.
jwt.verify(refreshToken, "refresh", (err, user) => {
if (!err) {
const accessToken = jwt.sign({ username: user.name }, "access", {
expiresIn: "20s"
});
return res.json({ success: true, accessToken });
} else {
return res.json({
success: false,
message: "Invalid refresh token"
});
}
});
});
So, my question is how secure it is and how can I create single middleware function that could do both authentication and refreshing access token without hitting the app.post('/refresh') as in my view it wouldn't be a smooth experience to deal with it in frontend API management within react
Edit
My middleware seems to work well but it doesn't identify the wrong refresh token and then actually getting worked on protected route
app.post('/home', authenticateUser, (req, res) => {
res.send('welcome');
});
async function authenticateUser(req, res, next) {
let token = req.headers['authorization'];
token = token.split(' ')[1];
jwt.verify(token, JWT_AUTH_TOKEN, async (err, phone) => {
if (phone) {
req.phone = phone;
next();
} else if (err) {
const refreshToken = req.body.refreshToken;
if (!refreshToken || !refreshTokens.includes(refreshToken)) {
return res.json({ message: 'Refresh token not found, login again' });
} else {
jwt.verify(refreshToken, JWT_REFRESH_TOKEN, (err, phone) => {
if (!err) {
const accessToken = jwt.sign({ phone }, JWT_AUTH_TOKEN, { expiresIn: '30s' });
return res.json({ success: true, accessToken });
} else {
return res.json({
success: false,
message: 'Invalid refresh token'
});
}
next();
});
}
} else {
console.log(err);
return res.status(403).json({ err, message: 'User not authenticated' });
}
});
}

Cannot return JWT token [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
I've built this sign in route that creates a JWT token, but outside of the function that creates it, the token is undefined, so I'm unable to use it outside of that function.
router.post('/login', (req, res) => {
const { errors, isValid } = validateLoginInput(req.body);
if (!isValid) {
return res.status(400).json(errors);
}
const email = req.body.email;
const password = req.body.password;
User.findOne({ email }).then(user => {
if (!user) {
return res.status(404).json({ emailnotfound: "Email not found"});
}
bcrypt.compare(password, user.password).then(isMatch => {
if (isMatch) {
const payload = {
id: user.id,
name: user.name
};
var token =jwt.sign(
payload,
keys.secretOrKey,
{ expiresIn: 31556926 },
(err, token) => {
res.json({
success: true,
token: "Bearer " + token
});
});
console.log(token)
} else {
return res.status(400).json({ passwordincorrect:
"Password incorrect"});
}
});
});
});
When the code hits that console.log statement, it shows that the token is undefined instead of returning the token.
It seems you might have a problem with the token being created. The code is not checking if the token got created successfully.
(err, token) => {
res.json({
success: true,
token: "Bearer " + token
})
}
Change this to :
(err, token) => {
if (err){
console.log("Error while creating token:"+err.message);
console.error(err);
//send an error response as well if needed.
} else {
res.json({
success: true,
token: "Bearer " + token
})
}
This will help you figure out what the problem might be.
The problem seems to be here:
var token =jwt.sign(
payload,
keys.secretOrKey,
{ expiresIn: 31556926 },
(err, token) => {
res.json({
success: true,
token: "Bearer " + token
});
});
Can you check the JWT library that you are using to see if it actually accepts a callback? The correct syntax on most JWT libraries for the sign function is:
var token = jwt.sign(payload, secretKey, options);
console.log("Token :" + token);
The options usually contains an expiresIn defined in seconds.

JWT-TypeError: Cannot read property 'id' of undefined

hello i am creating token validation (JWT) and this error came up here is the code
of JWT signing token:
if (user) {
const payload = user._id
console.log(payload)
console.log(process.env.SECRET)
const token = jwt.sign({id :payload}, process.env.SECRET, {
expiresIn: 10
})
console.log(token)
res.cookie('token', token, {
httpOnly: true
});
and verifying it (in middleware)
const token = req.body.token ||
req.query.token ||
req.headers['x-access-token'] ||
req.cookies.token;
if (!token) {
res.status(401).send({auth: false})
}
else{
jwt.verify(token, process.env.SECRET, function (err, decoded) {
if (err){
res.status(500).send({
message: err.message
})
}
req.userId = decoded.id
next()
})
}
i do not know the problem, i think i did everything according to docs but this error still shows up if anyone knows the solving for this problem i would be glad if i hear it thanks!
If jwt.verify fails, you're trying to access decoded.id which does not exist. So issue a return inside if(err) otherwise the code will continue, calling next & trying to access decoded.id, triggering an error.
jwt.verify(token, process.env.SECRET, function(err, decoded) {
if (err) {
return res.status(500).send({
message: err.message
})
}
req.userId = decoded.id
next()
})

checking Jwt token on every request?

I am developing a android aplication with nodejs and postgreSQL, at the moment i just have the login and the register.
When i do a login and everything is fine the server send me a token, that token is stored on the device SharedPreference, now my confusion is, do i need to decode this token on every request, or do i need to do it just 1 time?
in this tutorial at the end, he decodes on every route the token, but i don't need to do that when i do for example a request to register.
What is the best way to implement this?
here is my server code:
//****************************************************Begin of login request **********************************/
router.post('/login', function (req, res, next) {
if (JSON.stringify(req.body) == "{}") {
return res.status(400).json({ Error: "Login request body is empty" });
}
if (!req.body.username || !req.body.password) {
return res.status(400).json({ Error: "Missing fields for login" });
}
// search a user to login
User.findOne({ where: { username: req.body.username } }) // searching a user with the same username and password sended in req.body
.then(function (user) {
if (user && user.validPassword(req.body.password)) {
//return res.status(200).json({ message: "loged in!" }); // username and password match
var payload = { user: user };
// create a token
var token = jwt.sign(payload, 'superSecret', {
expiresIn: 60 * 60 * 24
});
// return the information including token as JSON
res.json({
success: true,
message: 'Enjoy your token!',
token: token
});
}
else {
return res.status(401).json({ message: "Unauthorized" }); // if there is no user with specific fields send
}
}).catch(function (err) {
console.error(err.stack)
return res.status(500).json({ message: "server issues when trying to login!" }); // server problems
});
});
//****************************************************End of Login request **********************************/
//****************************************************Begin of register request******************************/
router.post('/register', function (req, res, next) {
if (JSON.stringify(req.body) == "{}") {
return res.status(400).json({ Error: "Register request body is empty" });
}
if (!req.body.email || !req.body.username || !req.body.password) {
return res.status(400).json({ Error: "Missing fields for registration" });
}
var password = User.generateHash(req.body.password);
User.create({
username: req.body.username,
email: req.body.email,
password: password
}).then(function () {
return res.status(200).json({ message: "user created" });
}).catch(function (err) {
return res.status(400).send({ message: err.message }); //
}).catch(function (err) {
return res.status(400).json({ message: "issues trying to connect to database" });
})
});
//****************************************************End of register request **********************************/
module.exports = router;
If you don't want to use JWT token check for all routes, you can skip those routes.
const url = require('url');
apiRoutes.use((req, res, next) => {
const path = url.parse(req.url).pathname;
console.log(path);
//No JWT token check
if (/^\/register/.test(path)) {
return next();
}
return jwtTokenValidate();
});
function jwtTokenValidate() {
// check header or url parameters or post parameters for token
var token = req.body.token || req.query.token || req.headers['x-access-token'];
// decode token
if (token) {
// verifies secret and checks exp
jwt.verify(token, app.get('superSecret'), function(err, decoded) {
if (err) {
return res.json({ success: false, message: 'Failed to authenticate token.' });
} else {
// if everything is good, save to request for use in other routes
req.decoded = decoded;
next();
}
});
} else {
// if there is no token
// return an error
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
}

Express Middleware jsonwebtoken authentication

My server has a registration api that provides a token after registration, and a middleware that authenticates a user's token. I need to register an account to get the token to do something else with my server. However, the middleware blocks my network request because I don't have a token yet.
So how can I create my account and token in this case? Get pass the middleware with some tricks?
Middleware:
// Middleware to verify token, it will be called everytime a request is sent to API
api.use((req, res, next)=> {
var token = req.headers.token
if (token) {
jwt.verify(token, secret, (err, decoded)=> {
if (err) {
res.status(403).send({ success: false, message: "Failed to authenticate user." })
} else {
req.decoded = decoded
next()
}
})
} else {
res.status(403).send({ success: false, message: "No Token Provided." })
}
})
Signin:
// Sign In with email API
api.post('/signInWithEmail', (req, res)=> {
User.findOne({
email: req.body.email
}).select(userFields).exec((err, user)=> {
if(err) {
throw err
}
if (!user) {
res.send({ message: "User doesn't exist"});
} else if (user) {
var validPassword = user.comparePassword(req.body.password);
if (!validPassword) {
res.send({ message: "Invalid Password"});
} else {
var token = createToken(user);
res.json({
success: true,
message: "Login Successfully!",
token: token
})
}
}
})
})
Make a function to check tokens and expose your routes such that whenever you need to call an authenticated route then you'll be checking the token first and then you'll expose the route.
Sample Code
Let's say this is my check token function
function checkToken(req, res, next) {
var x = req.token; //This is just an example, please send token via header
if (x === token)
{
next();
}
else
{
res.redirect(/unauthorized); //here do whatever you want to do
}
}
Now let's use the function for routes.
app.post('/protectedroute', checkToken, routename.functionname);
app.post('/notprotected', routename.functionname);
It's your call if you'd like to have separate routes for different codes or else you can just call specific code block via keeping them in function etc. on the main file i.e. app.js or server.js, whatever you have chosen.
What actually we are doing here is - we are making a middleware of our own to expose our routes through a channel of code blocks or functions.

Resources