How Pass Token in every Request - node.js

I'm using jsonwebtoken And I want to pass this token in every Request.
Have I set my Token in Session and pass the session with token app.use?
or I have to Store it in Cookie?
Can I Retrieve the logged user by JWT?
I create my Token with
var token = jwt.sign(user, app.get('superSecret'), {
expiresIn: 1440 // expires in 24 hours
});
and Check The Token With
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();
}
});

Related

Add authorization header in nodejs to persist after login securely?

I wanted to know what is the best way to add authorization header in nodejs app so that client req header gets that header set from the server on login. That's, once a user logs in, server should set an authorization header with the token, hence let that header persist on all routes, so that if it is present on the client, the server can allow user to visit routes.
I have seen alot of talk about adding it as a cookie but I prefer authorization header for this scenario. In between I would want to make sure on logout token is destroyed.
I am using JWT, Passport, express, nodejs for this app. Any help would be appreciated.
let access;
/\*\*
* #route POST api/auth/login
* #desc Login user and return token
* #access public
\*/
exports.login = async (req, res, next) =\> {
try {
// Make sure this account exists
const user = await Users.findOne({ email: req.body.email }).select(
'+password',
);
if (!user)
return res.status(401).json({
message: 'Invalid email or password',
});
// Validate password
const validate = await bcrypt.compare(req.body.password, user.password);
if (!validate)
return res.status(401).json({ message: 'Invalid email or password' });
// Make sure user has been verified
if (!user.isVerified)
return res.status(401).json({
type: 'no-verified',
message: 'Your account has not been verified.',
});
const token = user.generateJWT();
access = token;
// Login user, write token, and send back user
const { password, ...data } = user._doc;
res.status(200).json({ hash: token });
} catch (err) {
res.status(500).json({ success: false, message: err.message });
}
};
exports.addHeader = (req, res, next) =\> {
console.log(access);
if (!access) {
console.log('token: undefined');
}
req.headers.authorization = 'Bearer ' + access;
next();
};
// In index.js
app.all('\*', authController.addHeader);
Tried that, could not get it to work.

Node.js JWT refresh token in express middleware

I'm trying to configure a token refresh method in my express middleware in wich the token is validate at every request to the api. I will check if the token expired and if so, I will sign a new token with new exp date. The problem is that I have to send the token again, but doing thatI lose the original request to send the token with the response and the api not continue to the destination endpoint.
How I can send back the new refreshed token and continue with the request?
My express middleware to check the token:
apiRouter.use(function(req, res, next) {
var token = req.body.token || req.query.token || req.headers['x-access-token'];
if (token) {
jwt.verify(token, app.get('superSecret'), function(err, decoded) {
if (err) {
//Here I can check if the received token in the request expired
if(err.name == "TokenExpiredError"){
var refreshedToken = jwt.sign({
success: true,
}, app.get('superSecret'), {
expiresIn: '5m'
});
//Here need to send the new token back to the client and continue with the request
//but if I use return res.... the request don't continue to next()
next();
}else if (err) {
return res.json({ success: false, message: 'Failed to authenticate token.' });
}
} else {
//If no error with the token, continue
next();
};
});
} else {
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
});
I dont' know if its the best aproach to this.
Thanks you.
You can not send a response to the client two times for single request, so better way will be sent an access token with the actual API response.
apiRouter.use(function(req, res, next) {
var token = req.body.token || req.query.token || req.headers['x-access-token'];
if (token) {
jwt.verify(token, app.get('superSecret'), function(err, decoded) {
if (err) {
//Here I can check if the received token in the request expired
if(err.name == "TokenExpiredError"){
var refreshedToken = jwt.sign({
success: true,
}, app.get('superSecret'), {
expiresIn: '5m'
});
request.apiToken = refreshedToken;
next();
}else if (err) {
return res.json({ success: false, message: 'Failed to authenticate token.' });
}
} else {
//If no error with the token, continue
request.apiToken = token;
next();
};
});
} else {
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
});
then when you send a response then send a response with the token, that you can get with request.apiToken.
but a better strategy is to provide a client refresh token and let the client make a request to get refreshed token.
You can read more about that here

How to exclude a router/api url from jsonwebtoken

I am using node.js express app. jsonwebtoken for authentication. I want to exlude some api url from the jsonwebtoken verification. below is what I have tried and my code
router.use('/authentication', mountAllRoutes(authenticationModule));
// route middleware to verify a token
router.use((req, res, next) => {
const r = req;
const token = req.body.token || req.query.token || req.headers.authorization;
// decode token
if (token) {
// verifies secret and checks exp
jwt.verify(token, (req.app.get('superSecret')), (err, decoded) => {
if (err) {
// res.json({ success: false, message: 'Failed to authenticate token.' });
res.status(401).send({
success: false,
message: 'Failed to authenticate token.'
});
} else {
// if everything is good, save to request for use in other routes
r.decoded = decoded;
next();
// console.log(decoded);
}
return {};
});
} else {
// if there is no token
// return an error
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
return {};
});
router.use('/test', mountAllRoutes(testModule));
router.use('/other', mountAllRoutes(otherModule));
router.use('/data', mountAllRoutes(dataModule));
Here I have placed routes above middleware which I dont want to protect. and I have placed after middleware which I want to protect. But it is protected which I placed above middleware. In authenticationModule, login and user registration api comes. so for user registration it gives response no token provided
Note: I have refrerred this link How-to-ignore-some-request-type-in-Jsonwebtoken
create separate route file for the API you want to exclued.
//Routes
var users = require('./routes/users');
var api = require('./routes/publicApi');
App.js:
// route middleware to verify a token
router.use((req, res, next) => {
const r = req;
const token = req.body.token || req.query.token || req.headers.authorization;
// decode token
if (token) {
// verifies secret and checks exp
jwt.verify(token, (req.app.get('superSecret')), (err, decoded) => {
if (err) {
// res.json({ success: false, message: 'Failed to authenticate token.' });
res.status(401).send({
success: false,
message: 'Failed to authenticate token.'
});
} else {
// if everything is good, save to request for use in other routes
r.decoded = decoded;
next();
// console.log(decoded);
}
return {};
});
} else {
// if there is no token
// return an error
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
return {};
});
app.use('/users', router);//will use Token Authentican
app.use('/publicApi', router);//Dont do this.

JsonWebTokenError: Can't verify jwt

I make the token here:
var token = jwt.sign(user, new_secret, {expiresIn: 10000});
Then I attempt to verify it here
var token = req.headers.authorization;
jwt.verify(token, new_secret, function(err, decoded) {
console.log(err);
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();
}
});
I can't figure out where I'm going wrong here. I'm new to jwt.
I was able to get it to work by changing the prefix on the client side using angular-jwt.
It was once 'Bearer'; I found evidence that it should be 'JWT'...it only worked by removing it entirely:
jwtInterceptorProvider.authPrefix = '';
I'm not sure if this is best practice or not.

Save and get express.js token from local storage

I am using Node with Express.js and trying to make an authentication with JWT, after the user logs in generate a token, and save it to localstorage, but then I don't know how to get the token for authentication.
This is the code I am using:
Login view:
$.ajax({
type: 'POST',
url: base_url + "login",
data: postData,
dataType: 'json',
success: function(data){
// console.log(data1);
// alert(data);
_(data);
if(data.success === false){
showError(data.msg);
}else{
showError(data.msg);
window.localStorage.setItem("authToken", data.token);
var token = window.localStorage.getItem('authToken');
if (token) {
$.ajaxSetup({
headers: {
'x-access-token': token
}
});
}
}
}
});
And this is the route authentication I am using to check before any of the routes is accessed:
router.use(function(req, res, next){
var token = req.headers['x-access-token'];
console.log(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.'
});
}
});
In console.log(token) I get an Undefined variable , it seems like I don't know how to access the token from route.
Thanks a lot.
"x-access-token" must be registered as an allowed header
response.setHeader("Access-Control-Allow-Headers", "x-access-token, mytoken");
Check this post :
How do CORS and Access-Control-Allow-Headers work?

Resources