I'm currently trying to utilize passport in my node server for twitter auth on a project. When I have all the code in one server file passport functions as expected. Below is an excerpt from the server file with all the routes in it:
passport.use(new TwitterStrategy({
consumerKey: config.twitter.consumer_key,
consumerSecret: config.twitter.consumer_secret,
callbackURL: config.twitter.callback_url.dev
}, (token, tokenSecret, profile, done) => {
console.log(token, tokenSecret, profile, done);
process.nextTick(() => {
return done(null, profile);
});
}));
app.use(session({ secret: 'SOMESECRET' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(path.join(__dirname, '../public')));
app.set('view engine', 'ejs');
// expose to routes
app.all('*', (request, response, next) => {
request.log = log;
next();
});
app.get('/', (req, res) => {
res.render('pages/index.ejs');
});
// twitter auth endpoint
app.get('/auth/twitter', passport.authenticate('twitter'));
// twitter auth callback endpoint
app.get('/auth/twitter/callback', passport.authenticate('twitter', { failureRedirect: '/' }), (req, res) => {
res.redirect('/');
});
However, when I try to expose passport from the server file to the routes file the authentication never occurs. I've searched most of the questions here and went back to the doc but all the tutorials show one server file with all the routes in it.
Server file:
passport.use(new TwitterStrategy({
consumerKey: config.twitter.consumer_key,
consumerSecret: config.twitter.consumer_secret,
callbackURL: config.twitter.callback_url.dev
}, (token, tokenSecret, profile, done) => {
console.log(token, tokenSecret, profile, done);
process.nextTick(() => {
return done(null, profile);
});
}));
app.use(session({ secret: 'SECRET' })); // session secret
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(path.join(__dirname, '../public')));
app.set('view engine', 'ejs');
// expose to routes
app.all('*', (request, response, next) => {
request.log = log;
request.passport = passport;
next();
});
// routes
app.use('/', routes);
Routes file:
import express from 'express';
const routes = express.Router();
import config from '../config.js';
// main
routes.get('/', (req, res) => {
res.render('pages/index.ejs');
});
// twitter auth endpoint
routes.get('/auth/twitter', (req, res) => {
const passport = req.passport;
passport.authenticate('twitter');
});
// twitter auth callback endpoint
routes.get('/auth/twitter/callback', (req, res) => {
const passport = req.passport;
passport.authenticate('twitter', {
failureRedirect: '/'
});
res.redirect('/');
});
module.exports = routes;
What am I missing here? I'm guessing I cannot use passport.authenticate inside the function for the route. I'm still trying to figure out how to get the version using the routes file working. Any help is appreciated!!
You can require Passport normally no need to get passport by let passport = req.passport. Here is my small demo for Google Oauth by passport
Routes.js
const router = require('express').Router();
const passport = require('passport');
router.get(
'/google',
passport.authenticate('google', {
scope: ['profile', 'email'],
session: false
})
);
router.get(
'/google/callback',
passport.authenticate('google', {
session: false
})
);
Server.js
// passort config
app.use(passport.initialize());
require('./services/passport'); // contains the passport google strategy
// routes
require('./routes')(app);
Related
I am trying to get session data, using passport js. When I use the /test or /test2 route, I get the session data. If I try to console.log in these routes, I get the whole session data. But when I try it with /user_data, I dont seem to get the expected response. Where am I going wrong here? I am using passport.js and express session. When going through the /user_data route, I get the following output:
Session {
cookie: { path: '/', _expires: null, originalMaxAge: null, httpOnly: true }
}
Here is the code I am using, it is fairly dirty as of now as I am trying to tinker around.
const express = require('express')
const app = express()
const session = require('express-session');
const port = 3000
const passport =require("passport")
const GoogleStrategy = require('passport-google-oauth2').Strategy;
const bodyParser = require("body-parser");
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});
passport.use(new GoogleStrategy({
clientID:"some.com",
clientSecret:"some_secret",
callbackURL: "http://localhost:3000/auth/google/callback",
passReqToCallback : true
},
function(request, accessToken, refreshToken, profile, done) {
return done(null, profile);
}
));
app.use(session({
resave: false,
saveUninitialized: true,
secret: 'SECRET'
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.get("/failed", (req, res) => {
res.send("Failed")
})
app.get("/success", (req, res) => {
res.send(`Welcome ${req.user.email}`)
})
app.get('/auth/google',
passport.authenticate('google', {
scope:
['email', 'profile']
}
));
app.get('/auth/google/callback',
passport.authenticate('google', {
failureRedirect: '/failed',
}),
function (req, res) {
res.redirect('/')
}
);
app.get("/test",(req,res)=>{
let sess = req.session;
console.log(sess);
var email=sess.passport.user.email;
var netid=email.split('#')[0];
req.session.netid=netid;
console.log(netid);
// console.log(sess.user.id);
res.send("test")
});
app.get("/test2",(req,res)=>{
let sess = req.session;
console.log(sess);
var netid=sess.netid;
console.log(netid);
res.send("test2")
});
app.get("/user_data",(req,res)=>{
var sess = req.session;
console.log(sess.passport);
res.send(sess.passport);
});
app.get('/logout', function(req, res){req.logOut();res.redirect('/');});
app.get('/', (req, res) => {res.sendFile(__dirname + "/pages/index.html");})
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
In theory user_data is just another endpoint and on that basis it should work just like test and test2.
However, user_data could be a reserved name. Try changing that endpoint to something else.
I am using passport.js for twitter social login. In my Web app after a successful login, it will populate the tweets accordingly and will reply to the tweets as per the loggedIn user credentials. Currently, I am able to successfully redirect after login, but not able to fetch the user details which passport gives after successful login i.e (username, email). As a result, I am not able to go further.
Below is the node server.js file.
Kindly help me with this issue.
server.js
const express = require('express');
const TwitterStrategy = require('passport-twitter').Strategy;
const twitConfig = require('./config/auth').twitterAuth;
const passport = require('passport');
const path = require('path');
const bodyParser = require('body-parser');
// Create a new Express application.
const app = express();
// require('./routes/')(app);
// Use application-level middleware for common functionality, including
// logging, parsing, and session handling.
app.use(require('cookie-parser')());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(require('express-session')({ secret: 'keyboard cat', resave: true, saveUninitialized: true }));
//initialize passport strategy for twitter login.
passport.use(new TwitterStrategy({
consumerKey: twitConfig.consumer_key,
consumerSecret: twitConfig.consumer_secret,
callbackURL: twitConfig.callbackURL
}, (token, tokenSecret, profile, callback) => {
console.log('arguments in passport.use>>>>>>>>>>>>>>>', arguments);
console.log('profile in twitterStrategy>>>>>>>>>>>>>', profile,callback);
process.nextTick(() => {
if (err) {
console.log('err in passport TwitterStrategy>>>>>>>>>>>',err)
return callback()
} else {
console.log('inside the else condition no error found>>>>>>>>>>',profile)
}
})
return callback(null, profile);
}));
const twit = require('twit');
const T = new twit(twitConfig);
passport.serializeUser(function(user, callback) {
console.log('arguments in serializeUser passport.use>>>>>>>>>>>>>>>', arguments);
callback(null, user);
})
passport.deserializeUser(function (obj, callback) {
console.log('arguments in deserializeUser passport.use>>>>>>>>>>>>>>>', arguments);
callback(null, obj);
});
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
//load the routes
app.use(require('./routes/twitterApi'));
app.use(require('./routes/token'));
app.use(passport.initialize());
app.use(passport.session());
app.get('/', function (req, res) {
console.log('user in />>>>>>>>>>>>>>', req);
res.render('index', {user: req.user})
})
app.get('/twitter/login', passport.authenticate('twitter'), (req, res) => {
console.log('consoe.log req>>>>>>>>>>>>>', req);
console.log('res >>>>>>>>>>',res);
});
app.get('/twitter/return', passport.authenticate('twitter', { failureRedirect: '/' }), function (req, res) {
console.log('inside the return failure');
res.redirect('http://localhost:8080/');
})
// listen for requests :)
const listener = app.listen(process.env.PORT || 9000, () => {
console.log('Your app is listening on port ' + listener.address().port);
});
Here is an async/await example of how to perform a database operation on the User, after authenticating with passport strategy.
passport.use(new TwitterStrategy({
consumerKey: twitConfig.consumer_key,
consumerSecret: twitConfig.consumer_secret,
callbackURL: twitConfig.callbackURL
}, async (token, tokenSecret, profile, callback) => {
try {
// Perform some kind of db lookup/create with profile object
const user = await User.findOne({
where: {
email: profile.email
}
})
// now your user object will be passed to your callbackURL
return callback(null, user)
}
catch(error) {
return callback(error, error.message);
}
I am having problem in logging in with LinkedIn, both in angular front-end and on node side using passport js. I guess It might be due to change in policy of LinkedIn after 1st march. i have following three files
Server file
app.set('view engine', 'ejs');
// initialize passport
app.use(passport.initialize());
app.use(passport.session());
// set up routes
app.use('/auth', authRoutes);
app.use('/profile', profileRoutes);
// create home route
app.get('/', (req, res) => {
res.render('home');
});
app.listen(3000, () => {
console.log('app now listening for requests on port 3000');
});
Routes file
const router = require('express').Router();
const passport = require('passport');
// auth login
router.get('/login', (req, res) => {
res.render('login', { user: req.user });
});
// auth logout
router.get('/logout', (req, res) => {
// handle with passport
res.send('logging out');
});
router.get('/google',
passport.authenticate('linkedin'),
function(req, res){
// The request will be redirected to LinkedIn for authentication, so this
// function will not be called.
});
router.get('/linkedin/callback', passport.authenticate('linkedin'), (req,
res) => {
res.send(req.user);
// res.redirect('/profile');
});
module.exports = router;
Paasport setup file
const passport = require('passport');
const LinkedInStrategy = require('passport-linkedin-oauth2').Strategy;
passport.use(new LinkedInStrategy({
clientID: LINKEDIN_CLIENT_ID,
clientSecret: LINKEDIN_CLIENT_SECRET,
callbackURL: "http://localhost:3000/auth/linkedin/callback",
scope: ['r_emailaddress','r_liteprofile'],
}, function(accessToken, refreshToken, profile, done) {
// asynchronous verification, for effect...
process.nextTick(function () {
return done(null, profile);
});
}));
I am trying to integrate passport into my node.js app.
app.js file
const app = express();
app.set('view engine', 'pug');
app.use('/libs', express.static('node_modules'));
require('../config/auth.config')(app, data, passport);
app.use((req, res, next) => {
res.locals.user = req.user;
next();
});
app.get('/', (req, res) => {
// those objects are populated correctly after redirect from auth middleware
console.log(req.session)
console.log(req.user)
return res.render('home');
});
app.get('/login', console.log(req.user);
// req.user is undefined here
if (req.user) {
return res.redirect('/');
}
return res.render('login'););
app.post('/login', passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/login',
}));
auth.config.js
const express = require('express');
const session = require('express-session');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const LocalStrategy = require('passport-local');
const MongoStore = require('connect-mongo')(session);
const config = require('./config');
const configAuth = (app, {
users
}, passport, db) => {
app.use(cookieParser('Purple Unicorn'));
app.use(bodyParser.urlencoded({
extended: true,
}));
app.use(bodyParser.json());
app.use(session({
store: new MongoStore({
url: config.connectionString
}),
secret: 'Purple Unicorn',
resave: true,
saveUninitialized: true,
}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy((username, password, done) => {
return users.login(username, password)
.then((user) => {
if (user) {
return done(null, user);
}
return done(null, false);
});
}));
passport.serializeUser((user, done) => {
done(null, user._id);
});
passport.deserializeUser((id, done) => {
users.getUserById(id)
.then((user) => {
console.log(user);
if (user) {
done(null, user);
}
done(null, false);
});
});
app.use((req, res, next) => {
res.locals = {
user: req.user,
};
next();
});
};
module.exports = configAuth;
The data object is working correctly.
After the post request on /login with correct data, I am redirected to / where console.log(req.user) prints the correct user. It is also added in the req.session object.
After I follow a link to /login, it should redirect me after the check for req.user but returns undefined. Sessions in mongo are stored correctly.
It seems passport is not saving the session correctly.
The problem is in your deserializeUser method where you always run done callback twice. In if statement you should use return done(null, user); to get out from function;
I am trying to do salseforce aouth in nodejs using passportjs butt getting error.
Cannot GET /callback?code=aPrxaSyVmC8fBbcSNDQ8G8UtoR.YZip2hdfAGpMSc2hf0798gD_UoDle1dqqC0HnPyewycgKMw%3D%3D
Here is my code
'use strict';
var express = require('express'),
passport = require('passport'),
util = require('util'),
ForceDotComStrategy = require('passport-forcedotcom').Strategy;
//----------------------------------------------------------------------------
// REPLACE THE BELOW SETTING TO MATCH YOUR SALESFORCE CONNECTED-APP'S SETTINGS
//----------------------------------------------------------------------------
var CF_CLIENT_ID = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
var CF_CLIENT_SECRET = 'xxxxxxxxxxxxxxxxxxxxx';
var CF_CALLBACK_URL = 'http://localhost:3000/callback';
var SF_AUTHORIZE_URL = 'https://login.salesforce.com/services/oauth2/authorize';
var SF_TOKEN_URL = 'https://login.salesforce.com/services/oauth2/token';
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
var sfStrategy = new ForceDotComStrategy({
clientID: CF_CLIENT_ID,
clientSecret: CF_CLIENT_SECRET,
callbackURL: CF_CALLBACK_URL,
authorizationURL: SF_AUTHORIZE_URL,
tokenURL: SF_TOKEN_URL
}, function(accessToken, refreshToken, profile, done) {
process.nextTick(function() {
delete profile._raw;
return done(null, profile);
});
});
passport.use(sfStrategy);
var app = express();
// configure Express
app.configure(function() {
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.logger());
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.session({
secret: 'keyboard cat'
}));
// Initialize Passport! Also use passport.session() middleware, to support
// persistent login sessions (recommended).
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.get('/', function(req, res) {
console.log(req.user);
if(!req.user) {
req.session.destroy();
req.logout();
return res.redirect('/login');
}
res.render('index', {
user: req.user
});
});
app.get('/login', function(req, res) {
req.logout();
req.session.destroy();
res.render('login', {
user: req.user
});
});
app.get('/auth/forcedotcom', passport.authenticate('forcedotcom'), function(req, res) {
});
app.get('/auth/forcedotcom/callback', passport.authenticate('forcedotcom', {
successRedirect: '/',
failureRedirect: '/login'
}), function(req, res) {
res.redirect('/');
});
app.get('/logout', function(req, res) {
res.redirect('/login');
});
app.listen(3000);
console.log('localhost run in 3000');
function ensureAuthenticated(req, res, next) {
if(req.isAuthenticated()) {
return next();
}
res.redirect('/login');
}
I am trying to fix problem with already post a query in at there but that cannot resole Cannot GET /auth/twitter/callback while using twitter oauth in nodejs
looks like you've set the callback URL to http://yourdomain.com/callback in your salesforce oauth app, but have not define a handler for it correctly
either change the callback URL of your salesforce oauth app to
http://yourdomain.com/auth/forcedotcom/callback
or change the following in your code
app.get('/auth/forcedotcom/callback', passport.authenticate('...
to
app.get('/callback', passport.authenticate('forcedotcom', {
successRedirect: '/',
failureRedirect: '/login'
}), function(req, res) {
res.redirect('/');
});