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')
Related
So I create my route user and I use this tutorial https://www.bezkoder.com/node-js-jwt-authentication-mysql/ to add the token and Authentication Token + validation name. Everything work great. But then when I beginning to create my route Comment (acces for every user), I had normaly the auth but even with the token Postman send me an "No token provided!". I have to add this token and autorize the acces but I don't know how. If somebody know how to do it, it would be great :D thx ! This is how I add my token on Postman
enter image description here
Here is my code:
My route comment:
const express = require("express");
const router = express.Router();
const commentCtrl = require("../controllers/comment");
const { authJwt } = require("../middleware");
router.post("/upload", [authJwt.verifyToken], commentCtrl.createComment);
module.exports = router;
The middleware token :
const jwt = require("jsonwebtoken");
const config = require("../config/auth.config.js");
verifyToken = (req, res, next) => {
let token = req.headers["x-access-token"];
if (!token) {
return res.status(403).send({
message: "No token provided!"
});
}
jwt.verify(token, config.secret, (err, decoded) => {
if (err) {
return res.status(401).send({
message: "Unauthorized!"
});
}
req.id = decoded.id;
next();
});
};
const authJwt = {
verifyToken: verifyToken,
};
module.exports = authJwt;
const authJwt = require("./authJwt");
const verifySignUp = require("./verifySignUp");
module.exports = {
authJwt,
verifySignUp
};
My verification SignUp:
const { User } = require("../models");
checkDuplicateEmail = async (req, res, next) => {
const user = await User.findOne({
where: {
email: req.body.email
}
}).then(user => {
if (user) {
res.status(400).send({
message: "Failed! Email is already in use!"
});
return;
}
next();
});
};
const verifySignUp = {
checkDuplicateEmail: checkDuplicateEmail
};
module.exports = verifySignUp;
And here is my user.controllers when is send the token:
const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");
const config = require("../config/auth.config");
const { User } = require("../models");
module.exports.signup = async (req, res) => {
if (!req.body.email || !req.body.password) {
res.status(400).send({
status: false,
message: 'une erreur dans create est survenu'
});
} else {
let { nom, prenom, email, password, status} = req.body;
const salt = await bcrypt.genSalt(10);
password = await bcrypt.hash(password, salt)
const user = await User.create({
nom, prenom, email, password, status
})
.then((user) => res.status(201).send(user)).catch((error) => {
console.log(error);
res.status(400).send(error);
});
}
};
module.exports.login = async (req, res) => {
const user = await User.findOne({
where: {
email: req.body.email
}
})
.then(user => {
if (!user) {
return res.status(404).send({ message: "User Not found." });
}
const passwordIsValid = bcrypt.compareSync(req.body.password, user.password);
if (!passwordIsValid) {
return res.status(401).send({
accessToken: null,
message: "Invalid Password!"
});
}
var token = jwt.sign({ id: user.id }, config.secret, {
expiresIn: 86400 // 24 hours
});
res.status(200).send({
id: user.id,
nom: user.nom,
email: user.email,
password: user.password,
accessToken: token
});
})
.catch(err => {
res.status(500).send({ message: err.message });
});
};
While it would have helped if you had provided a screenshot of where you are putting your token on postman, make sure you are using the appropriate header. According to your code, you are searching the 'x-access-token' header, so in postman, you should attach your jwt token to the same header property. It should be something like this:
postman x-access-token demo
I was working on a MERN app and was trying to use jason web-token (JWT) and bcrypt for authentication. It uses two routes for signup and authentication. However, I'm getting an internal server error coming from admin route not sure though. I have not been able to connect to the frontend correctly because of that.
//admin model
const mongoose = require('mongoose');
const jwt = require('jsonwebtoken');
const Joi = require('joi');
const passwordComplexity = require('joi-password-complexity');
const AdminSchema = new mongoose.Schema({
name: { type: String, required:true },
email: { type: String, required:true, unique:true },
password: { type: String, required:true, },
});
AdminSchema.methods.generateAuthToken = function(){
const token=jwt.sign({_id:this._id}, process.env.JWTPRIVATEKEY,{expiresIn: "7d",});
return token;
}
const AdminModel = mongoose.model("admin", AdminSchema)
const validate=(data) =>{
const schema= Joi.object({
name:Joi.string().required().label("Name"),
email:Joi.string().email().required.label("Email"),
password:passwordComplexity().required().label("Password")
});
return schema.validate(data)
};
module.exports = {AdminModel, validate};
//module.exports = AdminModel;
//admin route
const router= require("express").Router();
const {AdminModel, validate} = require("../models/admin");
const bcrypt = require("bcrypt");
router.post("/", async(req,res) =>{
try {
const {error} = validate(req.body);
if(error)
return res.status(400).send({message: error.details[0].message});
const user = await AdminModel.findOne({email: req.body.email});
if(user)
return res.status(409).send({message:"Admin with given email exists"});
const salt = await bcrypt.genSalt(Number(process.env.SALT));
const hashPassword = await bcrypt.hash(req.body.password, salt);
await new AdminModel({ ...req.body, password:hashPassword}).save();
res.status(201).send({message:"Admin created successfully"})
} catch (error) {
res.status(500).send({message:"Internal Server Error YOu see"})
}
})
module.exports = router;
//adminAuthentication route
const router = require("express").Router();
const {AdminModel} = require("../models/admin");
const bcrypt = require("bcrypt");
const Joi = require("joi");
router.post("/", async (req, res) => {
try {
const { error } = validate(req.body);
if (error)
return res.status(400).send({ message: error.details[0].message });
const Admin = await AdminModel.findOne({ email: req.body.email });
if (!Admin)
return res.status(401).send({ message: "Invalid Email or Password" });
const validPassword = await bcrypt.compare(
req.body.password,
Admin.password
);
if (!validPassword)
return res.status(401).send({ message: "Invalid Email or Password" });
const token = Admin.generateAuthToken();
res.status(200).send({ data: token, message: "logged in successfully" });
} catch (error) {
res.status(500).send({ message: "Internal Server Error" });
}
});
const validate = (data) => {
const schema = Joi.object({
email: Joi.string().email().required().label("Email"),
password: Joi.string().required().label("Password"),
});
return schema.validate(data);
};
module.exports = router;
I have created a middleware folder inside it I have created fetchuser.js
This is my fetchuser.js code, I have created getuser endpoint so that I can authenticate the user.
I have created a new post request in my thunderclient, but because of this error I am not able to do anything
...
const jwt = require('jsonwebtoken');
const JWT_SECRET = "Saurabhisgood$ouy";
const fetchuser = (req, res, next) => {
// Get the user from jwt token and id to req object
const token = req.header('auth-token');
if (!token) {
res.status(401).send({ error: "Please authenticate using a valid token" })
}
try {
const data = jwt.verify(token, JWT_SECRET)
req.user = data.user;
next();
} catch (error) {
res.status(401).send({ error: "Please authenticate using a valid token" })
}
}
module.exports = fetchuser();
...
This is auth.js file
...
const express = require('express');
const User = require('../models/User');
const router = express.Router();
const { body, validationResult } = require('express-validator');
const bcrypt = require('bcryptjs');
const JWT_SECRET = "Saurabhisgood$ouy";
const jwt = require('jsonwebtoken');
const fetchuser = require('../middleware/fetchuser');
// Create a user using : POST "/api/auth/createuser". Doesn't require auth. Dosen't require login
router.post('/createuser', [
body('name', 'Name should be atleast 3 characters').isLength({ min: 3 }),
body('email', 'Email should be unique').isEmail(),
body('password', 'Password must be atleast 5 characters').isLength({ min: 5 }),
], async (req, res) => {
// If there are errors then you will get bad request
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
// Check whether the user with the same email exists
try {
let user = await User.findOne({ email: req.body.email });
if (user) {
return res.status(400).json({ error: "The user with this email already exists" })
}
const salt = await bcrypt.genSalt(10);
const secPass = await bcrypt.hash(req.body.password, salt);
// Create a new user
user = await User.create({
name: req.body.name,
email: req.body.email,
password: secPass
});
const data = {
user: {
id: user.id
}
}
const authToken = jwt.sign(data, JWT_SECRET);
// console.log(jwtData);
// res.json(user);
res.json({authToken});
} catch (error) {
console.error(error.message);
res.status(500).send("Internal server error")
}
})
// Authenticate a user using : POST "/api/auth/login". Doesn't require auth. Dosen't require login
router.post('/login', [
body('email', 'Email should be unique').isEmail(),
body('password', 'Password cannot be blank').exists(),
], async (req, res) => {
// If there are errors then you will get bad request
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
};
const { email, password } = req.body;
// Check whether the user with the same email exists
try {
let user = await User.findOne({email});
if (!user) {
return res.status(400).json({ error: "Please enter the valid credentials" })
}
const passwordComapare= await bcrypt.compare(password, user.password);
if (!passwordComapare) {
return res.status(400).json({ error: "Please enter the valid credentials" })
}
const data = {
user: {
id: user.id
}
}
const authToken = jwt.sign(data, JWT_SECRET);
// console.log(jwtData);
// res.json(user);
res.json({authToken});
} catch (error) {
console.error(error.message);
res.status(500).send("Internal server error")
}
})
// Get details of logged in user using : POST "/api/auth/getuser". Require login
router.post('/getuser', fetchuser , async (req, res) => {
try {
userId= req.user.id;
const user= await User.findById(userId).select("-password");
res.send(user);
} catch (error) {
console.error(error.message);
res.status(500).send("Internal server error")
}
})
module.exports = router
...
You invoking the middleware automatically, change:
module.exports = fetchuser();
to:
module.exports = fetchuser;
I'm trying to login using the id from mongoDB but nodejs keeps giving me this error about user...
(node:13612) UnhandledPromiseRejectionWarning: ReferenceError: user is not defined
registering the user is alright but when calling the login ..... it crashs although everything is defined and I can't figure out why its not reading user from the database
...
const express = require("express");
const { findOne } = require("../models/User");
const router = express.Router();
const User = require("../models/User");
const bcrypt = require("bcryptjs");
const { registerValidation, loginValidation } = require("../validation");
const jwt = require("jsonwebtoken");
router.post("/register", async (req, res) => {
//VALIDATE DATA
const { error } = registerValidation(req.body);
if (error) return res.status(400).send(error.details[0].message);
//CHECK IF USER EXISTS
const emailExist = await User.findOne({ email: req.body.email });
if (emailExist) return res.status(400).send("Email already exists!");
//HASH THE PASSWORD
const salt = await bcrypt.genSalt(10);
const hashPassword = await bcrypt.hash(req.body.password, salt);
//CREATE NEW USER
const user = new User({
name: req.body.name,
email: req.body.email,
password: hashPassword,
});
try {
const savedUser = await user.save();
res.send({user:user._id});
} catch (error) {
res.status(400).send(error);
}
});
router.post("/login", async (req, res) => {
//VALIDATE DATA
const { error } = loginValidation(req.body);
if (error) return res.status(400).send(error.details[0].message);
//CHECK IF USER EXISTS
const emailExist = await User.findOne({ email: req.body.email });
if (!emailExist) return res.status(400).send("Email or Password is Wrong");
//CREATE AND ASSIGN TOKEN
const token = jwt.sign({ _id: user._id }, process.env.TOKEN_SECRET);
res.header("auth-token", token).send(token);
});
module.exports = router;
The issue is an undefined variable:
const token = jwt.sign({ _id: user._id }, process.env.TOKEN_SECRET);
The user (user._id) variable in the line above isn't defined in the Login route, perhaps you meant to find the user first, then to assign the JWT Token?
I am trying to get the name and other info from the jwt and I can so far only get the Id of the user.
This is the routes folder for authentication
const config = require("config");
const jwt = require("jsonwebtoken");
const { User } = require("../models/user");
const mongoose = require("mongoose");
const express = require("express");
const Joi = require("joi");
const _ = require("lodash");
const bcrypt = require("bcrypt");
const router = express.Router();
router.post("/", async (req, res) => {
const { error } = validate(req.body);
if (error) return res.status(400).send(error.details[0].message);
let user = await User.findOne({ email: req.body.email });
if (!user) return res.status(400).send("Invalide email or password.");
//compare the passowrd in the body and the password entered when registeration
const validePassword = await bcrypt.compare(req.body.password, user.password);
if (!validePassword)
return res.status(400).send("Invalide email or password.");
const token = user.generateAuthToken();
res.send(token);
});
function validate(req) {
const schema = {
email: Joi.string()
.required()
.min(5)
.max(250)
.email(),
password: Joi.string()
.required()
.min(7)
.max(1024)
};
return Joi.validate(req, schema);
}
module.exports = router;
this is the middleware folder
const jwt = require("jsonwebtoken");
const config = require("config");
module.exports = function(req, res, next) {
const token = req.header("x-auth-token");
if (!token) return res.status(401).send("Access denied. No token provided.");
try {
const decoded = jwt.verify(token, config.get("jwtPrivateKey"));
req.user = decoded;
next();
} catch (ex) {
res.status(400).send("Invalid token.");
}
};
This is the function for getting the current user when they are logged in...
export function getCurrentUser() {
try {
const jwt = localStorage.getItem(tokenKey);
return jwtDecode(jwt);
} catch (ex) {
return null;
}
}
This is all I have in my profile component file where the ComponentDidMount is located...
import React, { Component } from "react";
import { Link } from "react-router-dom";
import NavBar from "./navBar";
import "../profile.css";
import { getCurrentUser } from "../services/authService";
class Profile extends Component {
state = {};
async componentDidMount() {
const currentUser = await getCurrentUser();
console.log(currentUser)
}
When I log the the currentUser this is what I get...
{_id: "5d96a81f9a2f1a8bd485f76c", iat: 1570751361}
iat: 1570751361
_id: "5d96a81f9a2f1a8bd485f76c"
PLEASE HELP
if you need username in payload,you need to add username when you sign the token.If you can't sign with username for some reason,write another service to return username from userId or whatever field exist in your jwt.
userSchema.methods.generateAuthToken = function() {
const token = jwt.sign( { _id: this._id,
isAdmin: this.isAdmin,
_username:this.username },
config.get("jwtPrivateKey") );
return token;
};
i have added new _username:this.username key value pair inside the jwt.sign function, _username is the key and this.username should be your actual username which is in the database.