I am using React with Nodejs and Express in making a login app. I want to only access my profile page when I am logged in. I use passport to authenticate and save cookies in my browser.
If I am not logged in, it should take me back to the home page, when I am logged in I should be able to access my profile.
Now when I also create an account, it should save a cookie in my browser so I can access my profile page, however, when I check my browser, there is no cookie for localhost.
There is something wrong with my code and I can't seem to figure it out. Can anyone help me here?
This is my server.js
const express = require("express");
const cors = require("cors");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const session = require("express-session");
const passport = require("passport");
const passportLocalMongoose = require("passport-local-mongoose");
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(
session({
secret: "This is our little secret",
resave: false,
saveUninitialized: false,
})
);
app.use(passport.initialize());
app.use(passport.session());
//connect to mongodb atlas
mongoose.connect(
"mongodb+srv://admin-darwin:test123#cluster0.nmhlm.mongodb.net/secretsDB",
{ useNewUrlParser: true, useUnifiedTopology: true }
);
//user schema
const userSchema = new mongoose.Schema({
username: String,
email: String,
password: String,
});
userSchema.plugin(passportLocalMongoose);
//user model
const User = mongoose.model("User", userSchema);
passport.use(User.createStrategy());
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.get("/profile", (req, res) => {
if (req.isAuthenticated()) {
console.log("yes");
} else {
res.send("not authenticated");
}
});
// create user
app.post("/new", (req, res) => {
User.register(
{ username: req.body.username },
req.body.password,
(err, user) => {
if (err) {
console.log(err);
res.redirect("/new");
} else {
passport.authenticate("local")(req, res, () => {
res.send("ok");
});
}
}
);
});
app.listen(5000, () => {
console.log("server running on port 5000");
});
Related
I am following the brad Traversy Nodejs Tutorial my server is connected and started also my Mongodb connection is running but localhost keep loading and not responding.
I have checked my URL for mongo connection also the password and username all are correct. I have also allow network access from all sources.
This was perfectly working before but now this keeps loading and loading
my db.js
const mongoose = require("mongoose")
const connectDB = async () => {
try {
const conn = await mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useFindAndModify: false,
useUnifiedTopology: true
})
console.log(`MongoDB connected ${conn.connection.host}`)
} catch (err) {
console.error(err)
process.exit(1)
}
}
module.exports = connectDB
my app.js
const express = require("express")
const path = require("path")
const dotenv = require('dotenv')
const morgan = require('morgan')
const exphbs = require('express-handlebars')
const passport = require('passport')
const connectDB = require('./config/db')
const routes = require('./routes/index')
const session = require("express-session")
const MongoDBStore = require('connect-mongodb-session')(session);
const mongoose = require('mongoose')
const methodOverride = require('method-override')
//locad config
dotenv.config({ path: './config/config.env' })
connectDB()
//passport config
require('./config/passport')(passport)
const app = express()
const PORT = process.env.PORT || 5000
//body parser
app.use(express.urlencoded({ extended: false }))
app.use(express.json())
//method override
// Method override
app.use(
methodOverride(function (req, res) {
if (req.body && typeof req.body === 'object' && '_method' in req.body) {
// look in urlencoded POST bodies and delete it
let method = req.body._method
delete req.body._method
return method
}
})
)
//logging
if (process.env.NODE_ENV === 'development') {
app.use(morgan('dev'))
}
//handlebars helpers
const { formatDate, truncate, stripTags, select } = require('./helpers/hbs')
//Hnadlebars
app.engine('.hbs', exphbs({ helpers: { formatDate, truncate, stripTags, select }, defaultLayout: 'main', extname: '.hbs' }));
app.set('view engine', '.hbs');
//sessions
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUnitialized: false,
store: new MongoDBStore({
mongooseConnection: mongoose.connection
})
//cookie: { secure: true }
}))
//set passport middleware
app.use(passport.initialize())
app.use(passport.session())
//set global variable
app.use(function (req, res, next) {
res.locals.user = req.user || null
})
//static folder
app.use('/', express.static(path.join(__dirname, 'public')))
//Routes
app.use('/', routes);
app.use('/auth', require('./routes/auth'));
app.use('/stories', require('./routes/stories'));
//listen
app.listen(PORT, console.log(
`server is running in ${process.env.NODE_ENV} mode on port ${PORT}`
))
my ./routes/index.js
const express = require('express')
const router = express.Router()
const { ensureAuth, ensureGuest } = require('../middleware/auth')
const Story = require('../models/story')
//#desc Login/Landing Page
//#route GET/
router.get('/', ensureGuest, (req, res, next) => {
res.render("login", {
layout: "login"
})
})
//#desc Login/Landing Page
//#route GET/
router.get('/dashboard', ensureAuth, async (req, res, next) => {
console.log(req.user)
try {
const stories = await Story.find({ user: req.user._id }).lean() //plain Js object
res.render("dashboard", {
name: req.user.firstName,
stories
})
} catch (error) {
console.log('Stories error', error)
res.render('error/500')
}
})
module.exports = router
my browser
I have found if you're using middlewares then must call next function at the end this was the reason my page wasn't loading
The error was at //set global variable middleware
I get the message Unknown authentication strategy "google" in the browser when I try to login with Google using passport.JS in my node.js and express app. I can't seem to figure out what I'm doing wrong.
Here is my code. I've also read other posts but didn't find a working fix yet.
config\passport.js
const passport = require('passport');
const mongoose = require('mongoose')
const User = require('../Models/User')
const GoogleStrategy = require('passport-google-oauth20').Strategy
module.exports = function (passport) {
passport.use(
new GoogleStrategy(
{
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: '/auth/google/callback',
},
async (accessToken, refreshToken, profile, done) => {
const newUser = {
googleId: profile.id,
displayName: profile.displayName,
firstName: profile.name.givenName,
lastName: profile.name.familyName,
image: profile.photos[0].value,
}
try {
let user = await User.findOne({ googleId: profile.id })
if (user) {
done(null, user)
} else {
user = await User.create(newUser)
done(null, user)
}
} catch (err) {
console.error(err)
}
}
)
)
passport.serializeUser((user, done) => {
done(null, user.id)
})
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => done(err, user))
})
}
Routes\auth.js
const express = require('express')
const passport = require('passport')
const router = express.Router()
// #desc Auth with Google
// #route GET /auth/google
router.get('/google', passport.authenticate('google', { scope: ['profile'] }))
// #desc Google auth callback
// #route GET /auth/google/callback
router.get(
'/google/callback',
passport.authenticate('google', { failureRedirect: '/login' }),
(req, res) => {
res.redirect('/')
}
)
// #desc Logout user
// #route /auth/logout
router.get('/logout', (req, res) => {
req.logout()
res.redirect('/')
})
module.exports = router
App.js
var createError = require('http-errors');
var express = require('express');
const dotenv = require('dotenv');
var path = require('path');
const passport = require("passport")
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const connectDB = require('./config/db')
const mongoose = require('mongoose');
const session = require("express-session")
const MongoStore = require('connect-mongo')(session)
const expressLayouts = require("express-ejs-layouts")
const port = 3000
// Load config
dotenv.config({ path: './config/config.env' })
//Connect to MongoDB
connectDB();
// passport config
require('./config/passport');
const app = express();
// view engine and EJS layout setup
app.use(expressLayouts)
app.set('layout', './layouts/layout')
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')))
//Passport middleware - Express Session
session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
store: new MongoStore({ mongooseConnection: mongoose.connection, collection: 'sessions' }),
})
app.use(passport.initialize());
app.use(passport.session());
// routes
app.use('/', require('./routes/homepage'))
app.use('/login', require('./routes/login'))
app.use('/users', require('./routes/users'))
app.use('/project', require('./routes/project'));
app.use('/about', require('./routes/about'));
app.use('/auth', require('./routes/auth'));
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
module.exports = app;
I found my answer. I had to get rid of the module.exports = function (passport) in my passport.js file since I'm calling it through ``require('./config/passport')instead ofrequire('./config/passport')(passport)```
I have 2 modules
users
blogs
i have implemented users for login register with passport authentication . When i try to use current user data(req.user) in blog model it results 'undefined'.
i have share my code below
app.js
const express = require('express');
const app =express();
const path = require('path');
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended : false }));
app.use(bodyParser.json());
const Users = require("./routes/Users");
const Blogs = require("./routes/Blog");
app.use("/users",Users);
app.use("/blogs",Blogs);
app.set('views',path.join(__dirname, 'views'));
app.set('view engine','ejs');
app.listen(3000, function() {
console.log('Server started...');
});
users.js
const passport = require('passport');
const express=require('express');
const users = express.Router();
const models = require('../models');
const User = models.users;
var cookieParser = require('cookie-parser');
const session = require('express-session');
users.use(cookieParser());
users.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}));
users.use(passport.initialize());
users.use(passport.session());
require('../config/passport.js')(passport, User);
users.post('/register',passport.authenticate('local-register', {
successRedirect: '/users/profile',
failureRedirect: '/users/register'
}
));
users.post('/login',passport.authenticate('local-login', {
session: true,
successRedirect: '/users/profile',
failureRedirect: '/users/profile'
}
));
module.exports =users;
blogs.js
const express = require('express');
const blogs = express.Router();
const blogModel = require('../models/blogs');
blogs.get('/',(req,res) =>{
console.log(req.user) // RESULTS UNDEFINED
res.send('Blog List');
});
passport.js
const bCrypt = require('bcryptjs');
const LocalStrategy = require('passport-local').Strategy;
module.exports = function(passport, user) {
const User = user;
passport.use('local-register', new LocalStrategy( { usernameField: 'email', passwordField: 'password', passReqToCallback: true },
function(req, email, password, done) {
... ....
}
));
passport.use('local-login', new LocalStrategy({ usernameField: 'email', passwordField: 'password', passReqToCallback: true },
function(req, email, password, done) {
..... .....
}
));
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
const User =user;
User.findById(id).then((user) =>{
if (user) {
done(null, user);
} else {
done(user.errors, null);
}
});
});
}
You are initiating passport (which handles req.user) only for Users router, this way only routes starting with /users will actually have access to req.user.
In order to use req.user inside the Blogs module, you need to initiate passport for the entire express app (instead of just the users router).
You would probably want to move the initialization to the app.js file
app.use(bodyParser.urlencoded({extended : false }));
app.use(bodyParser.json());
app.use(cookieParser());
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
I believe your problem is you are using multiple objects/instance of express packages and trying to pass from one to another. It won't work as expected. To make it working you should have multiple routes using the same express instance.
I am using express-validator package to validate requested data.
According to these answer I also did change the order or package declaration and initialization
below is my server.js file
const express = require("express");
const session = require("express-session");
const mongoose = require('mongoose');
const MongoStore = require('connect-mongo')(session);
const path = require('path');
const cookieParser = require("cookie-parser");
const bodyParser = require("body-parser");
const passport = require('passport');
const promisify = require('es6-promisify');
const expressValidator = require('express-validator');
const expressJwt = require("express-jwt");
const error_staus = 404;
const morgan = require('morgan');
const logger = require('./helper/logger');
const routes = require('./routes/index');
let server = "";
const bugsnag = require('bugsnag');
// import our configurations from config/tester.js file
const config = require("./config/tester").get(process.env.NODE_ENV);
require('./helper/passport');
require("./helper/translator");
// create our Express app
const app = express();
// view engine setup
app.set("views", `${__dirname}/views`);
app.set("view engine", "ejs");
// serves up static files from the public folder. Anything in app/ will just be served up as the file it is
app.use(express.static(path.join(__dirname, 'app')));
// Takes the raw requests and turns them into usable properties on req.body
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// Exposes a bunch of methods for validating data. Used heavily on userController.validateRegister
app.use(expressValidator());
// Sessions allow us to store data on visitors from request to request
app.use(session({
secret: '123456',
key: '99785',
resave: false,
saveUninitialized: false,
store: new MongoStore({ mongooseConnection: mongoose.connection })
}));
app.use(session({
"secret": 'secret12345',
"resave": false,
"saveUninitialized": true
}));
// Passport JS is what we use to handle our logins
app.use(passport.initialize());
app.use(passport.session());
// promisify some callback based APIs
app.use((req, res, next) => {
req.login = promisify(req.login, req);
next();
});
// begin logger
app.use(morgan('dev', {
skip: function (req, res) {
return res.statusCode < 400
}, stream: process.stderr
}));
app.use(morgan('dev', {
skip: function (req, res) {
return res.statusCode >= 400
}, stream: process.stdout
}));
app.use('/', routes);
app.use(function(req, res, next){
logger.error('404 page requested');
res.sendStatus(error_staus);
});
// done! we export it so we can start the site in start.js
module.exports = app;
This is the userController.js
const mongoose = require('mongoose');
const User = mongoose.model('User');
const promisify = require('es6-promisify');
exports.loginForm = (req, res) => {
res.render('login', { title: 'Login' });
};
exports.registerForm = (req, res) => {
res.render('register', { title: 'Register' });
};
exports.validateRegister = (req, res, next) => {
req.sanitizeBody('name');
req.checkBody('name', 'You must supply a name!').notEmpty();
req.checkBody('email', 'That Email is not valid!').isEmail();
req.sanitizeBody('email').normalizeEmail({
gmail_remove_dots: false,
remove_extension: false,
gmail_remove_subaddress: false
});
req.checkBody('password', 'Password Cannot be Blank!').notEmpty();
req.checkBody('password-confirm', 'Confirmed Password cannot be blank!').notEmpty();
req.checkBody('password-confirm', 'Oops! Your passwords do not match').equals(req.body.password);
const errors = req.validationErrors();
if (errors) {
req.flash('error', errors.map(err => err.msg));
res.render('register', { title: 'Register', body: req.body, flashes: req.flash() });
return; // stop the fn from running
}
next(); // there were no errors!
};
Note : I am using express-validator version 3.1.2
When I check request object, in that object there is all methods of express-validator too.
But try to use that method I am getting req.checkBody is not a function error.
Can anybody help with these issue ?
I'm trying to build a login system using express and passport.
As far as I know, I can use the req.user to access user id and correctly store their actions and req.isAuthenticated() would be true if Passport is working properly, however it isn't working.
For some reason, req.user is always undefined and req.isAuthenticated() is always false.
This is my app.js ->
const express = require('express');
const http = require('http');
const session = require('express-session');
const bodyParser = require('body-parser');
const passport = require('passport');
const route = require('./controllers/core'); **// CORE.JS**
const app = express();
app.set('view engine', 'ejs');
app.use('/css', express.static('css'));
app.use('/js', express.static('js'));
app.use('/themify', express.static('themify'));
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: false
//cookie: { secure: true }
}));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(passport.initialize());
app.use(passport.session());
app.use(route);
//core(app);
app.listen(3000);
And this is my core.js
const router = require('express').Router();
const passport = require('passport');
const bodyParser = require('body-parser');
const mysql = require('mysql');
const connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '',
database : 'pharmate',
dateStrings: 'date'
});
const urlencodedParser = bodyParser.urlencoded({ extended: false });
router.get('/index', function(req,res){
console.log(req.user);
});
router.post('/index', urlencodedParser, function(req,res){
var email = req.body.email;
var pass = req.body.password;
connection.query("SELECT `Pharmacy_ID`, `Email`, `Password` FROM `pharmacy` WHERE Email = ? AND Password = ?", [email, pass], function (error, results, fields) {
if (error) res.send(error);//throw error;
else{
if(results.length>0){
req.login(results[0], function(err){
res.redirect('index');
});
}
else{
res.redirect('login');
}
}
});
});
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
done(null, user);
});
module.exports = router;
Any help would be appreciated. Thanks in advance.
You should handle the authentication like:
app.post('/login',
passport.authenticate('local', {
successRedirect: '/secret',
failureRedirect: '/login',
})
);
Did you setup the passport local strategy ?