I am trying to check if there is token but the 'split' is undefined. I'm still learning MERN so idk what's the problem.
const auths = async (req,res,next) => {
try {
const token = req.headers.authorization.split(" ")[1];
const isCustomAuth = token.length < 500;
let decodedData;
if(token && isCustomAuth){
decodedData = jwt.verify(token, 'todo');
req.userId = decodedData?.id;
}else {
decodedData = jwt.decode(token);
req.userId = decodedData?.sub;
}
next();
console.log('auth tapped!');
} catch (error) {
console.log(error);
}
}
Because header don't have authorization. So req.headers.authorization is undefined. You can use optional chaining to fix issues like this:
const token = req.headers.authorization?.split(" ")[1];
Related
I am writing a post request with basic auth in node js.I am trying to hit API without authorization field in header, still I am not getting any error.
subscriptionRouter.route('/subscriptions')
.post((req, res) => {
//console.log(JSON.stringify(req.body));
if (!req.headers.authorization || req.headers.authorization.indexOf('Basic ') === -1) {
res.status(401).json({ message: 'Missing Authorization Header' });
}
const base64Credentials = req.headers.authorization.split(' ')[1];
const credentials = Buffer.from(base64Credentials, 'base64').toString('ascii');
if(credentials == 'GsubNode:WelcomeNode#123'){
console.log(req.body);
var msgId = putMessageSync(req.body);
let responseJSON = {};
if (msgId == "") {
responseJSON.statusCode = 400;
responseJSON.statusDesc = "Bad Request";
responseJSON.msgId = msgId;
}
else {
responseJSON.statusCode = 200;
responseJSON.statusDesc = "Posted";
responseJSON.MsgId = msgId;
}
res.json(responseJSON);
}
else{
res.status(401).json({ message: 'Invalid Authentication Credentials' });
}
})
You may want to use a middleware, first declare the function:
function authenticate(req, res, next){
const authHeader = req.headers['authorization'];
const base64Credentials = authHeader && authHeader.split(' ')[1];
if( base64Credentials == null ) return res.sendStatus(401)
if(credentials == 'GsubNode:WelcomeNode#123'){
next()
}
}
Then you'd specify the middleware for each path you'd like to authenticate and run the rest of your code for the api call (using express) like:
express.post('/subscriptions', authenticate, (req, res) => {
console.log(req.body);
var msgId = putMessageSync(req.body);
let responseJSON = {};
if (msgId == "") {
responseJSON.statusCode = 400;
responseJSON.statusDesc = "Bad Request";
responseJSON.msgId = msgId;
}
else {
responseJSON.statusCode = 200;
responseJSON.statusDesc = "Posted";
responseJSON.MsgId = msgId;
}
res.json(responseJSON);
});
EDIT: The answer to this post elaborates on routers and middleware: setting up a middleware in router.route() in nodejs (express)
I have a function that checks the existence and validity of a token and makes a new request to get a new token if the token does not exists or is expired.
But the function always returns a promise instead of the data, and can not use it further.
const checkToken = (token) => {
if (!token || !(token.hasOwnProperty('expiry') && Object.prototype.toString.call(token.expiry) === '[object Date]') && !isExpired(token.expiry)) {
token = axios(getOptions()).then(resp => {
console.log(resp.data.expires_in);
let today = new Date();
let expiry = new Date(today.getTime() + 1000*(resp.data.expires_in));
return ({
'token': resp.data.access_token,
'expiry': expiry
});
});
return token;
}
return token;
}
checkToken is consumed like so:
const axios = require('axios');
let token;
exports.handler = (event, context, callback) => {
console.log(token);
console.log(event);
token = checkToken(token);
let options = getReqOptions(event,token);
console.log(options)
return options
};
Thanks for help!
Yes Axios return a promise but you're again returning a promise using then. You're using then value for token. That's why you're seeing token as a promise. You can simply use async/await to get same(more readable).
const checkToken = async (token) => {
if (!token || !(token.hasOwnProperty('expiry') && Object.prototype.toString.call(token.expiry) === '[object Date]') && !isExpired(token.expiry)) {
try {
const reponse = await axios(getOptions())
console.log(reponse.data.expires_in);
const expiry = new Date(today.getTime() + 1000 * (reponse.data.expires_in));
return {
token: resp.data.access_token,
expiry
}
} catch(err) {
console.log('Error while getting token ', err)
// handle error here if any
}
}
return token
}
const axios = require('axios');
let token;
exports.handler = async (event, context, callback) => {
console.log(token);
console.log(event);
try {
token = await checkToken(token);
let options = getReqOptions(event, token);
console.log(options)
return options
} catch (err) {
console.log(err)
}
};
const User = require ('../models/User');
const jwt = require ('jsonwebtoken');
const asynchronous = require('./async');
const ErrorHandler = require ('..utils/errorHandler');
exports.protect = asynchronous(async (res,req,next)=> {
if(req.headers.authorization &&
req.headers.authorization.startsWith('Bearer') ) {
let token = req.headers.authorization.split(' ')[1]
}
if(!token) {
return next(new ErrorHandler('Unauthorized,401'))
}
try {
const tokenVerify = jwt.verify(token,process.env.SECRET)
req.user = await User.findById(decoded.id);
next();
} catch(err) {
return next(new ErrorHandler('Unauthorized,401'))
}
})
Hello good people please can you tell me why anytime I execute the above code in Postman,I get a typeError:cannot read property 'authorization' of undefined?
I have require protect in all the necessary routers
It's simple you have invert req and res ;)
req is before res in the prototype
the order would be (req,res) rather than (rea,req).
I am working on express js api with jwtr,when i run the api it gives me error:
UnhandledPromiseRejectionWarning: Error: Can't set headers after they
are sent.
can anyone please help me why i am getting this error, here i have added my code, can anyone please look in it, and help me to resolve this issue,
const requireAuthentication = async(req, res, next) => {
try {
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIxUWpuTDBhd2lTIiwiaWF0IjoxNTY5OTQwMjgyfQ.1xwX2OULW4RjKW4Ok13mwlJE8k95u-d0o7T6k5U9tjs'; //req.headers['vrc-access-token'];
if (!token) return res.status(401).send('Failed to authenticate token.');
let verify_token_data = await jwtr.verify(token, secret);
if(typeof verify_token_data.jti != 'undefined') {
req.body.username = verify_token_data.username;
req.body.organization = verify_token_data.organization;
req.body.userId = verify_token_data.id;
req.body.organizationId = verify_token_data.organizationId;
console.log("sdsd234");
// create a new token
const newToken = await jwtr.sign({
username: verify_token_data.username,
organization: verify_token_data.organization,
id: verify_token_data.id,
organizationId: verify_token_data.organizationId
}, config['token-secret']);
console.log(newToken);
req.refreshToken = newToken;
console.log('sdfdf');
return await next();
} else {
return res.status(401).send('Failed to authenticate token.');
}
} catch (error) {
return res.status(401).send(error.message);
}
};
i have had this issue before and it happens because you have already send the response back to the server and it reaches a code which sends a response again.
i think that the issue is when you do
return await next()
what you should do is:
next()
const requireAuthentication = async(req, res, next) => {
try {
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIxUWpuTDBhd2lTIiwiaWF0IjoxNTY5OTQwMjgyfQ.1xwX2OULW4RjKW4Ok13mwlJE8k95u-d0o7T6k5U9tjs'; //req.headers['vrc-access-token'];
if (!token) return res.status(401).send('Failed to authenticate token.');
let verify_token_data = await jwtr.verify(token, secret);
if(typeof verify_token_data.jti != 'undefined') {
req.body.username = verify_token_data.username;
req.body.organization = verify_token_data.organization;
req.body.userId = verify_token_data.id;
req.body.organizationId = verify_token_data.organizationId;
// create a new token
const newToken = await jwtr.sign({
username: verify_token_data.username,
organization: verify_token_data.organization,
id: verify_token_data.id,
organizationId: verify_token_data.organizationId
}, config['token-secret']);
console.log(newToken);
req.refreshToken = newToken;
next();
} else {
return res.status(401).send('Failed to authenticate token.');
}
} catch (error) {
return res.status(401).send(error.message);
}
};
I tried to implement jwt token generation in node js.I got jwt token but how to validate token using node js crud operation.but I got token jwt verfiy code using callback function.without call back function used to implement async/awit function implement.
index.js
router.post('/', async (req, res) => {
(async function() {
try {
await client.connect();
console.log("Connected correctly to server");
const db = client.db('olc_prod_db');
//Validation
const { error } = validate.validate(req.body);
if (error)
{
return res.status(400).send(error.details[0].message);
}
else
{
const check_login = req.body
const r = await db.collection('UserRegistration').find().toArray();
r.forEach(element => {
if(element['username'] == check_login['username'])
{
const token = get_token.validate(req.body)
res.send({"token ":token})
}
else
{
return res.send(401,"Un Authorized");
}
});
}
client.close();
} catch(err) {
console.log(err.stack);
}
})();
});
authtoken.js
var jwt = require('jsonwebtoken')
function get_token(userdata)
{
var accessToken = jwt.sign(userdata, 'secretkey', {
//Set the expiration
expiresIn: 3600 //we are setting the expiration time of 1 hr.
});
//send the response to the caller with the accesstoken and data
console.log('Authentication is done successfully.....');
return accessToken
}
exports.validate = get_token;
const jwt = require('jsonwebtoken')
const config = require('../../config/default')
function verifyjwt(req,res,next){
const token = req.headers['authorization']
if(!token) return res.status(401).json('Unauthorize user')
try{
const decoded = jwt.verify(token,config.secret);
req.user = decoded
next()
}catch(e){
res.status(400).json('Token not valid')
}
}
module.exports = verifyjwt
const CONST = require('../../config')
exports.validJWTNeeded = (req, res, next) => {
if (req.headers['authorization']) {
try {
let authorization = req.headers['authorization'].split(' ');
if (authorization[0] !== 'Bearer') {
return res.status(401).send('invalid request'); //invalid request
} else {
req.jwt = jwt.verify(authorization[1], CONST.SECRET);
return next();
}
} catch (err) {
return res.status(403).send(); //invalid token
}
} else {
return res.status(401).send('invalid request');
}
}