I'm developing full-stack,
with
Node,
Express,
Session-mysql,
passport...
like a title, my router.post has no res.
router.post('/', function(req, res) {
hasher({password: req.body.password, function(err, pass, salt, hash){
var account = {
authId: 'local:'+req.body.username,
username: req.body.username,
password: hash,
salt: salt,
displayName: req.body.displayName
};
var sql = 'INSERT INTO accounts SET ?';
conn.query(sql, account, function(err, results) {
if(err) {
console.log("signup_post_in_error");
res.status(500);
} else {
req.login(account, function(err) {
console.log(err);
req.session.save(function() {
res.redirect('/board');
})
})
}
});
}})
})
form(action='/signup' method='post')
when I click submit, there is no response.
Related
When ever I submit a from to login in or get registered I get 400 bad request. But in register route the user get registered but it also gives bad request. When we go to login route same as register route I get BAD REQUEST. 0
I am using the following dependencies:
express session
passport
passport-local
passport-local-mongoose
Is there something wrong with the implementation of the passport-local-mongoose or its passport side or serialize or deserialize the user. Can anybody help me with this problem I am stuck on this for three days. Here is some code.
//-----------------------//Require---------------------
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const ejs = require("ejs");
const session = require("express-session");
const passport = require("passport");
const LocalStrategy= require("passport-local").Strategy;
const passportLocalMongoose = require("passport-local-mongoose");
const mongoose = require("mongoose");
//-----------------------//App.use---------------------
app.use(express.static("public"));
app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({extended: true}));
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}));
//-----------------------//Passport---------------------
app.use(passport.initialize());
app.use(passport.session());
//-----------------------//Mongoose---------------------
mongoose.connect('mongodb://localhost/Twitter', {useNewUrlParser: true, useUnifiedTopology: true});
mongoose.set('useCreateIndex', true);
const tweetschema = new mongoose.Schema({
username: String,
password: String,
tweets: String
});
//-----------------------//Schema Plgin---------------------
tweetschema.plugin(passportLocalMongoose);
//-----------------------//New Model---------------------
const Tweet = new mongoose.model("Tweet", tweetschema);
//-----------------------//Local Strategy-------------------
passport.use(new LocalStrategy(Tweet.authenticate()));
//-----------------------//Seralize Passport---------------------
passport.serializeUser(Tweet.serializeUser());
passport.deserializeUser(Tweet.deserializeUser());
//-----------------------//Get Routes---------------------
app.get("/" ,(req, res)=>{
Tweet.find({}, function(err, founItems){
res.render("home", {founItems:founItems});
});
});
app.get("/tweets", (req, res)=>{
if(req.isAuthenticated()){
res.render("Tweets");
}else{
res.redirect("/login");
}
});
//-----------------------//Post Routes---------------------
app.post("/login", (req, res)=>{
const user = new Tweet({
username: req.body.email,
password: req.body.password
});
req.logIn(user, (err)=>{
if(err){
res.send(err);
}
passport.authenticate("local")(req, res, ()=>{
console.log("Successfull.");
})
})
});
app.post("/reg", (req, res)=>{
Tweet.register({username: req.body.email}, req.body.password, (err, user)=>{
if(err){
console.log(err);
res.redirect("/reg");
}else{
if(user){
passport.authenticate("local")(req, res, ()=>{
res.redirect("/tweets");
console.log("Successfully Regsitered The User!");
})
}
}
})
})
You redirect user to /login route, but you don't have get request for this.
If you have it but not uploaded try this in Seralize Passport
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
What about this:
app.post("/login", (req, res) => {
const email = req.body.email;
User.findOne({ username: email }, function (err, u) {
if (err) {
console.log(err);
} else {
if (u) {
u.authenticate(req.body.password, (err, model, info) => {
if (info) {
res.send("Wrong email or password!");
}
if (err) {
console.log(err);
} else if (model) {
req.login(u, (err) => {
if (err) {
console.log(err);
} else {
passport.authenticate("local");
req.session.save((error) => {
if (err) {
console.log(err);
} else {
res.redirect("/");
}
});
}
});
}
});
} else {
res.send("Wrong email or password!");
}
}
});
});
So you first search user in the database with email: User.findOne({ username: email }, function (err, u){} I suggest to make username unique username: { type: String, unique: true} in tweetSchema.
After that you check for err. If u exists, you authenticate it with password. According to passport-local-mongoose- u.authenticate(password, (err, model, info)=>{}) has two arguments: password and callback function. In callback we check for info which is "an instance of AuthenticationError describing the reason the password failed, else undefined." After that we check for err and it is "null unless the hashing algorithm throws an error." And finally, we check for model that is "the model getting authenticated if authentication was successful otherwise false."
So, model is authenticated. After that we must use the user with req.login(u,(err)). Check for errors and if everything is alright, we authenticate user locally passport.authenticate("local");. If you want to save session, write:
req.session.save((error) => {
if (err) {
console.log(err);
} else {
res.redirect("/");
}
});
That's all.
For registration :
app.post("/register", (req, res) => {
const email = req.body.email;
const password = req.body.password
User.find({ email: email }, function (err, docs) {
if (docs.length === 0) {
User.register(
{
username: email,
},
password,
function (err, user) {
if (err) {
console.log(err);
} else {
req.login(user, (err) => {
if (err) {
console.log(err);
} else {
passport.authenticate("local");
req.session.save((error) => {
if (err) {
console.log(err);
} else {
res.redirect("/");
}
});
}
});
}
}
);
} else {
res.send("The accout already exists!");
}
});
});
First of all, let me give you a warm thank you for giving a thought to this question.
So, what's the problem?
(This is a simple problem for most of you grandmasters!)
Well, the user can be registered to this simple app. But, for some reason, authentication doesn't work. That some reason is what my brain nerves having a hard time comprehending!
Having tried all the possible solutions for hours and hours, this novice-newbie decided to head over to the haven of veterans here in the StackOverflow!
Let me give you the code, so you can shed me some bright light!
Following is a capture of the code written for the authentication
//Authenticating the user
router.post('/authenticate', (req, res, next) => {
const username = req.body.username;
const password = req.body.password;
User.getUserByUsername(username, (err, user) => {
if (err) throw err;
if (!user) {
return res.json({
sucess: false,
msg: 'There is no such user found here'
});
}
User.comparePassword(password, user.password, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
const token = jwt.sign(user.toJSON(), config.secret, {
expiresIn: 604800 // 1 week
});
res.json({
success: true,
token: 'JWT' + token,
user: {
id: user._id,
name: user.name,
username: user.username,
email: user.email
}
});
} else {
return res.json({
success: false,
msg: 'Enter the correct details!'
});
}
});
});
});
//Getting into the dashboard
router.get('/profile', passport.authenticate('jwt', {
session: false
}),
(req, res, next) => {
res.json({
user: req.user
});
});
The next few pictures on your way shows you the POSTMAN requests that are done by this novice.
Here, a post request is done to register the user and as you can see, there's not a smidgen of a problem there; the user is, without a doubt, registered!
Here's the authentication done with POSTMAN
But now, for some reason (which I have zero clue of), the user is NOT authenticated. This is the problem that I need to solve.
Here is a code of the model/user.js file in case you want to know what's in there as well
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const config = require('../config/database');
// These are the collection or entities in ERD language
const UserSchema = mongoose.Schema({
name: {
type: String
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
}
});
const User = module.exports = mongoose.model('user', UserSchema); //User is the name give for this particular model's schema
// these are functions implemented to do a certain task
module.exports.getUserById = function (id, callback) {
User.findById(id, callback);
}
module.exports.getUserByUsername = function (username, callback) {
const query = {
username: username
}
User.findOne(query, callback);
}
module.exports.addUser = function (newUser, callback) {
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newUser.password, salt, (err, hash) => {
if (err) throw err;
newUser.password = hash;
newUser.save(callback);
});
})
}
//comparing the hash password
module.exports.comparePassword = function (candidatePasword, hash, callback) {
bcrypt.compare(candidatePasword, hash, (err, isMatch) => {
if (err) throw err;
callback(null, isMatch);
});
}
Thank You for your time!
Stay safe btw!
edit1: The code for the registration or signing up.
router.post('/signup', (req, res, next) => {
let newUser = new User({
name: req.body.name,
email: req.body.email,
username: req.body.username,
password: req.body.password
});
User.addUser(newUser, (err, user) => {
//console.log("registration is working");
if (err) {
res.json({
sucess: false,
msg: 'Hey! Enter the correct information man!'
});
} else {
res.json({
success: true,
msg: 'you are registered'
});
}
});
});
Here's the whole routes/users.js file for you to refer
const express = require('express');
const router = express.Router();
const passport = require('passport');
const jwt = require('jsonwebtoken');
const User = require('../models/user');
const config = require('../config/database');
// Signingup the user
router.post('/signup', (req, res, next) => {
let newUser = new User({
name: req.body.name,
email: req.body.email,
username: req.body.username,
password: req.body.password
});
User.addUser(newUser, (err, user) => {
//console.log("registration is working");
if (err) {
res.json({
sucess: false,
msg: 'Hey! Enter the correct information man!'
});
} else {
res.json({
success: true,
msg: 'you are registered'
});
}
});
});
//Authenticating the user
router.post('/authenticate', (req, res, next) => {
const username = req.body.username;
const password = req.body.password;
User.getUserByUsername(username, (err, user) => {
if (err) throw err;
if (!user) {
return res.json({
sucess: false,
msg: 'There is no such user found here'
});
}
User.comparePassword(password, user.password, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
const token = jwt.sign(user.toJSON(), config.secret, {
expiresIn: 604800 // 1 week
});
res.json({
success: true,
token: 'JWT' + token,
user: {
id: user._id,
name: user.name,
username: user.username,
email: user.email
}
});
} else {
return res.json({
success: false,
msg: 'Enter the correct details!'
});
}
});
});
});
//Getting into the dashboard
router.get('/profile', passport.authenticate('jwt', {
session: false
}),
(req, res, next) => {
res.json({
user: req.user
});
});
router.post('/login', (req, res, next) => {
let newUser = new User({
username: req.body.username,
password: req.body.password
});
User.addUser(newUser, (err, user) => {
if (err) {
res.json({
success: false,
msg: "Enter the correct information"
});
} else {
res.json({
success: true,
msg: "User loggedIn"
});
}
});
});
module.exports = router;
In your schema, you don't have the field username but your query is {username: username}. That's why you can't find any user match and get the response "There is no such user found here". Change your query to {name: username} may solve the problem.
I want to make create users with hash password, and when i am sending http request i have code error 500 Internal Server Error. Can someone tell me what is wrong??
router.post('/create', function (req, res, next) {
var newUser = {
login: req.body.login,
password: req.body.password,
}
bcrypt.hash(password, saltRounds, function (err, hash) {
if (err) {
console.log(err)
} else {
newUser.password = hash;
var user = new User(newUser);
user.save()
.then(function (User) {
res.send(User);
})
.catch((err) => {
console.log(err)
})
}
});
});
Hi All,
I am authenticating my user using bcrypt module.
I am able to do perform the Registration process, but facing problem during Login process.
User Model:
var userSchema = new Schema({
email: {type: String, required: true},
password: {type: String,
});
Hashing methods:
userSchema.methods.encryptPassword = function (password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(5), null)
};
userSchema.methods.validPassword = function (password) {
return bcrypt.compareSync(password, this.password);
};
Sign in:
module.exports.login = function (user, callback) {
User.findOne({'email': user.email, 'password': user.validPassword(this.password)}, callback);
};
Login Route
router.post('/login', function (req, res) {
var user = req.body;
User.login(user, function (err, user) {
if (err) {
throw err;
}
if (!user) {
res.sendStatus(404);
return;
}
res.json(user.id);
});
});
While executing am getting this error: TypeError:user.validPassword is not a function
Please Help.
Your mistake is that the user being provided to your login method is not a Mongoose DB object. Instead, your login function should look something like this:
module.exports.login = function (request, callback) {
User.findOne({'email': request.email }, function(err, user) {
if (err) return callback(err);
if(!user || !user.validPassword(request.password)) return callback();
return callback(null, user);
});
};
This will ensure that user is a valid Mongoose object before you attempt to verify the password.
One other possible solution, if you'd prefer to avoid checking that the password is valid in your data layer, is to simply fetch the user document based on its email and then check the password in the login route.
router.post('/login', function (req, res) {
var user = req.body;
User.findOne(user, function (err, user) {
if (err) {
throw err;
}
if (!user) {
res.sendStatus(404);
return;
}
if (!user.validPassword(req.body.password)) {
res.sendStatus(401);
return;
}
res.json(user.id);
});
});
In Login Route, you need to instantiate the Schema:
router.post('/login', function (req, res) {
var user = new User(req.body);
User.login(user, function (err, user) {
if (err) {
throw err;
}
if (!user) {
res.sendStatus(404);
return;
}
res.json(user.id);
});
});
Every time i refresh a html page at route 'localhost:8080/' or login a user I will get this Error: Can't set headers after they are sent. As far as I know this problem happens due to callbacks that are accidentally called twice. The app doesn't crash or anything, its just keep logging the same error on the console.
Here's the code.
var User = require('../models/user');
var Story = require('../models/story');
var jwt = require('jsonwebtoken');
var config = require('../../config');
var superSecret = config.secret;
module.exports = function(app, express) {
// creating our first router
var apiRouter = express.Router();
// signup a user
apiRouter.post('/signup', function(req, res) {
var user = new User({
name: req.body.name,
username: req.body.username,
password: req.body.password
});
user.save(function(err) {
if(err) res.send(err);
res.json({ message: 'User has been created!' });
});
});
apiRouter.get('/users', function(req, res) {
User.find({}, function(err, users) {
if(err) res.send(err);
res.json(users);
});
});
// user login
apiRouter.post('/login', function(req, res) {
User.findOne({
username: req.body.username
}).select('name username password').exec(function(err, user) {
if(err) throw err;
if(!user) {
res.json({ message: "Wrong User" });
} else if(user) {
var validPassword = user.comparePassword(req.body.password);
if(!validPassword) {
res.json({ message: "Invalid Password" });
} else {
var token = jwt.sign({
id: user._id,
name: user.name,
username: user.username
}, superSecret, {
expiresInMinute: 1440
});
// return all the sucess
res.json({
success: true,
message: "Successfully login and token created!" + token.name,
token: token
});
};
}
});
});
// write a middleware for login
// A middleware for login user only, once a user has logged in , he can enter other links below
apiRouter.use(function(req, res, next) {
// do logging
console.log("Somebody just came to our app!");
var token = req.body.token || req.param('token') || req.headers['x-access-token'];
// check if token exist
if(token) {
jwt.verify(token, superSecret, function(err, decoded) {
if(err) {
res.status(403).send({ success: false, message: 'Failed to authenticate user' });
} else {
// if everything is good save request for use in other routes
req.decoded = decoded;
next();
}
});
} else {
res.status(403).send({ success: false, message: 'No token provided' });
}
});
apiRouter.route('/')
.post(function(req, res) {
var story = new Story({
user: req.decoded.id,
content: req.body.content
});
story.save(function(err, stor) {
if(err) res.send(err)
console.log(stor);
res.json(stor);
});
})
.get(function(req, res) {
Story.find({ user: req.decoded.id }, function(err, story) {
if(err) res.send(err);
res.json(story);
});
});
apiRouter.get('/me', function(req, res) {
res.send(req.decoded.name);
});
apiRouter.route('/:user_id')
.get(function(req, res) {
User.findById(req.params.user_id, function(err, user) {
if(err) res.send(err);
res.json(user);
});
})
.put(function(req, res) {
User.findById(req.params.user_id, function(err, user) {
if(err) res.send(err);
if(req.body.name) {
user.name = req.body.name;
}
if(req.body.username) {
user.username = req.body.username;
}
if(req.body.password) {
user.password = req.body.password;
}
user.save(function(err) {
if(err) res.send(err);
res.json({ message: "User updated" });
});
});
});
return apiRouter;
}
You are sending a response twice when an error occurs:
if (err) res.send(err);
res.json(foo);
Replace that with:
if (err) { res.send(err); return; }
res.json(foo);