Last active
December 14, 2015 11:58
-
-
Save andris9/5082700 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var crypto = require("crypto"), | |
urllib = require("url"); | |
/** | |
* Wrapper for new OAuthGenerator. | |
* | |
* Usage: | |
* | |
* var OAuthgen = createOAuthGenerator({}); | |
* OAuthgen.getToken(function(err, OAuthtoken){ | |
* request.headers['Authorization'] = OAuthtoken; | |
* }); | |
* | |
* @param {Object} options See OAuth2Generator for details | |
* @return {Object} | |
*/ | |
createOAuthGenerator = function(options){ | |
return new OAuthGenerator(options); | |
}; | |
/** | |
* Create a OAUTH login token generator | |
* | |
* @constructor | |
* @memberOf xoauth | |
* @param {Object} options | |
* @param {String} options.consumerKey OAuth consumer key | |
* @param {String} options.consumerSecret OAuth consumer secret | |
* @param {String} options.requestorId 2 legged OAuth requestor ID (e-mail address) | |
* @param {String} [options.nonce] Nonce value to be used for OAuth | |
* @param {Number} [options.timestamp] Unix timestamp value to be used for OAuth | |
* @param {String} options.requestUrl OAuth request URL | |
* @param {String} [options.method="GET"] OAuth request method | |
*/ | |
function OAuthGenerator(options){ | |
this.options = options || {}; | |
} | |
/** | |
* Generates an OAuth authorization token, that can be used for "Authorization: " header | |
* | |
* @param {Function} callback Returns an error object and the token string | |
*/ | |
OAuthGenerator.prototype.getToken = function(callback){ | |
generateOAuthStr(this.options, function(err, token){ | |
if(err){ | |
return callback(err); | |
} | |
callback(null, "OAuth "+token); | |
}); | |
}; | |
/** | |
* Generate a OAuth login token | |
* | |
* @param {Function} [callback] Callback function to run when the access token is genertaed | |
* @return {String|undefined} If callback is not set, return the token value, otherwise run callback instead | |
*/ | |
OAuthGenerator.prototype.generate = function(callback){ | |
return generateOAuthStr(this.options, callback); | |
}; | |
// Helper functions | |
/** | |
* Converts an array into urlencoded strings concated with & | |
* | |
* @param {Array} arr An array of strings to be concated | |
* @return {String} Urlencoded and concated string | |
*/ | |
function escapeAndJoin(arr){ | |
return arr.map(encodeURIComponent).join("&"); | |
} | |
/** | |
* Create a HMAC-SHA1 hash | |
* | |
* @param {String} str String to be hashed | |
* @param {String} key HMAC key to be used for hashing | |
* @param {String} Base64 encoded hash | |
*/ | |
function hmacSha1(str, key){ | |
var hmac = crypto.createHmac("sha1", key); | |
hmac.update(str); | |
return hmac.digest("base64"); | |
} | |
/** | |
* Setup OAuth params for signing and sending, generates a nonce and a timestamp | |
* if needed | |
* | |
* @param {Object} options OAuth params | |
* @return {Object} OAuth params | |
*/ | |
function initOAuthParams(options){ | |
return { | |
oauth_consumer_key: options.consumerKey || "anonymous", | |
oauth_nonce: options.nonce || "" + Date.now() + Math.round(Math.random()*1000000), | |
oauth_signature_method: "HMAC-SHA1", | |
oauth_version: "1.0", | |
oauth_timestamp: options.timestamp || "" + Math.round(Date.now()/1000) | |
}; | |
} | |
/** | |
* Generates the string that will be signed, includes HTTP method, request url | |
* and oauth params. | |
* | |
* @param {String} method HTTP method (eg. "POST") | |
* @param {String} requestUrl Target url for the request being made | |
* @param {Object} params Params object created with initOAuthParams() | |
* @return {String} urlencoded and & concatted string | |
*/ | |
function generateOAuthBaseStr(method, requestUrl, params){ | |
var reqArr = [method, requestUrl].concat(Object.keys(params).sort().map(function(key){ | |
return key + "=" + encodeURIComponent(params[key]); | |
}).join("&")); | |
return escapeAndJoin(reqArr); | |
} | |
/** | |
* Generates the token using provided options | |
* | |
* @param {Object} options OAuth options | |
* @param {Function} callback Callback function to run with the token | |
*/ | |
function generateOAuthStr(options, callback){ | |
options = options || {}; | |
var params = initOAuthParams(options), | |
requestUrl = options.requestUrl || "https://mail.google.com/mail/b/" + (options.user || "") + "/imap/", | |
baseStr, signatureKey, paramsStr; | |
var urlparts = urllib.parse(requestUrl, true); | |
Object.keys(urlparts.query).forEach(function(key){ | |
params[key] = urlparts.query[key]; | |
}); | |
if(options.token && !options.requestorId){ | |
params.oauth_token = options.token; | |
} | |
if(options.requestorId){ | |
params.xoauth_requestor_id = options.requestorId; | |
} | |
if(options.key){ | |
params.key = options.key; | |
} | |
baseStr = generateOAuthBaseStr(options.method || "GET", requestUrl.split("?").shift(), params); | |
signatureKey = escapeAndJoin([options.consumerSecret || "anonymous", options.tokenSecret || ""]); | |
params.oauth_signature = hmacSha1(baseStr, signatureKey); | |
Object.keys(urlparts.query).forEach(function(key){ | |
delete params[key]; | |
}); | |
delete params.key; | |
delete params.xoauth_requestor_id; | |
paramsStr = Object.keys(params).sort().map(function(key){ | |
return key+"=\""+encodeURIComponent(params[key])+"\""; | |
}).join(","); | |
callback(null, paramsStr); | |
} | |
var OAuthgen = createOAuthGenerator({ | |
requestorId: "[email protected]", | |
consumerKey: "node.ee", | |
consumerSecret: "qwerty...", | |
key: "poiuyt...", | |
nonce: "12345", | |
timestamp: "123456", | |
requestUrl: "https://www.googleapis.com/calendar/v3/users/me/calendarList", | |
method: "GET" | |
}); | |
OAuthgen.getToken(function(err, OAuthtoken){ | |
console.log("curl -X" + OAuthgen.options.method + " \"" + OAuthgen.options.requestUrl+(OAuthgen.options.requestUrl.match(/\?/)?"&":"?")+ | |
"xoauth_requestor_id="+encodeURIComponent(OAuthgen.options.requestorId)+ | |
"&"+ | |
"key="+encodeURIComponent(OAuthgen.options.key) +"\" --header 'Authorization: " + OAuthtoken + "'") | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment