Source: lib/oauth_util.js

"use strict";

// npm packages
var Oauth = require('oauth');

// Core packages
var url = require('url');

// Custom Packages
var errorStrings = require('./error');

/**
 * @namespace OauthUtil
 */

/**
 * Attempts to get an OAuth verification URL using the given API configuration.
 *
 * @memberOf OauthUtil
 * @param {Object} config The information needed to access the Jira API
 * @param {string} config.host The hostname of the Jira API.
 * @param {string} [config.protocol=https] - The protocol used to accses the Jira API.
 * @param {number} [config.port=443] - The port number used to connect to Jira.
 * @param {string} [config.path_prefix="/"] The prefix to use in front of the path, if Jira isn't at "/"
 * @param {string} [config.version=2] - The version of the Jira API to which you will be connecting.  Currently, only
 *     version 2 is supported.
 * @param {Object} config.oauth The oauth information
 * @param {string} config.oauth.consumer_key The consumer key of the application accessing Jira.
 * @param {string} config.oauth.private_key The private key of the application accessing Jira.
 * @param {string} [config.oauth.callback_url] The callback URL to be called after the token is generated.  If this is
 *     not included, the user will be given a verification code after authorizing the token, instead of Jira making a
 *     callback to the application.
 * @param {OauthUtil~getOauthUrlCallback} callback The function called when the URL has been retrieved.
 */
exports.getAuthorizeURL = function (config, callback) {
    var prefix = config.path_prefix ? config.path_prefix : '';
    var AUTH_TOKEN_APPEND = '/oauth/authorize';
    var SERVLET_BASE_URL = prefix + '/plugins/servlet';

    var authURL = url.format({
        protocol: config.protocol ? config.protocol : 'https',
        hostname: config.host,
        port: config.port ? config.port : null,
        pathname: SERVLET_BASE_URL + AUTH_TOKEN_APPEND
    });

    var oauth = generateOAuthObject(config);

    oauth.getOAuthRequestToken(function (err, token, token_secret) {
        if (err) {
            return callback(err);
        }
        return callback(null, { url: authURL + "?oauth_token=" + token, token: token, token_secret: token_secret });
    });
};

/**
 * Given an OAuth token, the token secret, and an access verification code (provided by Jira), swap an OAuth request
 * token with an OAuth access token.
 *
 * @memberOf OauthUtil
 * @param {Object} config The information needed to access the Jira API
 * @param {string} config.host The hostname of the Jira API.
 * @param {string} [config.protocol=https] - The protocol used to accses the Jira API.
 * @param {number} [config.port=443] - The port number used to connect to Jira.
 * @param {string} [config.version=2] - The version of the Jira API to which you will be connecting.  Currently, only
 *     version 2 is supported.
 * @param {Object} config.oauth The oauth information
 * @param {string} config.oauth.consumer_key The consumer key of the application accessing Jira.
 * @param {string} config.oauth.private_key The private key of the application accessing Jira.
 * @param {string} config.oauth.token The OAuth Token supplied by Jira.
 * @param {string} config.oauth.token_secret The OAuth Token secret supplied by Jira.
 * @param {string} config.oauth.oauth_verifier The verified code given to the user after authorizing the OAuth token.
 * @param {OauthUtil~swapRequestTokenCallback} callback The function called when the token has been swapped.
 */
exports.swapRequestTokenWithAccessToken = function (config, callback) {
    if (!config.oauth.oauth_verifier) {
        throw new Error(errorStrings.NO_VERIFIER_ERROR);
    }

    var oauth = generateOAuthObject(config);

    var token = config.oauth.token;
    var secret = config.oauth.token_secret;
    var verifier = config.oauth.oauth_verifier;

    oauth.getOAuthAccessToken(token, secret, verifier, callback);
};

/**
 * Utility function to generate an OAuth object.
 *
 * @memberOf OauthUtil
 * @param {Object} config The information needed to access the Jira API
 * @param {string} config.host The hostname of the Jira API.
 * @param {string} [config.protocol=https] - The protocol used to accses the Jira API.
 * @param {number} [config.port=443] - The port number used to connect to Jira.
 * @param {string} [config.path_prefix="/"] The prefix to use in front of the path, if Jira isn't at "/"
 * @param {string} [config.version=2] - The version of the Jira API to which you will be connecting.  Currently, only
 *     version 2 is supported.
 * @param {Object} config.oauth The oauth information
 * @param {string} config.oauth.consumer_key The consumer key of the application accessing Jira.
 * @param {string} config.oauth.private_key The private key of the application accessing Jira.
 * @param {string} [config.oauth.callback_url] The callback URL to be called after the token is generated.  If this is
 *     not included, the user will be given a verification code after authorizing the token, instead of Jira making a
 *     callback to the application.
 *
 * @returns {exports.OAuth} The generated object.
 */
function generateOAuthObject(config) {
    var prefix = config.path_prefix ? config.path_prefix : '';
    var SERVLET_BASE_URL = prefix + '/plugins/servlet';
    var REQ_TOKEN_APPEND = '/oauth/request-token';

    var ACCESS_TOKEN_APPEND = '/oauth/access-token';
    var sig = 'RSA-SHA1';

    if (!config.host) {
        throw new Error(errorStrings.NO_HOST_ERROR);
    } else if (!config.oauth.consumer_key) {
        throw new Error(errorStrings.NO_CONSUMER_KEY_ERROR);
    } else if (!config.oauth.private_key) {
        throw new Error(errorStrings.NO_PRIVATE_KEY_ERROR);
    }

    var consumer_key = config.oauth.consumer_key;
    var private_key = config.oauth.private_key;

    var reqURL = url.format({
        protocol: config.protocol ? config.protocol : 'https',
        hostname: config.host,
        port: config.port ? config.port : null,
        pathname: SERVLET_BASE_URL + REQ_TOKEN_APPEND
    });

    var accessURL = url.format({
        protocol: config.protocol ? config.protocol : 'https',
        hostname: config.host,
        port: config.port ? config.port : null,
        pathname: SERVLET_BASE_URL + ACCESS_TOKEN_APPEND
    });

    var cb = config.oauth.callback_url ? config.oauth.callback_url : 'oob';

    return new Oauth.OAuth(reqURL, accessURL, consumer_key, private_key, '1.0', cb, sig);
}

/**
 * Callback used by getOauthUrl.
 * @callback OauthUtil~getOauthUrlCallback
 * @param {*} error The error which occurred, if any.
 * @param {Object} oauth The OAuth information retrieved from the Jira API.
 * @param {String} oauth.url The URL that should be visited by the user to verify the OAuth access.
 * @param {String} oauth.token The OAuth Token retrieved from the Jira API.
 * @param {String} oauth.token_secret The OAuth Token Secret retrieved from the Jira API.
 */

/**
 * Callback used by swapRequestTokenWithAccessToken
 * @callback OauthUtil~swapRequestTokenCallback
 * @param {*} error The error which occurred, if any.
 * @param {string} access_token The access token retrieved from Jira.
 */