Why do I keep getting this error when trying to set up passport-local-mongoose, after registering a user? - authentication

Every time i try to register a new username and password i get this error. Error Message Im not sure if I am doing something wrong. I am trying to learn the different levels of authentication
my code is below
require('dotenv').config();
const express = require("express");
const bodyParser = require("body-parser");
const ejs = require("ejs");
const mongoose = require("mongoose");
const session = require('express-session');
const passport = require("passport");
const passportLocalMongoose = require("passport-local-mongoose");
const app = express();
app.use(express.static("public"));
app.set('view engine', 'ejs',);
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(session({
secret: 'suckbigd please',
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}));
app.use(passport.initialize());
app.use(passport.session());
mongoose.connect("mongodb://localhost:27017/userDB", { useNewUrlParser: true });
// mongoose.set("useCreateIndex", true);
const userSchema = new mongoose.Schema({
email: String,
password: String
});
userSchema.plugin(passportLocalMongoose);
const User = new mongoose.model("User", userSchema);
passport.use(User.createStrategy());
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.get("/", function (req, res) {
res.render("home");
});
app.get("/login", function (req, res) {
res.render("login");
});
app.get("/register", function (req, res) {
res.render("register");
});
app.get("/secrets", function (req, res) {
if (req.isAuthenticated()) {
res.render("secrets");
} else {
res.render("/login");
}
});
app.post("/register", function (req, res) {
User.register({ username: req.body.username }, req.body.password, function (err, user) {
if (err) {
console.log(err);
res.redirect("/register");
} else {
passport.authenticate("local")(req, res, function () {
res.redirect("/secrets");
});
}
});
});
app.post("/login", function (req, res) {
const usetr = new User({
username: req.body.username,
password: req.body.password
});
req.login(user, function (err) {
if (err) {
console.log(err);
} else {
passport.authenticate("local")(req, res, function () {
res.redirect("/secrets");
});
}
})
});
app.listen(3000, function () {
console.log("Server started on port 3000.");
});
I thought I followed the course instructions right. I even watched the video and followed along but I am still getting this error. I am banging my head on the key board. I have been trying to fix this for 4 days now and still nothing. Someone please help.

Related

passport.use is not being called

I want to learn how to use passport js, so I created a dummy project with front-end and express back-end, the front-end form is sending a post request to "/emailAndPassword" route on express.
the request is sent successfully but passport.use is not being called and the authenticate middleware is allway redirected to "/failure" route.
Can anybody help me, the code is here:
const express = require("express");
const cors = require("cors");
const passport = require("passport");
const LocalStrategy = require("passport-local").Strategy;
const session = require("express-session");
const app = express();
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(
session({
secret: "secret",
saveUninitialized: false,
resave: false,
})
);
passport.use(
new LocalStrategy(
{ usernameField: "username", passwordField: "password" },
function(username, password, done) {
return done(null, { username: "rest#test.com", password: "some-characters" });
}
)
);
app.use(passport.initialize());
app.use(passport.session());
app.get("/", (req, res) => {
res.send("success");
});
app.get("/failure", (req, res) => {
res.send("failure");
});
app.post(
"/emailAndPassword",
passport.authenticate("local", {
failureRedirect: "/failure",
successRedirect: "/",
}),
(req, res) => {
res.redirect("/")
}
);
app.listen(5000, () => {
console.log("listening...");
});
Try to put passport.use() function below passport.initialize()
Like:
app.use(passport.initialize())
app.use(passport.session())
passport.use(
new LocalStrategy(
{ usernameField: "username", passwordField: "password" },
function(username, password, done) {
return done(null, { username: "rest#test.com", password: "some-characters" });
}
)
)

Heroku to netlify session wont store session values

This works fine when I am running it on Localhost3000(client) and localhost:3005(server). However once I publish my app to Heroku(server) and netlify(client) it for some reason tells me the req.session.steamuser when accessing /user is null even after it has been set in /api/auth/steam/return and I have tested that the req.session.steamuser=req.user accutally work.
Server.js
var express = require('express');
var passport = require('passport');
var session = require('express-session');
var passportSteam = require('passport-steam');
const cors = require("cors");
var SteamStrategy = passportSteam.Strategy;
var app = express();
const corsOptions = {
origin: ["https://stunning-bavarois-0eef55.netlify.app"],
credentials: true, //access-control-allow-credentials:true
methods: ["GET", "POST"],
};
app.use(cors(corsOptions));
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((user, done) => {
done(null, user);
});
passport.use(new SteamStrategy({
returnURL: 'https://temtestt.herokuapp.com/api/auth/steam/return',
realm: 'https://temtestt.herokuapp.com/',
apiKey: 'MY SECRET API KEY'
}, function (identifier, profile, done) {
process.nextTick(function () {
profile.identifier = identifier;
return done(null, profile);
});
}
));
app.use(session({
secret: 'db5910cc8b9dcec166fda1d2c34860b6f8cd932cea641ea39924ed18fe6fc863',
resave: true,
saveUninitialized: true,
cookie: {
SameSite:"none",
maxAge: 3600000,
secure:true
}
}))
// Initiate Strategy
app.use(passport.initialize());
app.use(passport.session());
app.get('/', (req, res) => {
res.status(200);
res.send("Welcome to root URL of Server");
});
app.get("/user", (req, res) => {
if (req.session.steamuser) {
res.status(200).send(req.session.steamuser)
}
else {
res.send(false)
}
})
app.get('/api/auth/steam', passport.authenticate('steam', { failureRedirect: '/' }), function (req, res) {
res.redirect('/')
});
app.get('/api/auth/steam/return', passport.authenticate('steam', { failureRedirect: '/' }), function (req, res) {
req.session.steamuser = req.user;
res.redirect('https://stunning-bavarois-0eef55.netlify.app/')
});
app.listen(process.env.PORT || 3005);
Client
import { useEffect, useState } from 'react';
import './App.css';
import axios from 'axios';
function App() {
const [user,setUser]=useState(null);
useEffect(()=>{
async function getUser(){
const data = await axios.get("https://temtestt.herokuapp.com/user",{withCredentials:true});
setUser(data.data);
}
getUser();
},[]);
return (
<div className="App">
<h1>Hello</h1>
{(user===false||user===null)?<><p>Please log in</p>Login</>:<p>{user.displayName}</p>}
</div>
);
}
export default App;
As mentioned already it works fine when I do with localhost and returns correct values. But when I try with netlify and heroku it almost seems like it doesn't recognize the session key or something.

No 'Access-Control-Allow-Origin' header is present on the requested resource (MERN)

This error is never ending, I keep getting it and it's been days I've been trying to find a solution for this annoying error.
Here is what happens when I try to log in.
My app works perfectly fine in localhost but there are alot of issue when I uploaded it to heroku and it is really annoying.
Im using
Axios.defaults.withCredentials = true;
code on my every front end.
My backend
const express = require("express");
const cors = require("cors");
const mongoose = require("mongoose")
const app = express();
const bcrypt = require("bcryptjs")
const saltRounds = 10;
const bodyParser = require("body-parser")
const cookieParser = require("cookie-parser")
const session = require("express-session")
const voterModel = require('./modules/voters.js')
const presidentModel = require('./modules/president.js')
const viceModel = require('./modules/vice.js')
const treasurerModel = require('./modules/treasurer.js')
var MongoDBStore = require('connect-mongodb-session')(session);
app.use(express.json());
const corsOptions = {
origin: 'https://incomparable-speculoos-abdd5f.netlify.app',
//update: or "origin: true," if you don't wanna add a specific one
credentials: true,
};
app.use(cors(corsOptions));
app.options('*', cors());
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: true }))
mongoose.connect("hidden",
{
useNewUrlParser: true,
useUnifiedTopology: true
}
)
var store = new MongoDBStore({
uri: 'hidden',
collection: 'sessions'
});
// Catch errors
store.on('error', function(error) {
console.log(error);
});
app.use(session({
secret: "hidden",
resave: false,
store: store,
saveUninitialized: false,
cookie: {
maxAge: 1000 * 60 * 60 * 24
}
}))
app.post('/login', async (req, res) => {
const email = req.body.email;
const password = req.body.password;
voterModel.find({email: email}, {"email":1}, async (err, result) => {
if (err) {
console.log(err)
} else {
if(result.length > 0) {
const user = await voterModel.findOne({email: email})
const pass = await user.comparePassword(password)
if (pass) {
req.session.user = user
} else {
console.log("NOT LOGGED IN")
res.send({ message: 'Invalid email or password!'})
}
} else {
console.log("NOT LOGGED IN")
res.send({ message: 'Invalid email or password!'})
}
}
})
})
app.post('/register', async (req, res) => {
const username = req.body.username;
const email = req.body.email;
const password = req.body.password;
// HASING PASSWORD
bcrypt.hash(password, saltRounds, async (err, hash) => {
if (err) {
console.log(err)
}
// INSERTING VALUES
const voters = await voterModel({email: email, username: username, password: hash, status: false})
// CHECKS IF EMAIL IS IN USE
const isNewEmail = await voterModel.isThisEmailInUse(email)
if (!isNewEmail) return res.send({ message: 'This email is already taken!'})
// SAVES THE INSERT DATA FOR VOTERS
await voters.save()
res.send({success: true})
})
})
app.post('/voted', async (req, res) => {
// FOR UPDATING THE VOTING STATUS
const email = req.body.email
// VARIABLES FOR CHOSEN CANDIDATES OF USER
const president = req.body.president
const vice = req.body.vice
const treasurer = req.body.treasurer
// SETS THE STATUS OF VOTER TO TRUE SO HE/SHE CAN ONLY VOTE ONCE
voterModel.updateOne({email: email}, {$set : {status: true}}, (err, result) => {
if (err) {
console.log(err)
} else {
console.log(result)
}
})
// BELOW ARE THE COMMANDS FOR INCREMENTING THE VOTE COUNT OF SELECTED CANDIDATES OF THE VOTER
presidentModel.updateOne({nickname: president}, {$inc : {votes: 1}}, (err, result) => {
if (err) {
console.log(err)
} else {
console.log(result)
}
})
viceModel.updateOne({nickname: vice}, {$inc : {votes: 1}}, (err, result) => {
if (err) {
console.log(err)
} else {
console.log(result)
}
})
treasurerModel.updateOne({nickname: treasurer}, {$inc : {votes: 1}}, (err, result) => {
if (err) {
console.log(err)
} else {
console.log(result)
}
})
})
app.get('/login', (req, res) => {
if (req.session.user) {
res.send({loggedIn: true, user: req.session.user})
} else {
res.send({loggedIn: false})
}
})
app.post('/checkVote', (req, res) => {
const email = req.body.email
const num = true;
voterModel.find({ $and : [{email: email}, {status : num}]},(err, result) => {
if (err) {
console.log(err)
} else {
console.log(result)
if (result.length > 0) {
res.send( {voted: true } )
} else {
res.send( {voted: false } )
}
}
})
})
app.get("/logout", (req, res) => {
req.session.destroy(err => {
if (err) return next(err)
res.status(200).send('logged out')
})
res.status(200).send('User has been logged out');
});
const PORT = process.env.PORT || 3001
app.listen(PORT, () => {
console.log('running on port 3001')
})

cant get current User from API with axios

i have a problem to get my auth User. When I call my route where the current user is in i become no Data in my Vue file.
Backend:
var app = express();
app.use(cors({
methods:['GET','POST'],
credentials: true,
}))
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser('test'))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(session({
secret: 'test',
resave: true,
saveUninitialized: true,
}))
app.use(passport.initialize());
app.use(passport.session());
const port = 3000
app.use(express.static('public'))
//Passport setup
const apiRoutes = require('./apiRoutes')
app.use('/api', apiRoutes)
Passport config:
passport.use(new LocalStrategy(
{
usernameField: 'username',
passwordField: 'password'
},
function(username, password, done) {
userModel.findOne({
username: username
}, (req, res) => {
const match = bcrypt.compare(password, res.password).then(result => {
if (result) {
return done(null, res, {message: 'hat geklappt'})
} else {
return done(null, false, {message: 'hat nicht geklappt'})
}
})
})
}
));
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});
Route:
router.get("/", (req, res) => {
let user = req.user;
res.json(
user
);
});
My API is not empty but i cant get the data from Axios get
API:
APi
and my Empty data field:
vue
i dont know what i can do because i have not so much experience and iam really thankfull for help
Thanks :)
set content-type: application/json in the header like this:
it's a sample
var axios = require('axios');
var data = JSON.stringify({"username":"username","password":"password"});
let domain = "localhost";
let port = "3000"
let url = `http://${local}:${port}/api`
var config = {
method: 'post',
url: '',
headers: {
'Content-Type': 'application/json'
},
data : data
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
the request is not added to the question, but you can change your request base on my answer

How to properly logout with JWT using Passport Strategies?

I am new to JWT and Passport so I started following a MERN tutorial on Youtube by NoobCoder that deals with authentication and authorization using JWT. I reached the part where the route deals with '/logout' and I get Unauthorized as a reply from Postman. The code so far is exactly the same by the looks of it. Can someone help me understand what is wrong here?
I have attached the code in the bottom. Please let me know if more information is required.
Here is the code:
app.js
const express = require('express');
const app = express();
const cookieParser = require('cookie-parser');
const mongoose = require('mongoose');
app.use(cookieParser());
app.use(express.json());
mongoose.connect('mongodb://localhost:27017/mernauth', {useNewUrlParser: true, useUnifiedTopology: true}, () => {
console.log('Successfully connected to DB');
});
const userRouter = require('./routes/User');
app.use('/user', userRouter);
app.listen(5000, () => {
console.log('express server started');
});
passport.js
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const JwtStrategy = require('passport-jwt').Strategy;
const User = require('./models/User');
const cookieExtractor = req => {
let token = null;
if(req && req.cookies) {
token = req.cookies['access_token'];
}
return token;
}
// Authorization
passport.use(new JwtStrategy({
jwtFromRequest: cookieExtractor,
secretOrKey: 'NoobCoder'
}, (payload, done) => {
User.findById({_id: payload.sub}, (err, user) => {
if(err) {
return done(err, false);
}
if(user) {
return done(null, user);
}
else {
return done(null, false);
}
})
}));
// Authenticated local strategy using username and password
passport.use(new LocalStrategy((username, password, done) => {
User.findOne({username}, (err, user) => {
// Something went wrong with DB
if(err) {
return done(err);
}
// If no user exists; null = no error; false = user does not exist
if(!user) {
return done(null, false);
}
// Check if password is correct; callback cb = done
user.comparePassword(password, done);
});
}));
User.js (route)
const express = require('express');
const userRouter = express.Router();
const passport = require('passport');
const passportConfig = require('../passport');
const JWT = require('jsonwebtoken');
const User = require('../models/User');
const Todo = require('../models/Todo');
const signToken = userID => {
return JWT.sign({
iss: "NoobCoder",
sub: userID
}, "NoobCoder", {expiresIn: "1h"});
}
userRouter.post('/register', (req, res) => {
const {username, password, role} = req.body;
User.findOne({username}, (err, user) => {
if(err) {
res.status(500).json({message: {msgBody: "Error has occured", msgError: true}})
}
if(user) {
res.status(400).json({message: {msgBody: "Username is already taken", msgError: true}})
}
else {
const newUser = new User({username, password, role});
newUser.save(err => {
if(err) {
res.status(500).json({message: {msgBody: "Error has occured", msgError: true}})
}
else {
res.status(201).json({message: {msgBody: "Account Successfully Created", msgError: false}})
}
})
}
})
});
userRouter.post('/login', passport.authenticate('local', {session: false}), (req, res) => {
if(req.isAuthenticated()) {
const {_id, username, role} = req.user;
const token = signToken(_id);
res.cookie('access_token', token, {httpOnly: true, sameSite: true});
res.status(200).json({isAuthenticated: true, user: {username, role}})
}
});
userRouter.get('/logout', passport.authenticate('jwt', {session: false}), (req, res) => {
res.clearCookie('access_token');
res.json({user: {username: '', role: ''}, success: true});
});
module.exports = userRouter;
User.js (model)
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const UserSchema = new mongoose.Schema({
username: {
type: String,
required: true,
min: 6,
max: 15
},
password: {
type: String,
required: true,
},
role: {
type: String,
enum: ['user', 'admin'],
required: true
},
todos: [{type: mongoose.Schema.Types.ObjectId, ref: 'Todo'}]
});
UserSchema.pre('save', function(next) {
if(!this.isModified('password')) {
return next()
}
bcrypt.hash(this.password, 10, (err, passwordHash) => {
if(err) {
return next(err);
}
this.password = passwordHash;
next();
});
});
UserSchema.methods.comparePassword = function(password, cb) {
bcrypt.compare(password, this.password, (err, isMatch) => {
if(err) {
return cb(err);
}
else {
if(!isMatch) {
return cb(null, isMatch)
}
return cb(null, this);
}
})
};
module.exports = mongoose.model('User', UserSchema);
Perhaps the /logout route is unauthorised because the JWT token is not present?
JWT token presence can be verified by ensuring that the cookieExtractor function is returning a token
app.get('/logout', function(req, res){
req.logout();
res.redirect('/');
});
Source