NodeJS can't able to authenticate ,even though I give bearer token - node.js

Below code consist of my jwt file and user.service file code.I can't able to authenticate ,even though I give bearer token.please help me with this
my user.service file
module.exports = {
authenticate,
getAll,
getById,
create,
update,
getByEmail,
changePassword,
delete: _delete
};
async function authenticate({ email, password }) {
const user = await User.findOne({
email
});
if (user && bcrypt.compareSync(password, user.hash)) {
const { hash, ...userWithoutHash } = user.toObject();
const token = jwt.sign(
{
sub: user.id
},
config.secret
);
const y = user.lastLoginDate;
user.lastLoginDate = Date.now();
const x = user.lastLoginDate;
Object.assign(user, x);
await user.save();
const axyz = user.id;
const companies = await company.find({ userAccessId: user.id });
return {
...userWithoutHash,
token,
companies
};
}
}
async function getById(userParam) {
const user = await User.findOne({
id: userParam.id,
defaultAccountId: userParam.defaultAccountId
});
if (user) {
const companies = await company.find({ userAccessId: user.id });
return {
user,
companies
};
}
}
async function getByEmail(userParam) {
return await User.findOne({
email: userParam.email
}).select("-hash");
}
async function create(userParam) {
const users = await User.findOne({
email: userParam.email
});
const user = new User(userParam);
if (!users) {
if (userParam.password) {
user.hash = bcrypt.hashSync(userParam.password, 10);
}
await user.save();
const companies = await company.findOne({ businessUnitId: userParam.defaultAccountId });
if (companies) {
const Arrays = companies.userAccessId;
Arrays.addToSet(user.id);
await companies.save();
}
const { hash, ...userWithoutHash } = user.toObject();
const token = jwt.sign(
{
sub: user.id
},
config.secret
);
return {
...userWithoutHash
};
} else {
const idd = user.id;
const companies = await company.findOne({ businessUnitId: userParam.defaultAccountId });
if (companies) {
const Arrays = companies.userAccessId;
var index = Arrays.indexOf(users.id);
if (index > -1) {
} else {
Arrays.addToSet(users.id);
await companies.save();
return userParam;
}
}
}
}
async function update(userParam, call) {
const user = await User.findOne({
id: userParam.id,
defaultAccountId: userParam.defaultAccountId
});
if (user) {
const users = await User.findOne({ userName: userParam.userName });
if (!users) {
if (userParam.userName) {
user.userName = userParam.userName;
const x = userParam.userName;
Object.assign(user, x);
await user.save(x);
}
if (userParam.userRole) {
user.userRole = userParam.userRole;
const y = userParam.userRole;
Object.assign(user, y);
await user.save(y);
}
const { hash, ...userWithoutHash } = user.toObject();
const token = jwt.sign(
{
sub: user.id
},
config.secret
);
return {
...userWithoutHash
};
} else {
throw "User Aldready Exits";
}
}
}
async function changePassword(userParam) {
const user = await User.findOne({
email: userParam.email
});
if (user) {
if (userParam.password) {
userParam.hash = bcrypt.hashSync(userParam.password, 10);
}
Object.assign(user, userParam);
return await user.save();
}
}
async function _delete(userParam) {
const user = await User.findOne({
id: userParam.id
});
if (user) {
if (await company.findOne({ userAccessId: user.id })) {
const companiess = await company.find({ userAccessId: user.id });
if (companiess) {
const n = companiess.length;
for (i = 0; i < n; i++) {
console.log(i);
const Arrays = companiess[i].userAccessId;
console.log(Arrays);
var index = Arrays.indexOf(user.id);
if (index > -1) {
Arrays.splice(index, 1);
await companiess[i].save();
}
}
}
return await user.remove();
}
}
}
async function getAll(userParam) {
if (await User.findOne({ defaultAccountId: userParam.defaultAccountId })) {
const user = await User.find({ defaultAccountId: userParam.defaultAccountId });
return await user;
}
}
my jwt file:
const expressJwt = require("express-jwt");
const config = require("config.json");
const userService = require("models/v1/user.service");
module.exports = jwt;
function jwt() {
const secret = config.secret;
return expressJwt({
secret,
isRevoked
}).unless({
path: ["/users/login"]
});
}
async function isRevoked(req, payload, done) {
const user = await userService.getById(payload.sub);
if (!user) {
return done(null, true);
}
done();
}
Please help me to solve this issue. It works previously when I not integrate my code with my team, after integrating my code its not working, I'm getting Unauthorized error.

var decoded = jwt.verify(token, "someSecretKey");
console.log(decoded) // bar
// verify a token symmetric
jwt.verify(token, "someSecretKey", function(err, decoded) {
console.log(decoded.foo) // bar
});
// invalid token - synchronous
try {
var decoded = jwt.verify(token, 'wrong-secret');
} catch(err) {
}
jwt.verify(token, 'wrong-secret', function(err, decoded) {
});

Related

What would be the error with this token verification code?

When making the middleware request in my route, I always fall into the else of "verifyAdmin" (error 403). The big problem is that I can't send a throw or catch of this error, it just doesn't return any error in the terminal, but when testing in postman it always goes to else
const jwt = require('jsonwebtoken');
const verifyToken = (req, res, next) => {
const { authorization } = req.headers;
if (!authorization) {
return res.status(401).json('Invalid Authorization')
};
const token = authorization.replace('Bearer', ' ').trim();
try {
const secret = process.env.JWT_SECRET;
const data = jwt.verify(token, secret);
req.users = data;
const { id } = data;
req.userId = id;
return next();
} catch (err) {
return res.status(400).json(err);
}
};
const verifyAdmin = (req, res, next) => {
if (req.users.isAdmin === true) {
next();
} else {
return res.status(403).json("You are not alowed to do that!");
}
};
module.exports = {
verifyToken,
verifyAdmin,
};
in route
const { verifyToken, verifyAdmin } = require('../middlewares/verifyToken');
router.get('/', verifyToken, verifyAdmin, FindAllUsersController.index);
construction token
const db = require('../../models/index');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
exports.store = async (req, res) => {
const { email, password } = req.body;
const secret = process.env.JWT_SECRET;
try {
const user = await db.User.findOne({ where: { email } });
if (!user) {
return res.status(401).json('User does not exist');
}
const isValidPassword = await bcrypt.compare(password, user.password);
if (!isValidPassword) {
return res.status(401).json('Password is not valid');
}
const token = jwt.sign({ id: user.id }, secret, {
expiresIn: process.env.EXPIRES_TOKEN,
})
return res.status(200).json({
user,
token,
});
} catch (err) {
console.log(err);
}
}
The isAdmin flag is not contained in your token, because you include only the id when constructing it:
const token = jwt.sign({ id: user.id }, ...)
You need (at least):
const token = jwt.sign({ id: user.id, isAdmin: user.isAdmin }, ...)

Service Oriented Architecture in node.js

I am building a Node.js project which has an advanced folder structure for future purposes.
user.register controller:
exports.register = async (req, res) => {
try {
var isValidated = await userService.validateInDatabase(req);
if (!isValidated)
return res
.status(409)
.json({ error: "Phone number or email is already registered" });
var user = await userService.create(req);
return user
} catch (e) {
console.trace(e);
return res.status(400).json({ message: e.message });
}
};
The services file code:
exports.create = async (user) => {
const hashedPassword = passwordHash.generate(user.password);
let new_user = new User({
phoneNumber,
email,
password: hashedPassword,
});
const payload = {
id: new_user._id,
};
let token = jwt.sign(payload, keys.JWToken, { expiresIn: 31556926 });
const userData = await new_user.save();
return userData;
};
exports.validateInDatabase = async (req) => {
let check_user = await User.findOne({
$or: [{ email: req.body.email }, { phoneNumber: req.body.phoneNumber }],
});
if (check_user) return false;
return true;
};
Now, whenever I send the request from the postman it says invalid password Why is that?

Can't seem to fix undefined await result

I need to compare passwords with Bcrypt library.
here's my code:
bcrypt.js
const bcrypt = require('bcrypt');
const saltRounds = 10;
var Bcrypt = () => {
}
Bcrypt.encrypt = async function(password) {
const hashedPassword = await bcrypt.hash(password, saltRounds)
return hashedPassword
}
Bcrypt.compare = async function(password, hashed_password) {
await bcrypt.compare(password, hashed_password, function(err, result) {
return result;
});
}
module.exports = Bcrypt;
userMethods.js
const Bcrypt = require('../../global-functions/bcrypt');
var login = async(req) => {
var user = {
username: req.body.username,
password: req.body.password
}
if (!user.username || !user.password) {
return ({ error: "Login details are required to continue." });
}
return new Promise((resolve, reject) => {
db.query("SELECT name,username,email,password FROM users WHERE username = ?", [req.body.username], function(err, rows) {
if (err) {
console.log("error: ", err);
reject(err);
} else {
var compared_result = Bcrypt.compare(user.password, rows[0].password); // returns **undefined**
}
if (compared_result) {
resolve({ success: compared_result, username: rows[0].username });
} else {
resolve({ error: "wrong username or password!" });
}
});
});
}
when I try to add await before Bcrypt.compare I get an "await is only valid in async function" error.
I would appreciate any help.
Do you want to put it before this Bcrypt.compare
Bcrypt.compare = async function(password, hashed_password) {
await bcrypt.compare(password, hashed_password, function(err, result) {
return result;
});
}
Then you have to write this code into a outer function and give async there then use await inside
async function()
{
await Bcrypt.compare = async function(password, hashed_password) {
await bcrypt.compare(password, hashed_password, function(err, result) {
return result;
});
}
}
I think this might solve your problem

await is only valid in async function error - Azure Function

I'm trying to get my login api working inside azure function, but it keeps saying await is only valid in async function. This is an async function so I'm just super confused.
This line
const user = await db.collection('users').findOne({ email: userLoggingIn.email })
is throwing the error.
const jwt = require("jsonwebtoken");
const bcrypt = require("bcrypt");
var MongoClient = require('mongodb').MongoClient;
module.exports = async function (context, req) {
MongoClient.connect(process.env.CosmosDBConnectionString, (err, client) => {
let userLoggingIn = ({ email, password } = req.body);
console.log("userLoggingIn");
console.log(userLoggingIn.email);
let send = response(client, context);
if (err) send(500, err.message);
console.log("DBNAME: " + process.env.dbName);
let user;
let db = client.db(process.env.dbName);
const user = await db.collection('users').findOne({ email: userLoggingIn.email })
console.log("USER");
console.log(user);
let userName= user.instagramName;
if (!user) {
send(401, { message: "Auth failed" });
}
const { username } = user;
console.log("PASSWORD");
console.log(context.req.password);
console.log(user.password);
const goodPassword = bcrypt.compareSync(context.req.password, user.password);
if (!goodPassword) {
return send(401, { message: "Auth failed" });
}
const token = jwt.sign(
{
email: user.email,
userId: user._id,
username: userName
},
"secret_this_should_be_longer",
{ expiresIn: "1h" }
);
context.res = { status: 200, token: token, expiresIn: 3600, userId: user._id, username: username};
})
}
function response(client, context) {
return function (status, body) {
context.res = {
status: status,
body: body
};
client.close();
context.done();
};
}
MongoClient.connect(process.env.CosmosDBConnectionString, (err, client) => {
on this line, the annonymous callback function receiving err and client as parameter is the function that needs to be async
MongoClient.connect(process.env.CosmosDBConnectionString, async (err, client) => {

Mongoose Ignore Required

I have this User schema:
email: {
type: String,
required: true
},
name: {
type: String,
required: true
},
password: {
type: String,
required: true
}
When you do a POST (/api/user-add), I want all the fields to be required. But when I do a login (/api/login) then I only need the email and password fields. My problem is, in my login code I eventually get to this function:
staffSchema.methods.generateToken = function(callback) {
var token = jwt.sign(this._id.toHexString(), config.SECRET);
this.token = token;
this.save(function(err, staff) {
if (err) return callback(err);
callback(null, staff);
});
}
And here it thows an error because the name field is required. How do I bypass this. I am looking for something like this I assume:
this.save(function(err, staff) {
if (err) return callback(err);
callback(null, staff);
}).ignoreRequired('name');
When You Login using JWT token this is a basic example to generate token and authenticate user without store token
Note :
Example to authenticate the user without store token in DB
*Login Method
const jwt = require('./jwt');
userCtr.authenticate = (req, res) => {
const {
email, password,
} = req.body;
const query = {
email: email,
};
User.findOne(query)
.then((user) => {
if (!user) {
//return error user not found.
} else {
if (passwordHash.verify(password, user.password)) { // verify password
const token = jwt.getAuthToken({ id: user._id });
const userData = _.omit(user.toObject(), ['password']); // return user data
return res.status(200).json({ token, userData });
}
//return error password not match
}
})
.catch((err) => {
});
};
*jwt.js
const jwt = require('jwt-simple');
const logger = require('./logger');
const jwtUtil = {};
jwtUtil.getAuthToken = (data) => {
return jwt.encode(data, process.env.JwtSecret);
};
jwtUtil.decodeAuthToken = (token) => {
if (token) {
try {
return jwt.decode(token, process.env.JwtSecret);
} catch (err) {
logger.error(err);
return false;
}
}
return false;
};
module.exports = jwtUtil;
*use middleware to prevent another route to access.
userRouter.post('/update-profile', middleware.checkUser, userCtr.updateProfile);
*middleWare.js
middleware.checkUser = (req, res, next) => {
const { headers } = req;
if (_.isEmpty(headers.authorization)) {
//return error
} else {
const decoded = jwt.decodeAuthToken(headers.authorization.replace('Bearer ', ''));
if (decoded) {
User.findOne({ _id: decoded.id })
.then((user) => {
if (user) {
req.user = user;
next();
} else {
//error
}
})
.catch((err) => {
//errror
});
req.user = decoded;
} else {
//error
}
}
};

Resources