Why do i get the Error cannot post /login using express and passportjs? - express

When i make a post request containing the user data to log in, i get the response: Cannot post /login.
What is really weird about this is that you can see trough logging that the request get processed.
I was using postman and a html form to test and both didnt worked.
When i have a failure in the passport.js file it gets logged.
.
Thats my server.js file (shortened):
const express = require("express");
const cors = require("cors");
const flash = require("express-flash");
const passport = require("passport");
const session = require("express-session");
//app configuration
const app = express();
require("dotenv").config();
const initializePassport = require("./config/passport-config");
initializePassport(
passport,
require('./models/User')
)
app.use(
session({
secret: "Janniks whatsapp Klon",
resave: false,
saveUninitialized: false,
})
);
app.use(passport.initialize());
app.use(passport.session());
//For accepting post from data
const UserRouter = require("./api/User");
app.use(flash());
app.use(express.json());
app.use(bodyarser.urlencoded({ extended: true }));
app.use(
cors() //{ origin: "http://localhost:3000", origin: "http://localhost:3000" }
);
app.use("/user", UserRouter);
app.post('/login', passport.authenticate('local', {
sucessRedirect: 'http://localhost:3000/login',
failureRedirect: 'http://localhost:3000/login',
failureFlash: true
}),
)
and thats my passport-config.js file
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy
const bcrypt = require('bcrypt')
//Password handle
function initialize(passport, User){
const authenticateUser = async(emailORnumber, password, done)=>{
//Find user with email or phone number
let user;
if(emailORnumber.includes('#')){
user = await User.findOne({ email: emailORnumber})
}else{
user = await User.findOne({ number: emailORnumber })
}
if(!user){
//User not found, error
console.log('User not found')
return done(null, false, { message: 'Falsches passwort oder falsche Handynummer' })
}
//Check if password is correct
try{
console.log('Checking password')
const isMatch= await bcrypt.compare(password, user.password);
if(!isMatch){
return done(null, false, { message: 'Falsches passwort'})
}else{
//If credentials are correct, return the user object
console.log('correct') //gets logged
return done(null, user)
}
}
catch(err){
console.log(err)
return done(err)
}
}
passport.use(new LocalStrategy({ usernameField: 'emailORnumber'}, authenticateUser)),
//Serialize user to store
passport.serializeUser((user, done)=>{
console.log('Serializing user') //gets logged
done(null, user.id)
})
//Deserialize user from store
passport.deserializeUser((id, done)=>{
console.log('Serializing user') //dont gets logged but there is no interaction
User.findById(id, (err, user)=>{
return done(err, user);
});
});
}
module.exports = initialize;
Thanks for all awnsers that can be provided!

Related

How to display logged in username on the screen | express session

I want take the user info like email , username and display it on dashboard.ejs . i tried req.session.username and req.body.username but never worked . please help me in this !!
i want handle profile management for the web so by retriving the username help fetch the info about the user in the database
`
const express = require("express");
const app = express();
const bcrypt = require("bcryptjs");
const session = require("express-session");
const MongoDBSession = require("connect-mongodb-session")(session);
const mongoose = require("mongoose");
const UserModel = require("./models/user");
const mongoURI = "mongodb://localhost:27017/sessions";
mongoose.connect( mongoURI, {
useNewUrlParser : true,
// useCreateIndex : true,
// useUnifiedToplogy : true
}).then((res)=>{
console.log("MongoDB connected");
})
const store = new MongoDBSession({
uri : mongoURI,
collections : "mySessions"
})
const isAuth = (req,res,next)=>{
if(req.session.isAuth){
next();
}else{
res.redirect("/login");
}
}
app.use(session({
secret : "key that will sign a cookie",
resave : false,
saveUninitialized : false,
store : store
}))
app.set("view engine", "ejs");
app.use(express.urlencoded({ extended: true }));
app.get("/", (req,res)=>{
res.render("landing");
});
// Login Page
app.get("/login", (req,res)=>{
res.render("login");
} );
app.post("/login", async(req,res)=>{
const {email , password} = req.body;
const user = await UserModel.findOne({email});
if (!user){
return res.redirect("/login");
}
const isMatch =await bcrypt.compare(password , user.password);
if(!isMatch){
return res.redirect("/login");
}
req.session.isAuth = true;
res.redirect("/dashboard");
});
// Register Page
app.get("/register", (req,res)=>{
res.render("register");
});
app.post("/register", async (req,res)=>{
const {username , email , password } = req.body;
let user = await UserModel.findOne({email});
if (user){
return res.redirect("/register");
}
const hashPsw =await bcrypt.hash(password,12);
user = new UserModel({
username,
email,
password:hashPsw
});
user.save();
console.log("saved");
if (!user){
return res.redirect("/login");
}
const isMatch =await bcrypt.compare(password , user.password);
if(!isMatch){
return res.redirect("/login");
}
req.session.isAuth = true;
res.redirect("/dashboard");
});
// Dashboard Page
app.get("/dashboard", isAuth , (req,res)=>{
console.log(req.session);
res.render("dashboard");
});
app.post("/logout", (req,res)=>{
req.session.destroy((err)=>{
if (err) throw err;
res.redirect("/");
})
});
app.listen(3500 , ()=>{
console.log("server running on port 3500");
})
`
One of the options would be to supply that in the POST request's response. For example, Author has inserted it in a pug view here like h2 Username: #{user.name} and has supplied it as variable while page rendering in response here with res.render('profile', {title: "My Profile", user: req.cookies.userData});.
Since you have used ejs instead of pug, the injecting I did with #{} can be done with <%= YOUR_VARIABLE %> . Please, see this for a tutorial and ejs docs for more examples.

express-session doesn't pass a variable from one router to another

I have this session middleware:
app.use(session({
secret: "tarek",
resave: true,
saveUninitialized: true,
}));
and in this router i stored a variable this way:
app.post('/login', async(req, res)=>{
const {email, password} = req.body;
try {
const user = await User.findOne({email: email})
if (!user) {
res.json({message: "Can't find an account with this e-mail!"})
}else if(user && (await bcrypt.compare(password, user.pass))){
const token = jwt.sign({
email,
}, process.env.JWT_SECRET, {
expiresIn: process.env.JWT_EXPIRE,
});
req.session.token = token;
console.log(req.session.token)
res.json({token: token, id: user.name + user.lastname + user._id})
}else{
res.json({message: "Invalid password"}).status(400)
}
} catch (err) {
console.log(err.message)
res.json({message: "Error while trying to log in please try again later"})
}
})
and ofc when i console.log the req.session.token it works fine
but when i pass it to another router like this:
app.get('/isUSerAuth', verify.verifyjwt, async(req, res)=>{
console.log(req.session.token)
const token = req.session.token
res.status(200).json({auth: true, token: token, message: "you are authenticated!"})
})
so it says that the req.session.token is undefined

Login authenticates user with any password

I have a simple login form that I created. It seems to authenticate any existing user as long as the password field has something in it. Obviously, it is a huge security flaw. I'm new to mean stack and using passport to authenticate users seemed easy but not sure if I did it wrong.
This is my backend code using passportjs:
app.js
const passport = require('passport');
require('./config/passport');
app.use(passport.initialize());
routes/index.js
const ctrlAuth = require('../controllers/authentication');
router.post('/login', ctrlAuth.login);
controllers/authentication.js
module.exports.login = function(req, res) {
passport.authenticate('local', function(err, user, info){
let token;
// If Passport throws/catches an error
if (err) {
res.status(404).json(err);
return;
}
// If a user is found
if(user){
token = user.generateJwt();
res.status(200);
res.json({
"token" : token
});
} else {
// If user is not found
res.status(401).json(info);
}
})(req, res);
};
And finally, my config file
config/passport.js
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const mongoose = require('mongoose');
const User = mongoose.model('User');
passport.use(new LocalStrategy({
usernameField: 'email'
},
function(username, password, done) {
User.findOne({
email: username
}, function(err, user) {
if (err) {
return done(err);
}
//Return if user not found in database
if (!user) {
return done(null, false, {
message: 'User not found'
});
}
//Return if password is wrong
if (!user.validPassword(password)) {
return done(null, false, {
message: 'Password is wrong'
});
}
//If credentials are correct, return the user object
return done(null, user);
});
}
));
I believe I've narrowed the bug down to my validPassword function where I might be using bcrypt incorrectly.
userSchema.methods.validPassword = function(password){
return bcrypt.compare(password, this.hash);
};
I narrowed my issue down to my validPassword method and found that I was using bcrypt incorrectly. Changed it to
userSchema.methods.validPassword = function(password){
return bcrypt.compareSync(password, this.hash);
};
Makes more sense after looking at the docs for bcrypt https://github.com/kelektiv/node.bcrypt.js#readme

Passport local strategy is never get called

I know this question was asked many times in stack over flow. I tried every accepted answers but can't my local strategy into function. Here is my code
var express = require('express');
var app = express();
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
app.use(cookieParser()); // read cookies (needed for auth)
app.use(bodyParser.json({limit: '50mb'}));
app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));
app.set('trust proxy', 1); // trust first proxy
app.use(session({
secret: '564sdf4as564f56a7s765s4afjkgadxjkbadksj',
resave: true,
saveUninitialized: true,
cookie: { secure: true }
}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy({
usernameField:'userName',
passwordField:'password',
passReqToCallback : true
},function(request, userName, password, done) {
console.log(request);
UserAccount.findOne({'userName': userName} , function(err, user) {
if (err) return done(err);
if (!user) return done(null, false, 'Incorrect username.' );
user.verifyPassword(password, function(err, isMatch) {
if (isMatch) {
return done(null, user);
} else {
return done(null, false, 'Incorrect password.');
}
});
});
}));
passport.serializeUser(function(user, done) {
console.log('Serialize user called');
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
console.log('Deserialize user called');
UserAccount.findById(id, function(err, user) {
done(err, user);
});
});
Then I created a router like
var router = express.Router();
require('./controllers/user')(router,passport);
app.use('/api',router);
Then in my user controller I created signIn function like
app.post('/signIn',function (request,response,next){
var variables = request.body;
console.log(variables);
passport.authenticate('local', function(error, user, info) {
console.log(user);
if (error) { console.log(error); return next(err); }
if (!user) { return response.redirect('/login'); }
response.logIn(user, function(err) {
if (err) { return next(err); }
return response.redirect('/users/' + user.username);
});
})(request, response, next);
});
Then I send a request from "Postman"
{
"userName":"karthik#abc.com",
"password":"qwerty"
}
My mongodb userName and password fields are same.
In my db there is an account with this user name and password. But every time it return 'user' as 'false' inside authenticate. I tried to console my request inside local strategy but it never gets called. I don't understand What I done wrong here? Can some one help to solve this? Thank you very much.
You should name local strategy and use it in authenticate.
Use like this passport.use('local-strategy',new LocalStrategy({});
and like passport.authenticate('local-strategy');

ExpressJS - JWT and Passport Implementation

I'm currently trying to learn JWT and Passport for ExpressJS while trying them out but I can't seem to grasp the idea of how Passport works.
Here's what I have done initially in my ExpressJS application.
/api/login POST API
Accepts username and password
/api/login then creates a JWT with the username and password as the payload
The token is then responded to the client
I think my /api/login API simulates the general idea of JWT of hard authenticate once and respond with token.
/api/test GET API on the other hand
Only authenticated users can access
Simply returns "Hello World!"
What is the problem/s?
My code doesn't seem to validate the token (I tried putting the token in Authenticate header.
Where in my request should I include the token returned from /api/login when requesting to /api/test?
Now to my actual code:
app.js
var express = require("express");
var bodyParser = require("body-parser");
var jwt = require("jsonwebtoken");
var passport = require("passport");
var LocalStrategy = require('passport-local').Strategy;
var mySecret = "mySecret";
var app = express();
var port = process.env.PORT || 3000;
app.use(bodyParser.json());
passport.use(new LocalStrategy(
function (token, done) {
var credentials = jwt.verify(token, mySecret);
if (credentials.username == "test" && credentials.password == "test") {
return done(null, credentials);
} else {
return done(null, false);
}
}
));
app.use(passport.initialize());
app.post("/api/login", function (request, response) {
var user = {
"username": request.body.username,
"password": request.body.password
};
response.send(jwt.sign(user, "mySecret"));
});
app.get("/api/test", passport.authenticate("local", {
"session": false
}), function (request, response) {
response.send("Hello World!");
});
app.listen(port, function () {
console.log("Listening on port: " + port);
});
You need to configure jwtStratagy also to authenticate the user.
here is working example: -
const express = require("express");
const bodyParser = require("body-parser");
const jwt = require("jsonwebtoken");
console.log(jwt.verify);
const passport = require("passport"),
LocalStrategy = require("passport-local").Strategy;
const cors = require("cors");
const app = express();
app.use(cors());
app.use(bodyParser.json());
app.use(passport.initialize());
var secret = '11210646';
var JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
passport.use(new LocalStrategy({
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true
},
function(req, username, password, done) {
console.log('ohh', username, password);
let err = null;
if (err) { return done(err); }
if (username != 'abhi') {
return done(null, false, { message: 'Incorrect username.' });
}
if (password != 'pass') {
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, username);
}
));
app.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
console.log(err, user, info);
if (err) { return next(err); }
if (!user) { res.send({ "status": info.message }); }
res.send({ "status": user });
})(req, res, next);
});
var opts = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: secret,
issuer: 'jonu',
audience: 'jonu bhai',
passReqToCallback: false
};
app.post('/me2', function(req, res, next) {
passport.authenticate('jwt', { session: false }, function(err,user, info) {
if (err) { return next(err); }
if (!user) { res.send({ "status": info.message }); }
res.send({ "status": user });
})(req, res, next);
});
//jwt
passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
let err = null;
if (err) {
return done(err, false);
}
if (jwt_payload) {
return done(null, jwt_payload);
}
else {
return done(null, false);
// or you could create a new account
}
}));
app.post('/signup', (req, res) => {
let token = jwt.sign({
user: {
id: "idididid",
name: "Abhishek Singh",
username: "abhishek11210646"
}
},
secret, {
algorithm: 'HS256',
expiresIn: '5h',
issuer: 'jonu',
audience: 'jonu bhai'
});
res.send({ "token": token });
});
app.get('/', (req, res) => {
res.send({ "status": "Up and Running..." });
});
app.listen(8080, () => {
console.log('server running');
});