jaredhanson/passport-twitter

unable to get user email.

Adetona opened this issue ยท 8 comments

I've requested permission from apps.twitter.com and the authentication process is working successfully but twitter is not returning the user's email. Please check my code if there is something wrong with what I'm doing. Thanks

var passport = require('passport');
var LocalStrategy    = require('passport-local').Strategy;
var TwitterStrategy  = require('passport-twitter').Strategy;

// load up the user model
var User       = require('../app/models/user');

// load the auth variables
var configAuth = require('./auth');

module.exports = function(passport) {

    // used to serialize the user for the session
    passport.serializeUser(function(user, done) {
        done(null, user.id);
    });

    // used to deserialize the user
    passport.deserializeUser(function(id, done) {
        User.findById(id, function(err, user) {
            done(err, user);
        });
    });

    // code for login (use('local-login', new LocalStategy))
    // code for signup (use('local-signup', new LocalStategy))
    // code for facebook (use('facebook', new FacebookStrategy))

    // =========================================================================
    // TWITTER =================================================================
    // =========================================================================
    passport.use(new TwitterStrategy({

        consumerKey     : configAuth.twitterAuth.consumerKey,
        consumerSecret  : configAuth.twitterAuth.consumerSecret,
        callbackURL     : configAuth.twitterAuth.callbackURL,
        userProfileURL: "https://api.twitter.com/1.1/account/verify_credentials.json?include_email=true",
         passReqToCallback : true,

    },
    function(token, tokenSecret, profile, done) {

        // make the code asynchronous
    // User.findOne won't fire until we have all our data back from Twitter
        process.nextTick(function() {

            User.findOne({ 'twitter.id' : profile.id }, function(err, user) {

                // if there is an error, stop everything and return that
                // ie an error connecting to the database
                if (err)
                    return done(err);

                // if the user is found then log them in
                if (user) {
                    return done(null, user); // user found, return that user
                } else {
                    // if there is no user, create them
                    var newUser                 = new User();

                    // set all of the user data that we need
                    newUser.twitter.id          = profile.id;
                    newUser.twitter.token       = token;
                    newUser.twitter.username    = profile.username;
                    newUser.twitter.displayName = profile.displayName;
                    newUser.twitter.email       = profile.email; 

                    // save our user into the database
                    newUser.save(function(err) {
                        if (err)
                            throw err;
                        return done(null, newUser);
                    });
                }
            });

    });

    }));

};

same here

I can confirm this issue. Any status on a fix?

@ahromyak @nsuchy Yes, there is now a fix.

Simply pass profile.emails[0].value to the variable you want to save your email to.

Example:

newUser.twitter.email = profile.emails[0].value

I'm sorry it took me so long to give a response.

Twitter can return the email but if you don't explicitly ask for it it will not. By reading the source code of this Strategy, here is how you should ask for the email:

TwitterStrategy({
    consumerKey: configAuth.twitterAuth.consumerKey,
    consumerSecret : configAuth.twitterAuth.consumerSecret,
    callbackURL: configAuth.twitterAuth.callbackURL,
    includeEmail: true, // <======= this
    // also other options
  },
  // ...
)

As written here https://github.com/jaredhanson/passport-twitter/blob/master/lib/strategy.js#L119

It will return the email of the user in his profile in the field email as you expected.

Also try going to the developer console, the "Permissions" tab, click "Edit", check off "Request email address from users" under "Additional permissions" and click "Save".

consumerKey: process.env.CONSUMER_KEY,
consumerSecret: process.env.CONSUMER_SECRET,
includeEmail: true,
callbackURL: '/dashboard/auth/callback',
proxy: true

This is my strategy, and here, 99% of the time I receive an email address, but not 1% of the time. How can I solve this?

I tried both includeEmail and userProfileURL with include_email parameter set to true and they still don't work. includeEmail doesn't return profile.emails, and userProfileURL with a include_email query will throw 500 Internal Server Error

Edit: I do have permission enabled on twitter API and regenerated the key and secret

Twitter can return the email but if you don't explicitly ask for it it will not. By reading the source code of this Strategy, here is how you should ask for the email:

TwitterStrategy({
    consumerKey: configAuth.twitterAuth.consumerKey,
    consumerSecret : configAuth.twitterAuth.consumerSecret,
    callbackURL: configAuth.twitterAuth.callbackURL,
    includeEmail: true, // <======= this
    // also other options
  },
  // ...
)

As written here https://github.com/jaredhanson/passport-twitter/blob/master/lib/strategy.js#L119

It will return the email of the user in his profile in the field email as you expected.

Hi we are running into this problem right now, and this solution includeEmail: true does not work. Could you take a look at our stackoverflow? https://stackoverflow.com/questions/75180779/node-js-passport-twitter-unable-to-get-user-email-in-passport-twitter-authentic