My problem is when I make a request to POST /users/login with true data I receive no response instead the catch throw 400
routs file :
const express = require("express");
const router = new express.Router();
const User = require("../models/user");
router.post("/users/login", async (req, res) => {
try {
const user = await User.findByCredentials(
req.body.email,
req.body.password
);
// console.log(user);
res.send({ user });
} catch (e) {
res.status(400).send();
}
});
module.exports = router;
user middleware
userSchema.static.findByCredentials = async (email, password) => {
const user = await User.findOne({ email: email });
if (!user) {
throw new Error("Unable to find the user");
}
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
throw new Error("uncorect password");
}
return user;
};
Not all the code here, but I am sure the problem is in these lines,
In user middleware it should be statics(plural)
userSchema.statics.findByCredentials = async (email, password) => {
})
Related
I put the wrong password but it gets login successfully and the data which is inside a particular user is as a new user login. I want you to please tell me a error.
Link of an online hosted project: NOTEBOOK/login
Link of GitHub repository: GITHUB/notebook
The login folder is inside routes/auth.js
const express = require('express');
const router = express.Router();
const User = require('../models/User')
const { body, validationResult } = require('express-validator');
var bcrypt = require('bcryptjs');
var jwt = require('jsonwebtoken');
let fetchuser = require('../middleware/fetchuser')
const dotenv = require('dotenv');
dotenv.config();
const secret=process.env.YOUR_SECRET
router.post('/login', [
body('email', 'Enter a valid Email').isEmail(),
body('password', 'Password cannot be blank').exists()
], async (req, res) => {
let success=false;
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const { email, password } = req.body;
try {
// check whether user with this email exist
let user = await User.findOne({ email });
if (!user) {
return res.status(400).json({success, error: "Please login using correct credentials" })
};
let passwordCompare = bcrypt.compare(password, user.password);
if (!passwordCompare) {
return res.status(400).json({success, error: "Please login using correct credentials" })
};
const data = {
user: {
id: user.id
}
}
var authtoken = jwt.sign(data, secret);
success=true;
res.json({success, authtoken })
} catch (error) {
console.log(error.message);
res.status(500).send("Internal server error has occured")
}
})
you need to wait for the promise to resolve, you can opt for any of the below options
const passwordCompare = await bcrypt.compare(password, user.password);
OR
const passwordCompare = bcrypt.compareSync(password, user.password);
OR
bcrypt.compare(password, user.password).then(function(result) {
// result == true
});
I have this block of code and when a user login, it should set the "access_token" cookie to a token, but when i check the browser application cookie, i see nothing and user is unauthenticated.
const login = async (req, res) => {
try {
const oneUser = await Users.findOne({ username: req.body.username });
if (!oneUser) {
return res.status(403).json("No such user in the database");
}
const isPassword = await bcryptjs.compare(req.body.password, oneUser.password);
if (!isPassword) {
return res.status(500).json("Password is incorrect");
}
const token = jwt.sign(
{
id: oneUser._id,
isAdmin: oneUser.isAdmin,
},
process.env.jwt,
);
const { password, ...others } = oneUser._doc;
res
.cookie("access_token", token)
.status(200)
.json({ ...others });
} catch (err) {
res.status(500).json(err);
}
};
in the routes auth file i call it like so
router.post("/login", login);
then in my index.html file, i linked the routes up.
app.use("/api/auth", authRoute);
I am trying to show the page only if the Jsonwebtoken is verified and the user is logged on to the website, else show him the sign-in page.
However, I can see the token is generated in MongoDB, and also when I console log I can see that it is all good. But the issue is when I try to verify it using an already generated jwt token i.e.
req.cookies.signinToken
it shows an error.
Please the detail code below:
On app.js
const dotenv = require("dotenv");
const mongoose = require("mongoose");
const express = require("express");
const app = express();
const jwt = require("jsonwebtoken");
const cookieParser = require("cookie-parser");
dotenv.config({ path: "./config.env" });
require("./db/connection");
app.use(express.json());
app.use(cookieParser());
app.use(require("./router/route"));
const PORT = process.env.PORT;
app.listen(5000, () => {
console.log(`server running on ${PORT}`);
});
On route.js
const express = require("express");
const bcrypt = require("bcrypt");
const router = express.Router();
const jwt = require("jsonwebtoken");
require("../db/connection");
const User = require("../model/newUserSchema");
const auth = require("../middleware/auth");
// router.get("/", (req, res) => {
// res.send("hello am backend sever");
// });
//Signup or Register Part
router.post("/signup", async (req, res) => {
const { username, email, cpassword, retypePassword } = req.body;
if (!username || !email || !cpassword || !retypePassword) {
return res.status(422).json({ error: "please enter valid details" });
}
try {
const UserExist = await User.findOne({ email: email });
if (UserExist) {
return res.status(422).json({ error: "email already exist" });
} else if (cpassword !== retypePassword) {
return res.status(422).json({ error: "password incorrect" });
} else {
const user = new User({
username,
email,
cpassword,
retypePassword,
});
const userResgister = await user.save();
if (userResgister) {
return res.status(201).json({ message: "signup successfully" });
}
}
} catch (error) {
console.log(error);
}
});
//Login Part
router.post("/signin", async (req, res) => {
try {
const { email, cpassword } = req.body;
if (!email || !cpassword) {
return res.status(400).json({ error: " please enter valid credentials" });
}
const userLogin = await User.findOne({ email: email });
const token = userLogin.generateAuthToken();
res.cookie("signinToken", token, {
expires: new Date(Date.now() + 25892000000),
httpOnly: true,
});
if (userLogin) {
const isMatch = await bcrypt.compare(cpassword, userLogin.cpassword);
if (isMatch) {
return res.status(200).json({ message: "sigin in scuccessfully" });
} else {
return res.status(400).json({ error: " Invalid credentials" });
}
} else {
return res.status(400).json({ error: " Invalid credentials " });
}
} catch (error) {
console.log(error);
}
});
//watchlistpage
router.get("/watchlist", auth, (req, res) => {
console.log(" this is jwt token test " + req.cookies.signinToken);
res.send(req.rootuser);
console.log(req.rootuser);
});
module.exports = router;
On newUserSchema.js:
const mongoose = require("mongoose");
const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");
const newUserSchema = new mongoose.Schema({
username: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
cpassword: {
type: String,
required: true,
},
retypePassword: {
type: String,
required: true,
},
tokens: [
{
token: {
type: String,
required: true,
},
},
],
});
newUserSchema.pre("save", async function (next) {
if (this.isModified("cpassword")) {
this.cpassword = await bcrypt.hash(this.cpassword, 12);
this.retypePassword = await bcrypt.hash(this.retypePassword, 12);
}
next();
});
newUserSchema.methods.generateAuthToken = async function () {
try {
let token = jwt.sign({ _id: this._id }, process.env.SECRETKEY);
this.tokens = this.tokens.concat({ token: token });
await this.save();
return token;
} catch (error) {
console.log(error);
}
};
const User = mongoose.model("newUser", newUserSchema);
module.exports = User;
On auth.js (this is also my middleware)
const jwt = require("jsonwebtoken");
const User = require("../model/newUserSchema");
const Auth = async (req, res, next) => {
try {
console.log(JSON.stringify(req.cookies.signinToken) + " this is jwt token test");
const token = req.cookies.signinToken;
const verifytoken = jwt.verify(token, process.env.SECRETKEY);
const rootuser = await User.findOne({ _id: verifytoken._id, "tokens.token": token });
if (!rootuser) {
throw new Error("user not found");
}
req.token = token;
req.rootuser = rootuser;
req.UserID = rootuser._id;
next();
} catch (error) {
res.status(401).send("Unauthorized access");
console.log(error);
}
};
module.exports = Auth;
The API call result in postman
The terminal error :
when I try to console log on route.js inside Signin page i see promise pending
const token = userLogin.generateAuthToken();
console.log(token);
res.cookie("signinToken", token, {
expires: new Date(Date.now() + 25892000000),
httpOnly: true,
});
Could you please help to correct the error also please let me know why is this error coming?
Thanks a million in advance for any tips or suggestions.
Hi Thanks for the help
I just saw that my token was returning a promise, I did not add the keyword await before the token other thing was I was trying to access it before the validation, hence it was showing me nodata and error.
Please see the correct code below:
//Login Part
router.post("/signin", async (req, res) => {
try {
const { email, cpassword } = req.body;
if (!email || !cpassword) {
return res.status(400).json({ error: " please enter valid credentials" });
}
const userLogin = await User.findOne({ email: email });
if (userLogin) {
const isMatch = await bcrypt.compare(cpassword, userLogin.cpassword);
const token = await userLogin.generateAuthToken();
console.log(token);
res.cookie("signinToken", token, {
expires: new Date(Date.now() + 25892000000),
httpOnly: true,
});
if (isMatch) {
return res.status(200).json({ message: "sigin in scuccessfully" });
} else {
return res.status(400).json({ error: " Invalid credentials" });
}
} else {
return res.status(400).json({ error: " Invalid credentials " });
}
} catch (error) {
console.log(error);
}
});
I hope this might help other learners too.
Thanks.
const express = require('express');
const router = express.Router();
const auth = require('../../middleware/auth');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const config = require('config');
const { check, validationResult } = require('express-validator');
const User = require('../../models/User');
// #route Get api/auth
// #desc Test route
// #access Public
router.get('/', auth, async (req, res) => {
try {
const user = await User.findById(req.user.id).select('-password');
res.json(user);
} catch(err) {
console.error(err.message);
res.status(500).send('Server Error')
}
});
// #route POST api/auth
// #desc Authenticate User And Get Token
// #access Public
router.post('/',
[
check('email', 'Please include a valid email').isEmail(),
check('password', 'Password is required').exists()
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array()});
}
const { email, password } = req.body;
try {
// See if user exists
let user = await User.findOne({ email})
if (!user) {
return res
.status(400)
.json({ errors: [ { msg: 'Invalid Credentials Email' } ] });
}
// Make Sure Password matches
const isMatch = await bcrypt.compare(password, user.password);
if(!isMatch) {
return res
.status(400)
.json({ errors: [ { msg: 'Invalid Credentials Password' } ] });
}
const payload = {
user: {
id: user.id
}
}
jwt.sign(
payload,
config.get('jwtSecret'),
{ expiresIn: 360000 },
(err, token) => {
if(err) throw err;
res.json({ token });
}
);
} catch(err) {
console.error(err.message);
res.status(500).send('Server error')
}
});
module.exports = router
In my database I have email and password
in my postman when i make POST request to https://localhost:5000/api/auth
the email is correct however I keep getting password is not correct with this const isMatch = await bcrypt.compare(password, user.password);
if(!isMatch) {
return res
.status(400)
.json({ errors: [ { msg: 'Invalid Credentials Password' } ] });
}
i console logged both password and user.password and it is the same value, i dont understand why !isMatch is keep getting triggered
can anyone help me
The syntax of bcrypt.compare() is:
bcrypt.compare(plaintextPassword, hash)...
The first parameter is plaintext password and second is hash of the real password so it will not be the same value. As you mentioned that your password and user.password is the same value, I guess you forgot to hash user password before saving it to the DB. Please check the docs for more details.
usersRouter.post('/register', checkNotAuthenticated, async (req, res) => {
console.log(req.body)
const salt = await bcrypt.genSalt();
const hashedPassword = await bcrypt.hash(req.body.password, salt);
const user = new User ({
name: req.body.name,
email: req.body.email,
password: hashedPassword
})
try {
await user.save();
res.redirect(201, '../users/login') /* 200 means accepted status, 201 created resource */
} catch {
res.redirect(500, 'users/register') /* Internal server error */
}
});
usersRouter.post('/login', async (req, res) => {
const user = await User.find({email: req.body.email})
console.log(user)
if (!user) {
return res.send('User does not exist')
}
try {
if (!await bcrypt.compare(req.body.password, user.password)) {
return res.status(401).send('password failed') /* user Unauthorized */
} else {
return res.status(200).send('password validated');
}
} catch (err) {
res.send(err.message)
}
})
In /register path
When I try to make a request, console.log(req.body) = [Object: null prototype] { name: 'p', email: 'p#p', password: '1' }
In /login path
console.log(user) = [], instead of the registered user
console.log(user.email) = undefined; instead of the registered user email