ReactJs and Passport Auth - node.js

m trying to make auth system with react and Passport js
My passport look like this:
let passport = require('passport');
let User = require('../models/user');
let localStorage = require('passport-local').Strategy;
passport.serializeUser(function(user, done){
done(null, user.id)
});
passport.deserializeUser(function(id, done){
User.findById(id, (err, user) => {
done(err, user)
})
});
passport.use('local.signup', new localStorage({
usernameField: 'email', passwordField: 'password', passReqToCallback: true
}, function(req, email, password, done){
//Check valid
req.checkBody(req.body.email, 'Invalid email').notEmpty().isEmail();
req.checkBody(req.body.password, 'Invalid password').notEmpty().isLength({min: 4});
req.checkBody(req.body.name, 'Name is require!').notEmpty();
let errors = req.validationErrors(); //Get all errors for checkBody
if(errors){
let messages = [];
errors.forEach(function(error){
messages.push(error.msg)
});
return done(null, false, req.flash('error', messages));
}
User.findOne({'email': req.body.email}, function(err, user){
if(err) return done(err);
if(user) return done(null, false, {message: 'Email is already in use'});
var newUser = new User();
newUser.email= req.body.email;
newUser.password = newUser.encryptPassword(req.body.password);
newUser.name = req.body.name;
newUser.save((err, user) => {
if(err) return done(err);
return done(null, user);
})
})
}));
My route file:
const express = require('express');
const passport = require('passport');
let router = express.Router();
let User = require('../models/user');
router.post('/signup', passport.authenticate('local.signup', {
failureRedirect: '/', failureFlash: true
}), function(req, res,next){
console.log('Yes signUp');
});
module.exports = router;
React file:
handleChange = ev => {
this.setState({[ev.target.name]: ev.target.value});
}
onSubmit = ev => {
ev.preventDefault();
let user = {
name: this.state.name,
email: this.state.email,
password: this.state.password
}
axios.post('http://localhost:3001/signup', user)
.then(res=> { console.log(res) })
.catch(err=> { console.error(err) })
}
render() {
return (
<div className="container login-container">
<div className="title-login text-center">Login</div>
<hr/>
<div className="login-form">
<div className="form-group">
<input type="email" className="form-control" name="email" value={this.state.email} placeholder="Enter your Email.." onChange={this.handleChange} />
</div>
<div className="form-group">
<input type="text" className="form-control" name="name" value={this.state.name} placeholder="Enter your Name.." onChange={this.handleChange} />
</div>
<div className="form-group">
<input type="password" className="form-control" name="password" value={this.state.password} placeholder="Enter your password.." onChange={this.handleChange} />
</div>
<button className="btn btn-outline-primary btn-block" onClick={this.onSubmit}>Send</button>
</div>
</div>
)
}
The error is:
OPTIONS http://localhost:3001/ 404 (Not Found) signup:1 Failed to load
http://localhost:3001/: Response for preflight has invalid HTTP status
code 404. index.js:2178 Error: Network Error
at createError (createError.js:16)
at XMLHttpRequest.handleError (xhr.js:87)
Help!

Related

Problem with logIn page With authentcation

When i sign up a new mail it's redirect to logIn page, in router.post('/login') I added successRedirect: '/' and
failureRedirect: '/test' but it in anyway it redirect to /test even if it's success!
index.js
var express = require('express');
var router = express.Router();
const users = require('../model/db');
const { check, validationResult } = require('express-validator');
const passport = require('passport');
//GET login
router.get('/login', (req, res, next)=>{res.render('login')});
router.post('/login', passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/test',
failureFlash: true,
}));
router.get('/signup', function (req, res, next){
const msg = req.flash('error')
res.render('signup');
});
router.post('/signup', [
check('password').isLength({ min: 5 }).withMessage('Please enter Password with more than 5 letters!'),
check('password').not().isEmpty().withMessage('Please fill password fie'),
check('repassword').custom((val, {req})=>{
if(val !== req.body.password){
throw new Error('Password is not equal to confirm password');
}
return true;
})
],
function (req, res, next){
const newUser = new users({
email : req.body.email,
password : new users().hashPassword(req.body.password)
});
users.findOne({email : req.body.email}, (err, doc)=>{
if(err){
console.log('ERR while getting username =>' + err);
return ;
}
if(doc){
res.send('this email is already registered before!');
return ;
}
newUser.save((err, doc)=>{
if(err){
console.log('err' + err)
}else{
res.redirect('/login')
}
});
});
// Finds the validation errors in this request and wraps them in an object with handy functions
const errors = validationResult(req);
if (!errors.isEmpty()) {
var validationMessage = [];
for(var i = 0; i<errors.errors.length; i++){
validationMessage.push(errors.errors[i].msg);
}
req.flash('error', validationMessage)
res.redirect('signup')
}
});
module.exports = router;
According to these two lines of code,
router.post('/login', passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/test',
failureFlash: true,
}));
It should Redirect me to /test if it failed and To / if it succeeded
login.hbs
<div class="container">
<div class="s-f">
<div class="card">
<div class="card-body">
<div>
<h6>Log in | Coursatak</h6>
</div>
<form action="/login" method="post">
<div class="form-group">
<label for="email">Email</label>
<input type="text" name="email" id="email" class="form-control">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" name="password" id="password" class="form-control">
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary"> Sign Up</button>
</div>
<div>
<p class='if'></span>Sign Up, <span>If you already registered before.</p>
</div>
</form>
</div>
</div>
</div>
</div>
config/conficuration.js
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcryptjs');
const User = require('../model/students');
module.exports = function(passport) {
passport.use(
new LocalStrategy('local', { usernameField: 'email' }, (email, password, done) => {
// Match user
User.findOne({email: email}).then(user => {
if (!user) {
return done(null, false, { message: 'That email is not registered' });
}
bcrypt.compare(password, student.password, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, false, { message: 'Password incorrect' });
}
});
});
})
);
};
Schema
const mongoose = require('mongoose');
const bcrypt = require('bcrypt-nodejs');
const stDB = mongoose.Schema({
email : {
type: String,
required: true
},
password : {
type: String,
required: true
}
});
stDB.methods.hashPassword = function(password){
return bcrypt.hashSync(password, bcrypt.genSaltSync(10));
}
stDB.methods.comparePasswords = (password, hash) => {
return bcrypt.compareSync(password,hash)
}
module.exports = mongoose.model('db', stDB);
Node Version: 10.16.1
Express Version: 4.16.1
I dont know what you have at your app.js file , however paste the following code snippet at your app.js file and dismiss the config/conficuration.js
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
//after your modules
//passport login local login system
passport.serializeUser(function (user, done) {
//console.log('in serializeUser method user:' + user);
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
//console.log('in deserializeUser method id:' + id);
User.findById(id, function (err, user) {
done(err, user);
});
});
passport.use(
new LocalStrategy('local', { usernameField: 'email' }, (email, password, done) => {
// Match user
User.findOne({email: email}).then(user => {
if (!user) {
return done(null, false, { message: 'That email is not registered' });
}
bcrypt.compare(password, student.password, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, false, { message: 'Password incorrect' });
}
});
});
})
);
//after you initialize your sessions
app.use(passport.initialize());
app.use(passport.session());

Password confirmation with Passport

I've created a basic user registration form which works fine but I need to add a confirm password field.
My form is as follows:
<div class ="container form">
<div class="jumbotron form"><h2><i class="fa fa-user-plus" aria-hidden="true"></i> Signup</h2></div>
<form action = "/register" method="POST">
<div class="form-group">
<i class="fa fa-user" aria-hidden="true"></i>
<label for="username">Username</label>
<input type = "text" class = "form-control" placeholder = "Enter username" name="username">
</div>
<div class="form-group">
<i class="fa fa-key" aria-hidden="true"></i>
<label for="password">Password</label>
<input type = "password" class ="form-control" placeholder = "Enter password" name="password1">
</div>
<div class="form-group">
<i class="fa fa-key" aria-hidden="true"></i>
<label for="password">Confirm password</label>
<input type = "password" class ="form-control" placeholder = "Enter password" name = "password">
</div>
<div class="form-group">
<i class="fa fa-picture-o" aria-hidden="true"></i>
<label for="img">Image</label>
<input type = "text" class ="form-control" placeholder = "Enter image URL" name = "image">
</div>
<button type ="submit" class="btn btn-primary btn-lg">Signup</button>
</form>
</div>
So when a user hits submit, I obviously need the 2 password inputs to match and an error to be thrown if they don't.
I'm using Passport for authenitcation. I have the following setup:
// passport configuration
app.use(require("express-session")({
secret: "maidenJones",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.use(expressSanitizer());
app.use(function(req, res, next){
res.locals.currentUser = req.user;
res.locals.error = req.flash("error");
res.locals.success = req.flash("success");
next();
});
Register route:
router.post("/register", function(req, res){
var newUser = new User({username: req.body.username, image: req.body.image});
User.register(newUser, req.body.password, function(err, user){
if(err){
res.redirect("/blogs");
console.log(err);
}
passport.authenticate("local")(req, res, function(){
res.redirect("/blogs");
});
});
});
Not sure where to start to implement the password confirmation check
You have to move your registration logic inside the passport LocalStrategy and then use that strategy as a middleware in your routes.
Example:
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'passwd'
},
function(req, username, password, done) {
// User register logic
}
));
router.post('/register',
passport.authenticate('local', { failureRedirect: '/register' }),
function(req, res) {
res.redirect('/blogs');
});
more info here: passport-localstrategy
passport.use('local.signup', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
},
function (req, email, password, done) {
//All validation logic comes here
let password1 = req.body.password;
let password2 = req.body.password2;
req.checkBody('email', 'Invalid email').notEmpty().isEmail();
req.checkBody('password', 'Password must be more than 4 characters')
.not().isEmpty().isLength({ min: 4 });
let errors = req.validationErrors();
//just to see the output in your console
console.log(password1);
console.log(password2);
if (errors) {
let messages = [];
errors.forEach(function (error) {
messages.push(error.msg);
});
return done(null, false, req.flash('error', messages));
} else if (password1 !== password2) {
return done(null, false, req.flash('error', 'Password and Confirm Password must match'));
}
// You can then continue your code logic(submitting to database)

Nodejs Passport Local Strategy always failing

I am new to the whole user authentication things with node and I am trying to learn how to use Passport's LocalStrategy to add users to a Mongo database.
I'm trying to follow a particular tutorial and for some reason things aren't going to plan. Whenever I submit the registration form the strategy always fails (is redirected to the failure page). I have a feeling it is something to do with the body of he request not being passed (since the log I placed in where the strategy is declared is not run). However it seems like the current infrastructure makes it hard to refactor. Can this code be refactored such that the request can be parsed manually (e.g. request.body.* name *) before handing it over to passport?
Unless the issue is something completely different, in which case I have no idea...
index.js:
// Use middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(expressSession({ secret: 'whatkindofgamedoyouthinkthisishey',
cookie: {maxAge:null},
resave: false,
saveUninitialized: false}));
require("./config/passport")(passport);
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
// Obtain application modules
var userModels = require("./schemas/user")(mongoose);
var loginPage = require("./routes/login")(passport, userModels);
// Initialize Routes
app.use("/", loginPage);
passport.js (should come up with a better name):
var LocalStrategy = require("passport-local").Strategy,
User = require("../schemas/user");
module.exports = function (passport) {
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
passport.use("local-signup", new LocalStrategy({
email: "email",
password: "password",
passReqToCallback: true
},
function (request, email, password, done) {
console.log("message sent to sign up"); // log not running
process.nextTick(function () {
User.findOne({email: email}, function (err, user) {
if (err) {
return done(err);
}
if (user) {
return done(null, false, request.flash("signupMessage", "That email is already taken"));
} else {
var newUser = new User();
newUser.email = email;
newUser.password = password;
newUser.save(function (err) {
if (err) {
throw err;
} else {
return done(null, newUser);
}
});
}
});
});
}
));
};
login.js (router being exported)
router.post("/register", passport.authenticate("local-signup", {
successRedirect: "/loggedIn",
failureRedirect: "/connectFailed",
failureFlash: false
}));
Html form:
<form class="form-signin" action="/register" method="POST">
<div class="logoContainer">
<img src="images/LogoWithoutText.png" class="image image-responsive" id="loginImage">
</div>
<h2 class="form-signin-heading">Please sign in</h2>
<label for="inputEmail" class="sr-only">Email address</label>
<input type="email" id="inputEmail" class="form-control" name="email" placeholder="Email address" required autofocus>
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" id="inputPassword" class="form-control" name="password" placeholder="Password" required>
<div class="checkbox">
<label>
<input type="checkbox" value="remember-me"> Remember me
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
From what I can read in the passportjs.org/docs, it looks like passport.use has the following signature:
var passport = require('passport'),
LocalStrategy = require('passport-local').Strategy;
passport.use(new LocalStrategy({
email: "email",
password: "password",
passReqToCallback: true
},
function(req, email, password, done) {
User.findOne({ username: username }, function(err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
if (!user.validPassword(password)) {
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, user);
});
}
));
So, try changing the way passport.use is written and try you luck.

nodes passport Error: Unknown authentication strategy "local-login"

I have been trying to get local authentication work with passport on nodejs and as far as i can tell all of my code it is correct but i keep getting the same annoying error about "unknown authentication strategy so maybe someone else can help me with this problem my code is shown below.
Here is my code for passport configuration in nodejs.
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var User = require('../models/user');
module.exports = function(passport) {
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
passport.use('local-signup', new LocalStrategy({
usernameField : 'username',
passwordField : 'password',
passReqToCallback : true
},
function(req, username, password, done) {
process.nextTick(function() {
User.findOne({ 'local.username' : username}, function(err, user) {
if (err)
return done(err);
if(user) {
return done(null, false, req.flash('signupMessage', 'That Username is already taken.'));
}
else {
var newUser = new User();
newUser.local.username = username;
newUser.local.password = newUser.generateHash(password);
newUser.save(function(err) {
if(err)
throw err;
return done(null, newUser);
});
}
});
});
}));
passport.use('local-login', new LocalStrategy({
usernameField : 'username',
passwordField : 'password',
passReqToCallback : true
},
function(req, username, password,done) {
User.findOne({ 'local.username' : username}, function(err, user) {
if(err)
return done(err);
if(!user)
return done(null, false, req.flash('loginMessage', 'No user found.'));
if(!user.validPassword(password))
return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.'));
return done(null, user);
});
}));
};
And here is the post on the server side.
app.post('/signin', passport.authenticate('local-login', {
successRedirect : '/profile',
failureRedirect : '/login',
failureFlash : true
}));
And here is the form in the html doc
<div id="signin">
<form class="form-horizontal" method="POST" action="/signin">
<div class="form-group">
<label class="control-label col-sm-2">Username:</label>
<div class="col-xs-3">
<input type="text" class="form-control"></input><br>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">Password:</label>
<div class="col-xs-3">
<input type="password" class="form-control"></input><br><br>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default btn-lg">Sign In</button><br><br>
</div>
</div>
</form>
<div id="accountlinks">
Create Account<br>
Forgot Password
</div>
</div>
Can anyone please help me by telling me what i have done wrong. thanks
require('./config/passport')(passport);
Change the path of the file. Without this working, passport's configurations will not be passed to the routes.
Here is a snippet of where the line should be located:
// server.js
// configuration
===============================================================
mongoose.connect(configDB.url); // connect to our database
require('./config/passport')(passport); // pass passport for configuration
I also had the same problem but when I put this line of code after the app.use(flash()) it worked:
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
require('./config/passport')(passport);

Does the passport.js support ajax?

I want to make ajax login with the passport.js. I have the usual code for setting the passport.js:
//route
app.post('/api/auth/login', passport.authenticate('local-login', {
successRedirect: '/',
failureRedirect: '/login'
}));
//config strategy
passport.use('local-login', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
}, loginUser));
var loginUser = function(req, email, password, done) {
UserRepo.getOne({
'local.email': email
}).done(function(user) {
if (!user || !user.validPassword(password)) {
return done(null, false, {
message: 'user or password is incorrect'
});
}
return done(null, user);
},
function(err) {
return done(err);
});
};
This is my react component:
var Login = React.createClass({
//...
handleSubmit: function (e) {
e.preventDefault();
var email = this.state.email.trim();
var password = this.state.password.trim();
var data = {
email: email,
password: password
};
api.auth.login(data, function (result) {
console.log(result);
});
},
render: function () {
return (
<form className="login-form" onSubmit={this.handleSubmit}>
<section>
<label>email</label>
<input name="email" type="text" />
<label>password</label>
<input name="password" type="password" />
</section>
<section>
<input type="submit" value="send"/>
</section>
</form>
);
}
//...
})
But, it doesn't work, because redirects (successRedirect and failureRedirect) do their work. If I delete failureRedirect I get 401 status. I understand that my code for passport for server side rendering and page refresh, but I cannot find any documentation for ajax login.
You can use a custom callback to return JSON data.
app.post('/api/auth/login', function(req, res, next) {
passport.authenticate('local-login', function(error, user, info) {
if(error) {
return res.status(500).json(error);
}
if(!user) {
return res.status(401).json(info.message);
}
res.json(user);
})(req, res, next);
});

Resources