Home Reference Source Test Repository

src/oauth_connector.js

'use strict';
import Bluebird from 'bluebird';
import config from 'config';
import url from 'url';
import {
  clone
}
from 'lodash';
import {
  OAuth
}
from '@hoist/oauth';
import logger from '@hoist/logger';

/**
 * @protected
 * The base OAuth2 Connector class used for Hoist Connectors to implement OAuth2 flows
 * @implements {ConnectorInterface}
 */
export default class OAuthConnectorBase {

  /**
   * @protected
   * create a new OAuth2Connector
   * @param {object} configuration - the configuration details for this connector
   * @param {string} configuration.consumerKey - the OAuth consumer key
   * @param {string} configuration.consumerSecret - the OAuth consumer secret
   * @param {string} configuration.requestTokenUri - the uri to use for request token calls
   * @param {string} configuration.accessTokenUri - the uri to use for access token calls
   * @param {string} configuration.authorizationUri - the uri to send users to authorise access
   * @param {object} [configuration.oauthVersion=1.0A] - the version of OAuth to use
   * @param {object} [configuration.signingMethod=HMAC-SHA1] - the signing method to use
   */
  constructor(configuration) {
    this._logger = logger.child({
      cls: this.constructor.name
    });
    this._configuration = configuration;
    this._configuration.authorizationUri = url.parse(this._configuration.authorizationUri, true);
    this._auth = Bluebird.promisifyAll(
      new OAuth(
        configuration.requestTokenUri,
        configuration.accessTokenUri,
        configuration.consumerKey,
        configuration.consumerSecret,
        configuration.oauthVersion || '1.0A',
        `https://${config.get('Hoist.domains.bouncer')}/bounce`,
        configuration.signingMethod || 'HMAC-SHA1'
      ));
    this._auth._performSecureRequestAsync = Bluebird.promisify(this._auth._performSecureRequest, this._auth)
  }

  /**
   * perform an authorized request
   * @param {string} method - the HTTP method to call
   * @param {string} requestUri - the uri of the request to call
   * @param {string} body - the data to send
   * @param {string} contentType - the contentType header
   */
  _performRequest(method, requestUri, body, contentType) {
    return this._auth._performSecureRequestAsync(
      this._accessToken,
      this._accessTokenSecret,
      method,
      requestUri,
      null,
      body,
      contentType)
  }

  /**
   * authorize the oauth connection with existing parameters
   * @param {<AuthorizationStore>} authorization - the users authorization
   */
  authorize(authorization) {
    this._accessToken = authorization.get('AccessToken');
    this._accessTokenSecret = authorization.get('AccessTokenSecret');
  }

  /**
   * @param {AuthorizationStore} authorization - the users authorization
   */
  receiveBounce(authorization) {
    this._logger.info('receiving bounce');
    var authStep = authorization.get('currentStep');
    switch (authStep) {
    case 'RequestToken':
      //get access token
      this._logger.info('requesting access token');
      return this._auth.getOAuthAccessTokenAsync(
          authorization.get('RequestToken'),
          authorization.get('RequestTokenSecret'),
          authorization.query.oauth_verifier)
        .then((results) => {
          return Promise.all([
            authorization.set('AccessToken', results[0]),
            authorization.set('AccessTokenSecret', results[1]),
            authorization.set('currentStep', 'AccessToken')
          ]).then(() => {
            return authorization.done();
          });
        })

      break;

    default:
      //do request token auth
      this._logger.info('requesting request token');
      return this._auth.getOAuthRequestTokenAsync()
        .then((results) => {
          return Promise.all([
            authorization.set('RequestToken', results[0]),
            authorization.set('RequestTokenSecret', results[1]),
            authorization.set('currentStep', 'RequestToken')
          ]).then(() => {
            this._logger.info('redirecting user');
            let authorizationUri = this._configuration.authorizationUri;
            authorizationUri.query = authorizationUri.query || {};
            authorizationUri.query.oauth_token = results[0];
            return authorization.redirect(authorizationUri.format())
          });
        });
    }
    //default just mark as done
    return authorization.done();
  }

}