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

8.33% Statements 4/48
0% Branches 0/26
0% Functions 0/8
8.33% Lines 4/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 101 102 103 104 105 106 107 108 109 110 111                                                                                                                                                                                                                     
'use strict';
 
var helpers = require('../helpers');
var oauth = require('../oauth');
 
/**
 * This controller logs in an existing user with Facebook OAuth.
 *
 * When a user logs in with Facebook, all of the authentication happens on the
 * client side with Javascript.  Since all authentication happens with
 * Javascript, we *need* to force a newly created and / or logged in Facebook
 * user to redirect to this controller.
 *
 * What this controller does is:
 *
 *  - Grabs the user's Facebook access token from the query string.
 *  - Once we have the user's access token, we send it to Stormpath, so that
 *    we can either create (or update) the user on Stormpath's side.
 *  - Then we retrieve the Stormpath account object for the user, and log
 *    them in using our normal session support.
 *
 * The URL this controller is bound to, and the view used to render this page
 * can all be controlled via express-stormpath settings.
 *
 * @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.facebook;
  var authUrl = 'https://graph.facebook.com/oauth/access_token';
  var baseUrl = config.web.baseUrl || req.protocol + '://' + helpers.getHost(req);
 
  function loginWithAccessToken(accessToken) {
    if (!accessToken) {
      logger.info('A user attempted to log in via Facebook OAuth without specifying an OAuth token.');
      return oauth.errorResponder(req, res, new Error('Access token parameter required.'));
    }
 
    var userData = {
      providerData: {
        accessToken: accessToken,
        providerId: 'facebook'
      }
    };
 
    application.getAccount(userData, function (err, resp) {
      if (err) {
        logger.info('During a Facebook 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 Facebook 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 Facebook 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);
          }
        });
      });
    });
  }
 
  if (req.query.code) {
    oauth.common.exchangeAuthCodeForAccessToken(authUrl, req.query.code, req.cookies.oauthStateToken, baseUrl, provider, function (err, accessToken) {
      if (err) {
        logger.info('During a Facebook OAuth login attempt, we were unable to exchange the authentication code for an access token.');
        return oauth.errorResponder(req, res, err);
      }
 
      loginWithAccessToken(accessToken);
    });
  } else if (req.query.access_token) {
    loginWithAccessToken(req.query.access_token);
  }
};