SyntaxError: Identifier 'createToken' has already been declared - node.js

Hi I'm making a login server there is an error There's an error when I make a declaration. const createToken what can I do How can I change that code? What's the problem and how to solve and why? can you explain me thank you very much
isRefresh.js
const jwt = require("jsonwebtoken");
const { createToken } = require("../utils/jwt");
const db = require("../database/db");
const createToken = (payload) => {
console.log("createToken");
const token = jwt.sign({ username: payload.toString() }, secretKey, {
algorithm: "sha256",
expiresIn: "30m",
});
return token;
};
module.exports = async (req, res, next) => {
try {
const refreshtoken = req.get("r_x_auth");
if (!refreshtoken) {
return false;
}
const decodedToken = jwt.verify(refreshtoken, R_secretKey);
const data = [decodedToken.username];
const sql = "select * from member where user_id = ?";
const conn = await db.getConnection();
const [rows] = await conn.query(sql, data);
if (rows) {
const newtoken = createToken(rows[0].username);
res.send(newtoken);
} else {
return false;
}
} catch (err) {
next(err);
}
};
jwt.js
const jwt = require("jsonwebtoken");
const { ACCESS_KEY, REFRESH_KEY } = process.env;
const createToken = (payload) => {
const token = jwt.sign({ username: payload.toString() }, ACCESS_KEY, {
algorithm: "sha256",
expiresIn: "30m",
});
return token;
};
const creatRefreshToken = (payload) => {
const retoken = jwt.sign({ username: payload.toString() }, REFRESH_KEY, {
algorithm: "sha256",
expiresIn: "1d",
});
return retoken;
};
module.exports = { createToken, creatRefreshToken };
isAuth.js
const jwt = require("jsonwebtoken");
require("dotenv").config();
const secretKey = process.env.ACCESS_KEY;
const db = require("../database/db");
module.exports = async (req, res, next) => {
try {
const token = req.get("x_auth");
const decodedToken = jwt.verify(token, secretKey);
const { username } = decodedToken;
const data = [username];
const sql = "select * from member where username = ?";
const conn = await db.getConnection();
const [rows] = await conn.query(sql, data);
if (!rows) {
return false;
}
next();
} catch (err) {
next(err);
}
};
controller.js
const jwt = require("jsonwebtoken");
require("dotenv").config();
const secretKey = process.env.ACCESS_KEY;
const db = require("../database/db");
module.exports = async (req, res, next) => {
try {
const token = req.get("x_auth");
const decodedToken = jwt.verify(token, secretKey);
const { username } = decodedToken;
const data = [username];
const sql = "select * from member where username = ?";
const conn = await db.getConnection();
const [rows] = await conn.query(sql, data);
if (!rows) {
return false;
}
next();
} catch (err) {
next(err);
}
};
Anyone please help thanks !
please please help me
I'm clueless save me

Error message is clean as it should be: you defined createToken twice on same module level.
Rename one of them, for example:
const createTokenJWT = require("../utils/jwt").createToken;

You are declaring createToken twice:
const { createToken } = require("../utils/jwt");
and here:
const createToken = (payload) => {
console.log("createToken");
const token = jwt.sign({ username: payload.toString() }, secretKey, {
algorithm: "sha256",
expiresIn: "30m",
});
return token;
};

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 }, ...)

NodeJS can't able to authenticate ,even though I give bearer token

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) {
});

Is this implementation of sending reset password email correct?

I've gone through this article https://ahrjarrett.com/posts/2019-02-08-resetting-user-passwords-with-node-and-jwt to see how to reset password in express.
mailer.js
const nodemailer = require("nodemailer")
export const transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: process.env.EMAIL,
pass: process.env.PASSWORD
}
})
export const getPasswordResetURL = (user, token) => {
`http://localhost:3000/password/reset/${user._id}/${token}`
}
export const resetPasswordTemplate = (user, url) => {
const from = process.env.EMAIL
const to = user.email
const subject = "Password Reset"
const html = `
<p>Hey ${user.name || user.email},</p>
<p>We heard that you forgot your password. Sorry about that!</p>
<p>But don’t worry! You can use the following link to reset your password:</p>
<a href=${url}>${url}</a>
<p>If you don’t use this link within 1 hour, it will expire.</p>
`
}
return { from, to, subject, html }
emailController.js
const jwt = require("jsonwebtoken")
const bcrypt = require("bcrypt")
const User = require("../models/User")
import { transporter, getPasswordResetURL, resetPasswordTemplate } from "../utils/mailer"
export const usePasswordHashToMakeToken = ({
password: passwordHash,
_id: userId,
createdAt
}) => {
const secret = passwordHash + "-" + createdAt
const token = jwt.sign({ userId }, secret, {
expiresIn: 3600 // 1 hour
})
return token
}
export const sendPasswordResetEmail = async (req, res) => {
const { email } = req.params
let user
try {
user = await User.findOne({ email }).exec()
} catch (err) {
res.status(404).json("No user with that email")
}
const token = usePasswordHashToMakeToken(user)
const url = getPasswordResetURL(user, token)
const emailTemplate = resetPasswordTemplate(user, url)
const sendEmail = () => {
transporter.sendMail(emailTemplate, (err, info) => {
if (err) {
res.status(500).json("Error sending email")
}
console.log(`** Email sent **`, info.response)
})
}
sendEmail()
}
export const receiveNewPassword = (req, res) => {
const { userId, token } = req.params
const { password } = req.body
User.findOne({ _id: userId })
.then(user => {
const secret = user.password + "-" + user.createdAt
const payload = jwt.decode(token, secret)
if (payload.userId === user.id) {
bcrypt.genSalt(10, function(err, salt) {
if (err) return
bcrypt.hash(password, salt, function(err, hash) {
if (err) return
User.findOneAndUpdate({ _id: userId }, { password: hash })
.then(() => res.status(202).json("Password changed accepted"))
.catch(err => res.status(500).json(err))
})
})
}
})
.catch(() => {
res.status(404).json("Invalid user")
})
}
users.js
const express = require('express');
const router = express.Router();
const userController = require("../controllers/userController")
const emailController = require("../controllers/emailController")
router.post("/register", userController.registerUser)
router.post("/login", userController.loginUser)
router.get("/:userId", userController.getUser)
router.post("/user/:email", emailController.sendPasswordResetEmail)
router.post("/receive_new_password/:userId/:token", emailController.receiveNewPassword)
module.exports = router;
It's giving me an error of unexpected token { in this line
import { transporter, getPasswordResetURL, resetPasswordTemplate } from "../utils/mailer"
Can I convert this export const into module.exports and require the above by:
const { transporter, getPasswordResetURL, resetPasswordTemplate } = require("../utils/mailer")
As you mentioned in the question replace all export const and replace it to
module.exports = {transporter, getPasswordResetURL, resetPasswordTemplate}
Also replace the line
import { transporter, getPasswordResetURL, resetPasswordTemplate } from "../utils/mailer"
to
const { transporter, getPasswordResetURL, resetPasswordTemplate } = require("../utils/mailer")
As import, export is es6 syntax and require, module.exports is es5 syntax. If you want to use import then you need to configure Babel.
Suggestions
Most probably example you've taken from he's using es6 and es5 syntax together(He must have configured babel). But in your case, I don't think you have configured babel. So I'll suggest you to either configure babel or change all the es6 syntax to es5. In es6 you can use es5 but in es5 you cannot use es6

Microsoft Graph API with Simple-OAuth2 and Client Credentials Flow

I'm trying to log users with Client Credentials Flow with Simple-OAuth2 in a NodeJS website.
My routes/index.js is this:
var express = require('express');
var router = express.Router();
var authHelper = require('../helpers/auth');
router.get('/', async function(req, res, next) {
let parms = { title: 'Home', active: { home: true } };
const accessToken = await authHelper.accessToken;
res.render('index', parms);
});
module.exports = router;
And my auth.js is this:
const credentials = {
client: {
id: process.env.APP_ID,
secret: process.env.APP_PASSWORD,
},
auth: {
tokenHost: 'https://login.microsoftonline.com',
authorizePath: "common/oauth2/v2.0/authorize",
tokenPath: "common/oauth2/v2.0/token",
}
};
const oauth2 = require('simple-oauth2').create(credentials);
const tokenConfig = {
username: 'uuuuuu#dddddd.com',
password: 'ppppppp',
scope: process.env.APP_SCOPES,
};
try {
const result = await oauth2.ownerPassword.getToken(tokenConfig);
const accessToken = oauth2.accessToken.create(result);
} catch (error) {
console.log('Access Token Error', error.message);
}
exports.accessToken = accessToken;
When I try to start website, nodejs shows me a sintax error:
const result = await oauth2.ownerPassword.getToken(tokenConfig);
^^^^^
SyntaxError: await is only valid in async function
This error does not make much sense to me since the code is provided by simple-oauth2.
Could someone shed light on my actual error?
Well you have to wrap your code into async function so you could use await key word in that function. You cna find more info here.
In your case I would wrap code into function and export that function like this:
const credentials = {
client: {
id: process.env.APP_ID,
secret: process.env.APP_PASSWORD,
},
auth: {
tokenHost: 'https://login.microsoftonline.com',
authorizePath: "common/oauth2/v2.0/authorize",
tokenPath: "common/oauth2/v2.0/token",
}
};
const oauth2 = require('simple-oauth2').create(credentials);
const tokenConfig = {
username: 'uuuuuu#dddddd.com',
password: 'ppppppp',
scope: process.env.APP_SCOPES,
};
const getAccessToken = async () => {
try {
const result = await oauth2.ownerPassword.getToken(tokenConfig);
const accessToken = oauth2.accessToken.create(result);
return accessToken;
} catch (error) {
console.log('Access Token Error', error.message);
return null;
}
};
exports.getAccessToken = getAccessToken;
And then you can use that function like this:
var express = require('express');
var router = express.Router();
var authHelper = require('../helpers/auth');
router.get('/', async function(req, res, next) {
let parms = { title: 'Home', active: { home: true } };
const accessToken = await authHelper.getAccessToken();
res.render('index', parms);
});
module.exports = router;

How to use multiple post functions in node js epxress mongodb

What I'm trying to do here is use the 2 functions but I don't know how to use both of them as they're both post functions with same name and I want to able to test using postman. These are in the same file
const jwt = require('jsonwebtoken');
const Joi = require('joi');
const bcrypt = require('bcrypt');
const _ = require('lodash');
const { users } = require('../models/user');
const express = require('express');
const router = express.Router();
this is the first post function
router.post('/', async (req, res) => {
const { error } = validate(req.body);
if (error) {
return res.status(400).send(error.details[0].message);
}
let user = await users.findOne({ email: req.body.email });
if (!user) {
return res.status(400).send('Incorrect email or password.');
}
const validPassword = await bcrypt.compare(req.body.password,
user.password);
if (!validPassword) {
return res.status(400).send('Incorrect email or password.');
}
const token = jwt.sign({ _id: user._id }, 'PrivateKey');
res.header('x-auth-token', token).send(_.pick(user, ['_id', 'name',
'email']));
});
this is the second post function
router.post('/', async (req, res) => {
const { error } = validate(req.body);
if (error) {
return res.status(400).send(error.details[0].message);
}
let user = await users.findOne({ email: req.body.email });
if (!user) {
return res.status(400).send('Incorrect email or password.');
}
const validPassword = await bcrypt.compare(req.body.password,
user.password);
if (!validPassword) {
return res.status(400).send('Incorrect email or password.');
}
});
function validate(req) {
const schema = {
email: Joi.string().min(5).max(255).required().email(),
password: Joi.string().min(5).max(255).required()
};
return Joi.validate(req, schema);
}
and lastly the last line in the file
module.exports = router;
You cannot have 2 handlers for same REST endpoint with same METHOD. Why don't you change one to router.post('/login')

Resources