all files / express-stormpath/lib/controllers/ github-login.js

6.25% Statements 3/48
0% Branches 0/24
0% Functions 0/7
6.25% Lines 3/48
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100                                                                                                                                                                                                 
'use strict';
 
var helpers = require('../helpers');
var oauth = require('../oauth');
 
/**
 * This controller logs in a user with GitHub OAuth.
 *
 * When a user logs in with GitHub (using JavaScript), GitHub will redirect the
 * user to this view, along with an access code for the user.
 *
 * What we do here is grab this access code, exchange it for an access token
 * using the GitHub API, and lastly send it to Stormpath to handle the OAuth
 * negotiation. Once this is done, we log this user in using normal sessions,
 * and from this point on -- this user is treated like a normal system user!
 *
 * @method
 *
 * @param {Object} req - The http request.
 * @param {Object} res - The http response.
 */
module.exports = function (req, res) {
  var application = req.app.get('stormpathApplication');
  var config = req.app.get('stormpathConfig');
  var logger = req.app.get('stormpathLogger');
  var loginHandler = config.postLoginHandler;
  var registrationHandler = config.postRegistrationHandler;
  var provider = config.web.social.github;
  var baseUrl = config.web.baseUrl || req.protocol + '://' + helpers.getHost(req);
  var authUrl = 'https://github.com/login/oauth/access_token';
  var code = req.query.code;
  var error = req.query.error;
 
  if (error) {
    logger.info('A user attempted to log in via GitHub OAuth but recieved the error " ' + error + '"');
    return oauth.errorResponder(req, res, new Error(error));
  }
 
  if (!code) {
    logger.info('A user attempted to log in via GitHub OAuth without specifying an OAuth token.');
    return oauth.errorResponder(req, res, new Error('code parameter required.'));
  }
 
  oauth.common.exchangeAuthCodeForAccessToken(authUrl, code, req.cookies.oauthStateToken, baseUrl, provider, function (err, accessToken) {
    if (err) {
      logger.info('During a GitHub OAuth login attempt, we were unable to exchange the authentication code for an access token.');
      return oauth.errorResponder(req, res, err);
    }
 
    var userData = {
      providerData: {
        accessToken: accessToken,
        providerId: 'github'
      }
    };
 
    application.getAccount(userData, function (err, resp) {
      if (err) {
        logger.info('During a GitHub OAuth login attempt, we were unable to fetch the user\'s social account from Stormpath.');
        return oauth.errorResponder(req, res, err);
      }
 
      helpers.expandAccount(resp.account, config.expand, logger, function (err, expandedAccount) {
        if (err) {
          logger.info('During a GitHub OAuth login attempt, we were unable to fetch the user\'s social account from Stormpath.');
          return oauth.errorResponder(req, res, err);
        }
 
        res.locals.user = expandedAccount;
        req.user = expandedAccount;
 
        helpers.createStormpathSession(req.user, req, res, function (err) {
          if (err) {
            logger.info('During a GitHub OAuth login attempt, we were unable to create a Stormpath session.');
            return oauth.errorResponder(req, res, err);
          }
 
          var nextUrl = oauth.common.consumeRedirectUri(req, res);
 
          if (!nextUrl) {
            nextUrl = resp.created ? config.web.register.nextUri : config.web.login.nextUri;
          }
 
          if (resp.created && registrationHandler) {
            registrationHandler(req.user, req, res, function () {
              res.redirect(302, nextUrl);
            });
          } else if (loginHandler) {
            loginHandler(req.user, req, res, function () {
              res.redirect(302, nextUrl);
            });
          } else {
            res.redirect(302, nextUrl);
          }
        });
      });
    });
  });
};