JWT error with placement of jwt.sign code - node.js

I'm working on creating a authentication system and am trying to figure out how to use JWT. I'm using Node, express, passport and MYSQL. I tried creating the "var token" after the db.sync() method but that would only throw a error but then it works if i put the "var token" before db.sync() why is this? And should i do it this way? Thanks in advance!
var jwt = require('jsonwebtoken');
var config = require('../config'),
db = require('../services/database'),
User = require('../models/user'),
Organisation = require('../models/organisation'),
Event = require('../models/event');
// The authentication controller.
var AuthController = {};
// Register a user.
AuthController.signUp = function(req, res) {
if(!req.body.username || !req.body.password || !req.body.email) {
res.json({ message: 'Please provide a username and a password.' });
} else {
var token = jwt.sign({ username: req.body.username }, config.keys.secret, { expiresIn: '30m' });
db.sync().then(function() {
var newUser = {
username: req.body.username,
password: req.body.password,
email: req.body.email,
temporarytoken: token
};
console.log(newUser.temporarytoken);
return User.create(newUser).then(function() {
res.status(201).json({ message: 'Account created!' });
});
}).catch(function(error) {
res.status(403).json({ message: 'Username already exists!' });
});
}
}

What is your error message like?
Also, are you seeing errors if you do this code?
db.sync().then(function() {
var token = jwt.sign({ username: req.body.username }, config.keys.secret, { expiresIn: '30m' });
var newUser = {
username: req.body.username,
password: req.body.password,
email: req.body.email,
temporarytoken: token
};
console.log(newUser.temporarytoken);
return User.create(newUser).then(function() {
res.status(201).json({ message: 'Account created!' });
});
P.S. Why are you saving the token to the DB? You should send the jwt to the client and the client will save it to a local storage or cookie. That is the whole point of jwt.

Related

getting an arror 500 when trying to register new user

im completing a fullstack project using react and node
when trying to register a user or a product i keep on getting error 500 in the browser and this error in my visual studio terminal:
Error: Illegal arguments: string, object
here's my create user function:
const createUser = asyncHandler(async (req, res) => {
const { name, email, password } = req.body;
const userExist = await User.findOne({ email });
if (userExist) {
res.status(400);
throw new Error("User already exists");
}
const user = await User.create({
name,
email,
password,
});
if (user) {
res.status(201).json({
_id: user._id,
name: user.name,
email: user.email,
isAdmin: user.isAdmin,
token: generateToken(user._id),
});
} else {
res.status(400);
throw new Error("Invalid user data");
}
});
what could cause an error 500?
trying to register a new user to the db
To resolve this issue you can follow some steps:
Try to console the data from the request parameters i.e name, email, password and manipulate your request parameters
Else use:- const email=req.body.email; such syntax for all the request params
Again try to console the req params, hope this time these params will be there.
Use this modification:
const createUser = asyncHandler(async (req, res) => {
const name = req.body.name;
const email = req.body.email;
const password = req.body.password;
const userExist = await User.findOne({ email });
if (userExist) {
res.status(400);
throw new Error("User already exists");
}
const user = await User.create({
name,
email,
password,
});
if (user) {
res.status(201).json({
_id: user._id,
name: user.name,
email: user.email,
isAdmin: user.isAdmin,
token: generateToken(user._id),
});
} else {
res.status(400);
throw new Error("Invalid user data");
}
});
if your req params are not accessing the body params from the form, try using body-parser or multer for the same.
Note: Try using console.log() to know the line of concern of your code.

JWT Webtoken Unable to verify against req.params

I've created an email authentication system, however there appears to be an issue with how I jwt.verify this token.
I believe there's an issue with my : process.env.PASS_SEC, which is just my Mongo.DB password secret. Is this correct?
I can confirm if I do a res.sent(req.params.token), my token comes through fine, for example in this.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYyZjc0MWU3ZjBkZjZkY2IyZjM0ZDc3ZSIsImlhdCI6MTY2MDM3MTQzMSwiZXhwIjoxNjYwNjMwNjMxfQ.vFtdRzEH2_52Hdhxs84bk7RPdIRDIoZ6Rcd-zZoBhus
As such, I believe it's the SECRET is being passed incorrectly.
My current functioning code is:
router.post("/register", async (req, res, EMAIL_SECRET) => {
const newUser = new User({
fullname: req.body.fullname,
email: req.body.email,
position: req.body.position,
username: req.body.fullname,
password: CryptoJS.AES.encrypt(
req.body.password,
process.env.PASS_SEC
).toString(),
});
const accessToken = jwt.sign(
{
id: newUser._id,
},
process.env.JWT_SEC,
{
expiresIn:"3d"
},
);
const url = `http://localhost:5000/api/auth/confirmation/${accessToken}`;
const mailOptions = {
from: 'nathandrewphone#gmail.com',
to: req.body.email,
subject: 'Confirm Email',
html: `Please click this email to confirm your email: ${url}`
};
transporter.sendMail(mailOptions, function(error, info){
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
});
try {
const savedUser = await newUser.save();
res.status(201).json(savedUser);
} catch (err) {
res.status(500).json(err);
}
});
Which sends a code fine, however it does not appear to be correct, how would you create an EMAIL_SECRET?
This is how I wish to validate the email.
//User Email Auth Login
//Not yet functioning
router.get('/confirmation/:token', async (req, res) => {
try {
//verify the token with the secret
const { _id: { _id } } = jwt.verify(req.params.token, process.env.PASS_SEC);
await models.User.update({ confirmed: true }, { where: { _id } });
} catch (e) {
res.send('This isnt working');
}
});
However, I cannot get to verify, whats wrong with secret
You signed your token with process.env.JWT_SEC, you should verify it using the same key:
const { _id } = jwt.verify(req.params.token, process.env.JWT_SEC);
Also, you should be able to update your User with findByIdAndUpdate:
await User.findByIdAndUpdate(_id, { confirmed: true });

Cannot set headers to pass token in node js

node js
This is my register method to register a user. I am trying to pass token in headers when a user is registered which will be used in the front end to access the token and store it in the local storage.
module.exports.register = async function (req, res, next) {
try {
const { username, email, password } = req.body;
const profileImage = req.file.path;
const usernameCheck = await User.findOne({ username });
if (usernameCheck)
return res.json({ msg: "Username already used", status: false });
const emailCheck = await User.findOne({ email });
if (emailCheck)
return res.json({ msg: "Email already exists", status: false });
const hashedPassword = await bcrypt.hash(password, 10);
const user = await User.create({
_id: new mongoose.Types.ObjectId(),
username,
email,
profileImage,
password: hashedPassword,
});
delete user.password;
//create jwt token
const token = jwt.sign(
{
username: user.username,
email: user.email,
userId: user._id,
},
process.env.JWT_KEY,
{
expiresIn: "1h",
}
);
res.header("x-auth-token", token); //This is not setting the token in headers
return res.json({
message: "User Created Successfully",
status: true,
user,
});
} catch (ex) {
next(ex);
}
};
react js
This is my front-end react code to register a user. I want to login the user with the jwt token stored in localStorage once the user is registered.
const handleSubmit = async (values) => {
try {
const { username, email, profileImage, password } = values;
const formData = new FormData();
formData.append("username", username);
formData.append("email", email);
formData.append("profileImage", profileImage);
formData.append("password", password);
const response = await register(formData);
console.log(response);
if (response.status === false) return;
else {
loginWithJwt(response.headers["x-auth-token"]);// log the user in using jwt token
console.log(response.headers["x-auth-token"]);
navigate("/chatroom");
}
} catch (ex) {
console.log(ex.message);
}
};

Can't update document data with mongoose, node.js, express and async function

I'm trying to make a login function that receives and email and password from user.
checks if email exists - works
checks if password match to encrypted password in db - works
if 1+2 is true -> generates a token and set the token into the user document. But it doesn't work, the action user.token = token is invalid, and postman yields no response.
what am I doing wrong?
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const User = require('../models/user');
exports.login = async (req, res, next) => {
const email = req.body.email;
const password = req.body.password;
let emailExist = await User.findOne({ email: email }).then(user => {
if (!user) {
return res.json({ isAuth: false, message: 'Login failed, email not found' });
}
return user;
});
let isPasswordMatch = await bcrypt.compare(password, emailExist.password);
if (!isPasswordMatch) {
return res.json({ isAuth: false, message: 'Login failed, wrong password' });
}
let loadedUser = await User.findOne({ email: email, password: emailExist.password })
.then(user => {
if (!user) {
return res.json({ isAuth: false, message: 'Login failed' });
}
return user;
})
.then(user => {
const token = jwt.sign({ role: user.role, email: user.email, userId: user._id.toString() }, 'secret');
console.log(user);
user.token = token;
return user.save();
});
res.status(200)
.cookie(('auth', token))
.json({ isAuth: true, token: token, user: loadedUser });
};
updated version: (still doesn't work)
now it gives me the following error:
(node:11336) UnhandledPromiseRejectionWarning: CastError: Cast to
number failed for value
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjowLCJlbWFpbCI6ImFoQGdtYWlsLmNvbSIsInVzZXJJZCI6IjVjMTc4NDc3Mzg5MWI5MjY5MGNkMzgwNiIsImlhdCI6MTU0NTA1MTY5OX0.8GWuV82A7yOvKKkXeOjIeYve5aH0YwBEK_RuH0NVfYA"
at path "token"
exports.login = async (req, res, next) => {
const email = req.body.email;
const password = req.body.password;
let emailExist = await User.findOne({ email: email });
if (!emailExist) {
return res.json({ isAuth: false, message: 'Login failed, email not found' });
}
let isPasswordMatch = await bcrypt.compare(password, emailExist.password);
if (!isPasswordMatch) {
return res.json({ isAuth: false, message: 'Login failed, wrong password' });
}
let loadedUser = await User.findOne({ email: email, password: emailExist.password });
let token = jwt.sign(
{
role: loadedUser.role,
email: loadedUser.email,
userId: loadedUser._id.toString()
},
'secret'
);
console.log('token === ', token);
console.log('user before token === ', loadedUser);
updateUserToken = await loadedUser.update({ $set: { token: token } });
console.log('user === ', loadedUser);
res.status(200)
.cookie(('auth', token))
.json({ isAuth: true, token: token, user: updateUserToken });
};
check your user model file and see whether you have add the token as a number. if so this might be the issue. Try changing it to string

How Do I Authenticate In Sequelize?

I have a route that I must authenticate by getting sequelize to search for any instance of an existing username and password in the request body in order to know if I can go ahead and authenticate the user. I'm not sure how to do this (search and check instances in Sequelize) because documentation is pretty new for Sequelize. I attempted User.findOne by reading here http://docs.sequelizejs.com/en/latest/api/model/ for example
db.User.findOne({
where: { password: req.password, username: req.username }
}).then(function(address) {
if(address.User !== null) {
console.log('User name: '+address.User.name);
} else {
console.log('User name: NO USER');
}
But not sure of the exact syntax/approach. I have something like this:
app.post('/authenticate', function (req, res) {
//TODO validate req.body.username and req.body.password
//if is invalid, return 401
if (!(req.body.username === 'john.doe' && req.body.password === 'foobar')) {
res.status(401).send('Wrong user or password');
return;
}
var profile = {
first_name: 'John',
last_name: 'Doe',
email: 'john#doe.com',
id: 123
};
// We are sending the profile inside the token
var token = jwt.sign(profile, secret, { expiresIn: 18000 });
res.json({ token: token });
});
app.get('/api/restricted', function (req, res) {
console.log('user ' + req.user.email + ' is calling /api/restricted');
res.json({
name: 'foo'
});
});

Resources