%PDF- %PDF-
Direktori : /home/opti/workflow/node_modules/xoauth2/ |
Current File : /home/opti/workflow/node_modules/xoauth2/index.js |
var Stream = require("stream").Stream, utillib = require("util"), querystring = require("querystring"), http = require("http"), https = require("https"), urllib = require("url"); /** * Wrapper for new XOAuth2Generator. * * Usage: * * var xoauthgen = createXOAuth2Generator({}); * xoauthgen.getToken(function(err, xoauthtoken){ * socket.send("AUTH XOAUTH2 " + xoauthtoken); * }); * * @param {Object} options See XOAuth2Generator for details * @return {Object} */ module.exports.createXOAuth2Generator = function(options){ return new XOAuth2Generator(options); }; /** * XOAUTH2 access_token generator for Gmail. * Create client ID for web applications in Google API console to use it. * See Offline Access for receiving the needed refreshToken for an user * https://developers.google.com/accounts/docs/OAuth2WebServer#offline * * @constructor * @param {Object} options Client information for token generation * @param {String} options.user (Required) User e-mail address * @param {String} options.clientId (Required) Client ID value * @param {String} options.clientSecret (Required) Client secret value * @param {String} options.refreshToken (Required) Refresh token for an user * @param {String} options.accessUrl (Optional) Endpoint for token generation, defaults to "https://accounts.google.com/o/oauth2/token" * @param {String} options.accessToken (Optional) An existing valid accessToken * @param {int} options.timeout (Optional) A timestamp in milliseconds after 1.1.1970 when the given accessToken expires */ function XOAuth2Generator(options){ Stream.call(this); this.options = options || {}; this.options.accessUrl = this.options.accessUrl || "https://accounts.google.com/o/oauth2/token"; this.token = this.options.accessToken && this.buildXOAuth2Token(this.options.accessToken) || false; this.accessToken = this.token && this.options.accessToken || false; this.timeout = this.options.timeout && Date.now() + ((Number(this.options.timeout) || 0) - 1) * 1000 || 0; } utillib.inherits(XOAuth2Generator, Stream); /** * Returns or generates (if previous has expired) a XOAuth2 token * * @param {Function} callback Callback function with error object and token string */ XOAuth2Generator.prototype.getToken = function(callback){ if(this.token && (!this.timeout || this.timeout > Date.now())){ return callback(null, this.token, this.accessToken); } this.generateToken(callback); }; /** * Updates token values * * @param {String} accessToken New access token * @param {Number} timeout Access token lifetime in seconds * * Emits 'token': { user: User email-address, accessToken: the new accessToken, timeout: Timestamp in seconds after 1.1.1970 } */ XOAuth2Generator.prototype.updateToken = function(accessToken, timeout){ this.token = this.buildXOAuth2Token(accessToken); this.accessToken = accessToken; this.timeout = timeout && Date.now() + ((Number(timeout) || 0) - 1) * 1000 || 0; this.emit("token", { user: this.options.user, accessToken: accessToken || "", timeout: Math.floor(this.timeout/1000) }); }; /** * Generates a new XOAuth2 token with the credentials provided at initialization * * @param {Function} callback Callback function with error object and token string */ XOAuth2Generator.prototype.generateToken = function(callback){ var urlOptions = { client_id: this.options.clientId || "", client_secret: this.options.clientSecret || "", refresh_token: this.options.refreshToken, grant_type: "refresh_token" }, payload = querystring.stringify(urlOptions); postRequest(this.options.accessUrl, payload, (function(error, response, body){ var data; if(error){ return callback(error); } try{ data = JSON.parse(body.toString()); }catch(E){ return callback(E); } if(!data || typeof data != "object"){ return callback(new Error("Invalid authentication response")); } if(data.error){ return callback(new Error(data.error)); } if(data.access_token){ this.updateToken(data.access_token, data.expires_in); return callback(null, this.token, this.accessToken); } return callback(new Error("No access token")); }).bind(this)); }; /** * Converts an access_token and user id into a base64 encoded XOAuth2 token * * @param {String} accessToken Access token string * @return {String} Base64 encoded token for IMAP or SMTP login */ XOAuth2Generator.prototype.buildXOAuth2Token = function(accessToken){ var authData = [ "user=" + (this.options.user || ""), "auth=Bearer " + accessToken, "", ""]; return new Buffer(authData.join("\x01"), "utf-8").toString("base64"); }; function postRequest(url, payload, callback){ var options = urllib.parse(url), finished = false; options.method = "POST"; var req = (options.protocol=="https:"?https:http).request(options, function(res) { var data = []; res.on('data', function (chunk) { data.push(chunk); }); res.on("end", function(){ if(finished){return;} finished = true return callback(null, res, Buffer.concat(data)); }); res.on("error", function(err) { if(finished){return;} finished = true callback(err); }); }); req.on("error", function(err) { if(finished){return;} finished = true callback(err); }); if(payload){ req.setHeader("Content-Type", "application/x-www-form-urlencoded"); req.setHeader("Content-Length", typeof payload == "string" ? Buffer.byteLength(payload) : payload.length); } req.write(payload); req.end(); }