Script Valley
Authentication From Scratch
OAuth 2.0 and Social LoginLesson 4.4

Adding GitHub OAuth login to an Express app

passport-github2, GitHub OAuth App setup, GitHub profile structure, scope parameter, public vs private email, handling users with no public email

GitHub OAuth Setup

GitHub OAuth follows the same authorization code flow as Google. Register an OAuth App in GitHub Settings → Developer settings → OAuth Apps. Set the callback URL to http://localhost:3000/auth/github/callback.

npm install passport-github2
const GitHubStrategy = require('passport-github2').Strategy;

passport.use(new GitHubStrategy({
  clientID: process.env.GITHUB_CLIENT_ID,
  clientSecret: process.env.GITHUB_CLIENT_SECRET,
  callbackURL: '/auth/github/callback',
  scope: ['user:email']
}, async (accessToken, refreshToken, profile, done) => {
  const email = profile.emails && profile.emails[0]
    ? profile.emails[0].value
    : null;

  let user = await db.findByGithubId(profile.id);
  if (!user) {
    user = await db.createUser({
      githubId: profile.id,
      email,
      name: profile.displayName || profile.username
    });
  }
  return done(null, user);
}));

GitHub Email Gotcha

GitHub users can make their email private. Without the user:email scope, profile.emails will be empty. Even with the scope, the array can be empty if the user has no verified email. Always handle the null case and allow users to add an email later. Never require an email at social-login time if you cannot guarantee it will be present.

Up next

OAuth callback routes and session handling with Passport

Sign in to track progress