问题
There are many questions relating to getting a req.user undefined after social authentication, but I found none which could help me.
I have been able to successfully use the example for using passport for twitter authentication: https://github.com/passport/express-4.x-twitter-example. I tried to follow this pattern as closely as possible but cannot seem to get it to work.
Specifically, I am able to successfully authenticate, but the req.user is undefined. This makes no sense to me as my user data was returned no problem from the example.
I'm not inclined to believe this is a middleware problem (as it has been for others) as the middleware is the same as that used in the example. It could be something about having multiple domains, but I'm not sure what. All of this is being done on the localhost.
In Twitter, the app is set up so that website is: 127.0.0.1:3000/signin and the callback url is: 127.0.0.1:2999/auth/twitter/return
As you can tell, my client is working on port 3000 and it is making calls to a server running on port 2999.
To briefly walk you through the code, the client on 127.0.0.1:3000/signin has a button which links to 127.0.0.1:2999/auth/twitter, thus initiating the authentication request. Under the hood, the express server is created in server/index.js--server. This imports the routes in routes/index.js, some of which the controller authenticate.js handles. As you can see, the oauth twitter request is made in authenticate.js. Again, authentication proceeds successfully, I am redirected to 127.0.0.1:3000/search. However, as you can see in this.twitter_callback, I am printing the req.user and it is undefined.
Please note that I have redacted the consumer key/secret from my code.
server/index.js
var cors = require('cors')
var bodyParser = require('body-parser')
var express = require('express');
var app = express();
var http = require('http').Server(app)
var io = require('socket.io')(http)
// NOT SURE WHY I NEED TO GO BACK 3 FOLDERS TO GET TO PORT_CONFIG
var port = require("../port_config.json").server_port;
var PORT = Number(process.env.PORT || port);
var routes = require('./routes/index.js')
var database = require('./database/db.js')
var db = new database()
app.use(cors()); // middleware that allows cross-platform requests
app.use(bodyParser.json());
db.dbConnect(function(err,db_instance){
// routes
routes(app, db_instance, io)
// send user polls on connection
// TEMPORARY (WILL BE GRABBED ON LOGIN)
var user = null // WILL BE SET AFTER LOGIN
io.on('connection', function(socket) {
var places_attending = db_instance.collection('places_attending')
places_attending.find({}).toArray(function(err,docs){
var places_user_attending = docs.map(doc => {
if (doc.attending.indexOf(user) !== -1) {
return {
id: doc.id,
name: doc.name,
num_attending: doc.attending.length
}
}
})
socket.emit('places_user_attending', places_user_attending);
})
})
})
http.listen(PORT, function () {
console.log('Backend server listening at http://localhost:' + PORT);
})
module.exports = http
routes/index.js
var Search = require('../controllers/search.js')
var Add = require('../controllers/add.js')
var Authenticate = require('../controllers/authenticate.js')
module.exports = function(app, db, io) {
var search = new Search(db, io)
var add = new Add(db, io)
var authenticate = new Authenticate(app)
app.route('/api/search')
.post(search.search_yelp)
app.route('/api/add')
.post(add.add_attendee)
app.route('/auth/twitter')
.get(authenticate.twitter_authentication)
app.route('/auth/twitter/return')
.get(authenticate.twitter_callback)
}
authenticate.js
function authenticate(app) {
var passport = require('passport');
var Strategy = require('passport-twitter').Strategy;
// Configure the Twitter strategy for use by Passport.
passport.use(new Strategy({
consumerKey: REDACTED,
consumerSecret: REDACTED,
callbackURL: 'http://127.0.0.1:2999/auth/twitter/return'
},
function(token, tokenSecret, profile, cb) {
// In this example, the user's Twitter profile is supplied as the user
// record. In a production-quality application, the Twitter profile should
// be associated with a user record in the application's database, which
// allows for account linking and authentication with other identity
// providers.
return cb(null, profile);
}));
// Configure Passport authenticated session persistence.
passport.serializeUser(function(user, cb) {
cb(null, user);
});
passport.deserializeUser(function(obj, cb) {
cb(null, obj);
});
// Use application-level middleware for common functionality, including
// logging, parsing, and session handling.
app.use(require('morgan')('combined'));
app.use(require('cookie-parser')());
app.use(require('body-parser').urlencoded({ extended: true }));
app.use(require('express-session')({ secret: 'keyboard cat', resave: true, saveUninitialized: true }));
// Initialize Passport and restore authentication state, if any, from the
// session.
app.use(passport.initialize());
app.use(passport.session());
this.twitter_authentication = passport.authenticate('twitter')
this.twitter_callback = (
passport.authenticate('twitter', { failureRedirect: 'http://127.0.0.1:3000/signin' }),
function(req, res) {
console.log('REQ.USER OBJECT: ' + req.user)
res.redirect('http://127.0.0.1:3000/search');
}
)
}
module.exports = authenticate
Any help would be greatly, greatly appreciated.
回答1:
The problem was in how my twitter_callback route was specified.
If I change the callback to this:
this.twitter_callback = app.get('/auth/twitter/return',
passport.authenticate('twitter', { failureRedirect: 'http://127.0.0.1:3000/signin' }),
function(req, res) {
console.log(req.user)
res.redirect('http://127.0.0.1:3000/search');
})
everything works fine. I think this has something to do with the middleware not being applied correctly the initial way I wrote it. Not exactly sure how I would rewrite it to export it, without using app.get in the twitter_callback though
来源:https://stackoverflow.com/questions/36378540/req-user-undefined-after-twitter-authentication-using-express-sever-passport-js