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.
Related
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");
});
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'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 ?
Update: I have downloaded express-4.x-local-example and can't seem to get it working either. Is there something that I'm missing?
I'm trying to set a local strategy for passport but it's not being fired. After entering the credentials, the page redirects to failureRedirect.
app.js
const express = require('express')
, app = express()
, mainRouter = require('./controllers/mainRouter');
mainRouter(app);
mainRouter.js
const bodyParser = require('body-parser')
, passport = require('passport')
, passportConfig = require('../config/passport');
passportConfig(passport);
module.exports = (app) => {
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(passport.initialize());
app.use(passport.session());
app.post('/login', passport.authenticate(('local'), {
successRedirect: '/',
failureRedirect: 'login/',
})
);
}
passport.js
const LocalStrategy = require('passport-local').Strategy;
module.exports = (passport) => {
passport.use(new LocalStrategy({usernameField: 'email'},
(email, password, done) => {
console.log('This message is not being logged.');
})
);
}
Your not actually calling the strategy in your mainRouter.js file.
Before the app.post, add passport.use(passportConfig);
I've read similar questions, but I couldn't find a solution.
In my server.js file:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var passport = require('passport');
var cookieParser = require('cookie-parser');
var expressSession = require('express-session');
var passportHelp = require('./config/passport');
var flash = require('connect-flash');
app.use(express.static(__dirname + '/public'));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.set('view engine', '.hbs');
app.set('views', path.join(__dirname, './app/views'))
app.use(expressSession({
secret: 'secret',
saveUninitialized: true,
resave: true
}));
passportHelp(passport);
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use(require('./app/controllers'));
app.listen(3000);
In ./app/controllers
var express = require('express');
var router = express.Router();
router.use(require('./signup'));
module.exports = router;
In ./controllers/signup
var express = require('express');
var passport = require('passport');
var router = express.Router();
router.get('/signup', function(req, res) {
res.render('signup');
});
router.post('/signup', passport.authenticate('local-signup', {
successRedirect: '/profile',
failureRedirect: '/signup',
failureFlash: true,
}));
module.exports = router;
Finally, in ./config/passport
var LocalStrategy = require('passport-local').Strategy;
var User = require('../app/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({
passReqToCallback : true
},
function(req, username, password, done) {
console.log(req.body.username);
console.log(req.body.password); //successfully logs all of these 3
console.log(req.body.email);
process.nextTick(function() {
User.findOne({ 'username' : username }, function(err, user) {
if (err) {
return done(err);
}
if (user) {
return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
}
else {
var newUser = new User;
//filling new user data here
newUser.save(function(err) {
if (err)
throw err;
return done(null, newUser);
});
}
});
});
}));
I end up with strange behavior. Sometimes POST has no problem, sometimes I get cannot POST /signup, but the result is still saved into the database.
I've tried switching some lines in server.js file, but without result. As I've read, when I require passport in controller/signup, it should be the same 'passport' object which I 'initialized' in server.js, so I dont end up working with a fresh passport object. Am I right?
In case someone faces the same problem.
The reason I got the error, but the save into the database was successful was that I have commented that line: successRedirect