i have been stuck for 3 days straight the error that i'm getting
if (!options.algorithms) throw new Error('algorithms should be set');
but why would i pass option algorithm when i already signed my token to with it's algorithm is there anyway to solve this problem appreciate your help
this is my authController!
const jwtDecode = require('jwt-decode');
const User = require('../models/userModel');
const jwt = require('express-jwt');
const dotenv = require('dotenv');
dotenv.config({ path: '.env' });
const { createToken, hashPassword, verifyPassword } = require('../utils/apiToken');
exports.authenticate = async (req, res) => {
try {
const { email, password } = req.body;
const user = await User.findOne({ email }).lean();
if (!user) {
return res.status(403).json({
message: 'Wrong email or password.'
});
}
const passwordValid = await verifyPassword(password, user.password);
if (passwordValid) {
const { password, bio, ...rest } = user;
const userInfo = Object.assign({}, { ...rest });
const token = createToken(userInfo);
const decodedToken = jwtDecode(token);
const expiresAt = decodedToken.exp;
res.status(201).json({
message: 'Authentication successfull!',
token,
userInfo,
expiresAt
});
} else {
res.status(403).json({
message: 'Wrong email or password.'
});
}
} catch (err) {
console.log(err);
return res.status(400).json({ message: 'Something Went totally wrong.' });
}
};
exports.signup = async (req, res) => {
try {
const { email, firstName, lastName, role } = req.body;
const hashedPassword = await hashPassword(req.body.password);
const userData = {
email: email.toLowerCase(),
firstName,
lastName,
password: hashedPassword,
role: role
};
const existingEmail = await User.findOne({ email: userData.email }).lean();
if (existingEmail) {
return res.status(400).json({ message: 'Email already exists' });
}
const newUser = new User(userData);
const savedUser = await newUser.save();
if (savedUser) {
const token = createToken(savedUser);
const decodedToken = jwtDecode(token);
const expiresAt = decodedToken.exp;
//FirstName,lastName,Email,Role = savedUser;
const userInfo = {
firstName,
lastName,
email,
role
};
return res.status(201).json({
message: 'User created!',
token,
userInfo,
expiresAt
});
} else {
return res.status(400).json({
message: 'There was a problem creating your account'
});
}
} catch (err) {
return res.status(400).json({
message: 'There was a problem creating your account',
error: err.message
});
}
};
this is my util functionality
const jwt = require('jsonwebtoken');
const jwtE = require('express-jwt');
const bcrypt = require('bcryptjs');
const dotenv= require('dotenv')
dotenv.config({ path: '.env' });
const createToken = user => {
// Sign the JWT
if (!user.role) {
throw new Error('No user role specified');
}
return jwt.sign({
sub: user._id,
email: user.email,
role: user.role,
iss: 'api.orbit',
aud: 'api.orbit'
},
process.env.JWT_SECRET,
{ algorithm: 'HS256', expiresIn: '1h' }
);
};
const hashPassword = password => {
return new Promise((resolve, reject) => {
bcrypt.genSalt(12, (err, salt) => {
if (err) {
reject(err);
}
bcrypt.hash(password, salt, (err, hash) => {
if (err) {
reject(err);
}
resolve(hash);
});
});
});
};
const verifyPassword = (passwordAttempt, hashedPassword) => {
return bcrypt.compare(passwordAttempt, hashedPassword);
};
const requireAdmin = (req, res, next) => {
if (!req.user) {
return res.status(401).json({
message: 'There was a problem authorizing the request'
});
}
if (req.user.role !== 'admin') {
return res.status(401).json({ message: 'Insufficient role' });
}
next();
};
const attachUser = (req, res, next) => {
const token = req.headers.authorization;
if (!token) {
return res.status(401).json({ message: 'Authentication invalid' });
}
const decodedToken = jwtDecode(token.slice(7));
if (!decodedToken) {
return res.status(401).json({
message: 'There was a problem authorizing the request'
});
} else {
req.user = decodedToken;
next();
}
};
const requireAuth = jwtE({
secret: process.env.JWT_SECRET,
audience: 'api.orbit',
issuer: 'api.orbit'
});
module.exports = {
createToken,
hashPassword,
verifyPassword,
requireAdmin,
attachUser,
requireAuth
};
this is my route
const express = require('express');
const userController = require('./../controllers/userController');
const authController = require('./../controllers/authController');
const router = express.Router();
const { attachUser, requireAuth } = require('../utils');
//Param middle is middleware that runs for certain param
//the only param that we have id
// router.param('id', (req, res, next, val) => {
// console.log(`product id is :${id}`)
// next()
// })
router.post('/signup', authController.signup);
router.post('/authenticate', authController.authenticate);
router.route('/')
.get(attachUser, requireAuth, userController.getAllUsers)
.post(attachUser, requireAuth, userController.createUser);
router.route('/:id')
.get(attachUser, requireAuth, userController.getUser)
.patch(attachUser, requireAuth, userController.updateUser)
.delete(attachUser, requireAuth, userController.deleteUser);
module.exports = router;
CodePudding user response:
First, you have to Generate a JWT token when the user successfully logged in...
exports.login = async (req, res, next) => {
const email = req.body.email;
const password = req.body.password;
let loadedUser;
try {
const user = await User.findOne({ email: email });
if (!user) {
const error = new Error("A user with this email could not be found.");
error.statusCode = 401;
throw error;
}
loadedUser = user;
const isEqual = await bcrypt.compare(password, user.password);
if (!isEqual) {
const error = new Error("Wrong password!");
error.statusCode = 401;
throw error;
}
const token = jwt.sign(
{
email: loadedUser.email,
userId: loadedUser._id.toString(),
},
"somesupersecretsecret",
{ expiresIn: "1h" }
);
res.status(200).json({ token: token, userId: loadedUser._id.toString() });
} catch (err) {
if (!err.statusCode) {
err.statusCode = 500;
}
next(err);
}
};
After that, you have to create an Auth Middleware
const jwt = require('jsonwebtoken');
module.exports = (req, res, next) => {
const authHeader = req.get('Authorization');
if (!authHeader) {
const error = new Error('Not authenticated.');
error.statusCode = 401;
throw error;
}
const token = authHeader.split(' ')[1];
let decodedToken;
try {
decodedToken = jwt.verify(token, 'somesupersecretsecret');
} catch (err) {
err.statusCode = 500;
throw err;
}
if (!decodedToken) {
const error = new Error('Not authenticated.');
error.statusCode = 401;
throw error;
}
req.userId = decodedToken.userId;
next();
};
After that, you can easily import this middleware and routes and use it for great User auth.