I have seen the other posts with the exact same title however none of those have fixed my problem. When a user logs in, it briefly grabs the user object, then drops it on the next render. I am doing this all in the backend at the moment, so the problem lies there. I have made sure I have the correct order of the imports as well. Here is the relevant code.
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');
const passport = require("passport");
var passportGithub = require('./auth/github')
const KBRoutes = express.Router();
const PORT = 4000;
let KB = require('./models/kb')
let Tags = require('./models/tags')
let User = require('./models/user')
const session = require('express-session')
mongoose.connect(process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/kb', { useNewUrlParser: true });
const connection = mongoose.connection;
app.use(cors());
app.use(bodyParser.json());
app.use(
session({
secret: process.env.APP_SECRET || 'this is the default passphrase',
})
)
app.use(passport.initialize())
app.use(passport.session())
KBRoutes.get('/auth/github', passport.authenticate("github"));
KBRoutes.get(
"/auth/github/callback",
passport.authenticate("github", {
failureRedirect: "/auth/login/failed"
}),
function (req, res) {
var token = req.user.id;
res.redirect("http://localhost:3111?token=" + token);
},
);
app.use(function (req, res, next) {
console.log('===== passport user =======')
console.log(req.session)
console.log(req.user)
console.log('===== END =======')
next()
})
init.js
var passport = require('passport');
var User = require('../models/user');
module.exports = function () {
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
};
Strategy
var passport = require('passport');
var GitHubStrategy = require('passport-github2').Strategy;
var User = require('../models/user');
var config = require('../_config');
var init = require('./init');
passport.use(new GitHubStrategy({
clientID: config.github.clientID,
clientSecret: config.github.clientSecret,
callbackURL: config.github.callbackURL
},
function (accessToken, refreshToken, profile, done) {
var searchQuery = {
name: profile.username
};
var updates = {
name: profile.username,
someID: profile.id
};
var options = {
upsert: true
};
// update the user if s/he exists or add a new user
User.findOneAndUpdate(searchQuery, updates, options, function (err, user) {
if (err) {
return done(err);
} else {
console.log(user)
return done(null, user);
}
});
}
));
// serialize user into the session
init();
module.exports = passport;
EDIT: The session is losing the data and req.user becomes undefined after the serialization. Everything prior to that works.
I think it's because there are multiple instances of passport that may have made the app go haywire. I would do delete the init.js file and integrate it in the Strategy file, as such:
var passport = require('passport');
var GitHubStrategy = require('passport-github2').Strategy;
var User = require('../models/user');
var config = require('../_config');
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(new GitHubStrategy({
clientID: config.github.clientID,
clientSecret: config.github.clientSecret,
callbackURL: config.github.callbackURL
},
function (accessToken, refreshToken, profile, done) {
var searchQuery = {
name: profile.username
};
var updates = {
name: profile.username,
someID: profile.id
};
var options = {
upsert: true
};
// update the user if s/he exists or add a new user
User.findOneAndUpdate(searchQuery, updates, options, function (err, user) {
if (err) {
return done(err);
} else {
console.log(user)
return done(null, user);
}
});
}
));
module.exports = passport;
Related
I'm trying to authenticate users locally using the passport-jwt strategy or with their google account using passport-google-oauth20 strategy. The local authentication with passport-jwt works fine but when I try to access the protected route after google signup, req.isAuthenticated() keeps returning false.
Here's what my code looks like
passport-jwt config
const passport = require("passport");
const JwtStrategy = require("passport-jwt").Strategy;
const ExtractJwt = require("passport-jwt").ExtractJwt;
const User = require("../models/User");
const opts = {};
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = process.env.JWT_SECRET;
passport.use(
new JwtStrategy(opts, (jwt_payload, done) => {
User.findOne({ id: jwt_payload.id }, function (err, user) {
if (err) {
return done(err, false);
}
if (user) {
return done(null, user);
} else {
return done(null, false);
}
});
})
);
passport-google-oauth20 config
const passport = require("passport");
const GoogleStrategy = require("passport-google-oauth20").Strategy;
const User = require("../models/User");
passport.use(
new GoogleStrategy(
{
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: "http://localhost:5000/auth/google/protected",
},
(accessToken, refreshToken, profile, cb) => {
// console.log(profile);
const userInfo = {
googleId: profile.id,
fullname: profile.displayName,
email: profile.emails[0].value,
};
User.findOrCreate(userInfo, (err, user) => {
return cb(err, user);
});
}
)
);
controllers/auth.js
const User = require("../models/User");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const createError = require("../utils/error");
const jsonToken = require("../utils/verifyToken");
const passport = require("passport");
module.exports = {
googleAuth: passport.authenticate("google", {
session: false,
scope: ["email", "profile"],
}),
googleAuthRedirect: passport.authenticate("google", {
session: false,
failureRedirect: "auth/login",
}),
authRedirectCallBack: (req, res) => {
// const token = jsonToken.createToken({
// id: req.user._id,
// isAdmin: req.user.isAdnmin,
// services: req.user.services,
// });
// req.headers["Authorization"] = "Bearer " + token;
// console.log(req.headers["Authorization"]);
console.log(req.isAuthenticated()); //this line returns true
res.redirect("/api/protected");
},
};
routes/auth.js
const express = require("express");
const router = express.Router();
const controllers = require("../controllers/auth");
const {
googleAuth,
googleAuthRedirect,
authRedirectCallBack,
} = controllers;
router.route("/google").get(googleAuth);
router.route("/google/protected").get(googleAuthRedirect, authRedirectCallBack);
module.exports = router;
routes/protected.js
const router = require("express").Router();
const passport = require("passport");
router.get(
"/protected",
(req, res, next) => {
console.log("protected route returns: " + req.isAuthenticated()); //this line returns false
if (req.isAuthenticated()) {
res.send("this is the protected route");
} else {
return res.send("you're not authorized");
}
next();
},
passport.authenticate("jwt", { session: false }),
(req, res) => {
res.send("this is the protected route");
}
);
module.exports = router;
finally, server.js
const express = require("express");
const app = express();
const dotenv = require("dotenv");
dotenv.config();
const mongoose = require("mongoose");
const passport = require("passport");
require("./config/passportJwt");
require("./config/passportGoogle");
mongoose.connect("mongodb://localhost:27017/findersDB", {
useUnifiedTopology: true,
useNewUrlParser: true,
});
mongoose.connection.on("connected", () => console.log("DB connected!"));
app.use(express.json());
app.use(passport.initialize());
const authRoute = require("./routes/auth");
const protectedRoute = require("./routes/protected");
app.use("/auth", authRoute);
app.use("/api", protectedRoute);
app.use((err, req, res, next) => {
const errorMessage = err.message || "Something went wrong";
const errorStatus = err.status || 500;
return res.status(errorStatus).json({
success: false,
message: errorMessage,
status: errorStatus,
stack: err.stack,
});
});
app.listen(5000, () => console.log("Server is running on port 5000"));
I've tried every solution I've seen so far but none seems to work. Any help will be very much appreciated.
var express = require('express');
var passport = require('passport');
var router = express.Router();
var User = require('../models/authentication');
var todo_controller = require('../controllers/todoController');
var auth_controller = require('../controllers/authController');
var BasicStrategy = require('passport-http').BasicStrategy;
passport.use(new BasicStrategy(
function (username, password, done) {
User.findOne({ clientId: username }, function (err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false);
}
if (user.clientSecret != password) {
return done(null, false);
}
return done(null, user);
});
}
));
router.post('/api/me',
passport.authenticate('basic', { session: false }),
function (req, res) {
res.json(req.user);
});
module.exports = router;
I am using express js , mongoose, and passports.
this is the router.js file. The authentication not works, it returns "unauthorized" always. is this the correct way to use passport..i didn't find an easy reference to use passport.
I have a tremendous headche with a problem when I try to login using Passport.
I'm making a post request to /login with an email and password. Passport authenticates it correctly, err isn't called and then return res.redirect('/user') gets called too but it returns 404 and doesn't redirect.
I don't know why this is happening. Here's my code:
Server (index.js):
const
express = require('express'),
app = express(),
mongoose = require('mongoose'),
passport = require('passport'),
cookieSession = require('cookie-session'),
bodyParser = require('body-parser'),
keys = require('./config/keys'),
user = require('./models/User'),
passportService = require('./services/passport'),
authRoutes = require('./routes/auth');
mongoose.connect(keys.mongoURI);
app.use(bodyParser.json());
app.use(
cookieSession({
maxAge: 15 * 24 * 60 * 60 * 1000,
keys: [keys.cookieKey]
})
);
app.use(passport.initialize());
app.use(passport.session());
passportService(passport);
authRoutes(app);
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
console.log(`App listening on port ${PORT}`);
});
passportService (passport.js):
const LocalStrategy = require('passport-local').Strategy;
const mongoose = require('mongoose');
const User = mongoose.model('users');
module.exports = (passport) => {
passport.serializeUser((user, done) => {
done(null, user._id);
});
passport.deserializeUser((id, done) => {
User.findById(id).then(user => {
done(null, user);
});
});
passport.use(
new LocalStrategy(
{
usernameField: 'emailaddr',
passwordField: 'passwd'
},
function(username, password, done) {
User.findOne({ email: username }, function(err, user) {
if(err){
return done(err);
}
if(!user) {
console.log('User not found with email: ', username);
return done(null, false);
}
if(user.password != password) {
console.log('Invalid password');
return done(null, false)
}
return done(null, user);
});
}));
}
Authentication route:
const passport = require('passport');
module.exports = app => {
app.post('/api/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.redirect('/login'); }
req.logIn(user, function(err) {
if (err) { return next(err); }
return res.redirect('/user');
});
})(req, res, next);
});
}
There is not route for /user because I'm working with React and React Router in the client.
Please I need your help!!!
I would suggest not using the custom callback on your authenticate function. Instead, check to see if after the api is called and authentication is run if you have a user attached to the request object.
// calling redirects from your api will be problematic with react router
// allow your front end to decide what route to call based on the response
app.post('/api/login', passport.authenticate('local'), function(req, res, next) {
if(req.user) {
res.json(req.user);
} else {
// handle errors here, decide what you want to send back to your front end
// so that it knows the user wasn't found
res.statusCode = 503;
res.send({message: 'Not Found'})
}
});
I am new to NodeJS. And I am trying to create a simple web server.
I am only using NodeJS and Passport.js (using a google strategy) right now.
Currently, all the app.get("") calls are working when I am not authenticated, but once I authenticate with google and the callback happens, I can no longer access any of the app.get routes. I try and put a break point in the arrow function and it is never calls, and just hangs when loading from the browser with auth cookie.
Here is my current code:
Index.js
const express = require('express');
const mongoose = require('mongoose');
const cookieSession = require("cookie-session");
const passport = require("passport");
const keys = require('./config/keys');
require('./models/User');
require('./services/passport');
mongoose.connect(keys.mongoURI);
const app = express();
app.use(
cookieSession({
maxAge: 30 * 24 * 60 * 60 * 1000, //30 days
keys: [keys.cookieKey]
})
);
app.use(passport.initialize());
app.use(passport.session());
require('./routes/authRoutes')(app);
const PORT = process.env.PORT || 5000;
app.listen(PORT);
authRoutes.js
const passport = require('passport');
module.exports = (app) => {
app.get(
"/auth/google",
passport.authenticate('google', {
scope: ['profile', 'email']
})
);
app.get(
'/auth/google/callback',
passport.authenticate('google')
);
app.get("/api/logout", (req, res) => {
req.logout();
res.send(req.user);
});
app.get("/api/current_user", (req, res) => {
res.send("test");//req.user); //Tried as a test, is called when
//not authenticated, but does not get
//called when authenticated
});
}
passport.js
const passport = require('passport');
const googleStrategy = require('passport-google-oauth20');
const mongoose = require('mongoose');
const keys = require('../config/keys');
const User = mongoose.model("users");
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done)=> {
User.findById(id)
.then(user =>{
doen(null, user);
});
});
passport.use(new googleStrategy({
clientID: keys.googleClientID,
clientSecret: keys.googleclientSecret,
callbackURL: '/auth/google/callback'
},
(accessToken, refreshToken, profile, done) => {
User.findOne({ googleId: profile.id })
.then((existingUser) => {
if (existingUser){
//we already have a user
done(null, existingUser);
}
else{
new User({ googleId: profile.id })
.save()
.then (user => done(null, user));
}
});
})
);
this probably wont help anyone besides for the fact to check for TYPOS!
I found my problem here:
passport.deserializeUser((id, done)=> {
User.findById(id)
.then(user =>{
doen(null, user);
});
});
notice doen should be done
I got no error messages that helped me on this one.
I am trying to create passport-local sign-up functionality, but whenever I try to hit auth/signup API, I always redirect to failure path i.e. failureRedirect: '/auth/failure'.
The code seems fine to me.
app.js:
var passport = require('passport');
var api = require('./routes/api');
var authenticate = require('./routes/authenticate')(passport);
require('./models/models');
var mongoose = require('mongoose');
mongoose.connect("mongodb://localhost:27017/test-chirp");
var app = express();
app.use('/auth', authenticate);
//// Initialize Passport
var initPassport = require('./passport-init');
initPassport(passport);
authenticate.js:
var express = require('express');
var router = express.Router();
module.exports = function(passport){
//sends successful login state back to angular
router.get('/success', function(req, res){
res.send({state: 'success', user: req.user ? req.user : null});
});
//sends failure login state back to angular
router.get('/failure', function(req, res){
res.send({state: 'failure', user: null, message: "Invalid username or password"});
});
//sign up
router.post('/signup', passport.authenticate('signup', {
successRedirect: '/auth/success',
failureRedirect: '/auth/failure'
}));
return router;
}
passport-init.js:
var mongoose = require('mongoose');
var User = mongoose.model('User');
var LocalStrategy = require('passport-local').Strategy;
var bCrypt = require('bcrypt-nodejs');
module.exports = function (passport) {
passport.serializeUser(function (user, done) {
//return the unique id for the user
return done(null, user._id);
});
passport.deserializeUser(function (username, done) {
User.findById(id, function (err, user) {
if (err) { return done(err, false); }
if (!user) { return done('user not found', false); }
return done(user, true);
})
});
passport.use('signup', new LocalStrategy({
passReqToCallback: true
},
function (req, username, password, done) {
// find a user in mongo with provided username
User.findOne({ 'username': username }, function (err, user) {
if (err) {return done(err);}
// already exists
if (user) {return done(null, false);}
else {
// if there is no user, create the user
var newUser = new User();
// set the user's local credentials
newUser.username = username;
newUser.password = createHash(password);
// save the user
newUser.save(function (err) {
if (err) {throw err;}
console.log(newUser.username + ' Registration succesful');
return done(null, newUser);
});
}
});
})
);
var isValidPassword = function (user, password) {
return bCrypt.compareSync(password, user.password);
};
// Generates hash using bCrypt
var createHash = function (password) {
return bCrypt.hashSync(password, bCrypt.genSaltSync(10), null);
};
};
var app = express();
app.use('/auth', authenticate);
//// Initialize Passport
var initPassport = require('./passport-init');
initPassport(passport);
You are routing to the path /auth before initializing passport.
Try to switch :
var app = express();
//// Initialize Passport
var initPassport = require('./passport-init');
initPassport(passport);
app.use('/auth', authenticate);