Github user email is null, despite user:email scope

Solution 1:

I found out why this occurs and how to resolve it. According to the docs:

Note: The returned email is the user's publicly visible email address (or null if the user has not specified a public email address in their profile).

In your GitHub profile settings, under Public email, some users (including myself) have that option set to "Don't show my email address." The call to /user only returns the public email address, so if the user doesn't want it shown, the API will respect that.

enter image description here

To get the user's email addresses regardless of whether or not they are public, use the call to /user/emails. You would use the access token in exactly the same way as the /user request:

Accept-Language: en-us
Accept: application/json
Authorization: token 83f42..xxx
Accept-Encoding: gzip, deflate

GET https://api.github.com/user/emails

This call gave me the following JSON response:

[
  {
    "email": "[email protected]",
    "primary": true,
    "verified": true
  }
]

Solution 2:

Couldn't fit this into a comment, so answering for the node.js passport-github case:

var GitHubStrategy = require('passport-github').Strategy;

passport.use('github-login', new GitHubStrategy({
  clientID: config.clientId,
  clientSecret:  config.secret,
  callbackURL: config.host + config.callback,
  passReqToCallback: true, // req object on auth is passed as first arg
  scope: [ 'user:email' ], // fetches non-public emails as well
},
  function (req, accessToken, refreshToken, profile, done) {
    // find user by profile and update it
    // or create the user object given the req, tokens and profile objs
    // don't forget to call `done(null, user)` once done
}
));