Skip to content

Instantly share code, notes, and snippets.

@yoavniran
Last active May 6, 2024 12:33
Show Gist options
  • Save yoavniran/06454e87a3b8d858614e to your computer and use it in GitHub Desktop.
Save yoavniran/06454e87a3b8d858614e to your computer and use it in GitHub Desktop.
class used to allow making authorized requests to google API that also allows streaming the response even if a token refresh is required
"use strict";
var util = require("util"),
_ = require("underscore"),
events = require("events"),
request = require("request"),
AppAuthClient = require("../google/AppAuthClient"); //thin wrapper around the google oauth2client - simply initializing it with app's client id and secret
var SimpleAuthTransporter= (function () {
var _USER_AGENT = "css-server@node";
var SimpleAuthTransporter = function () {
events.EventEmitter.call(this);
};
util.inherits(SimpleAuthTransporter, events.EventEmitter);
SimpleAuthTransporter.prototype.request = function (options, responseCallback) {
var tokenInfo = options.tokens;
responseCallback = _wrapResponseCallback(responseCallback);
if (tokenInfo) {
if (!tokenInfo.access_token && !tokenInfo.refresh_token) {
responseCallback(new Error("access token or refresh tokens not supplied"));
return;
}
var isTokenExpired = tokenInfo.expiry_date ? tokenInfo.expiry_date <= (new Date()).getTime() : false; //logic taken from google's api node client: oauth2client class
if (!tokenInfo.access_token || isTokenExpired){
_refreshToken.call(this, options, responseCallback);
return;
}
}
_makeApiRequest.call(this, options, responseCallback) ;
};
function _makeApiRequest(options, responseCallback){
options = _configure.call(this, options);
var req = request(options,responseCallback.bind(this));
this.emit("request", req); //give access to the request result
}
function _onTokenRefresh(options, responseCallback, err, credentials){
if (err){
responseCallback(err);
return;
}
this.emit("refresh", _.clone(credentials)); //allow calling code use the new token
options.tokens = credentials;
_makeApiRequest.call(this, options, responseCallback) ;
}
function _configure(options) {
options.headers = options.headers || {};
if (options.tokens) {
options.headers["Authorization"] = options.tokens.token_type + " " + options.tokens.access_token;
}
options.headers["User-Agent"] = options.headers["User-Agent"] ? options.headers["User-Agent"] : _USER_AGENT;
return options;
}
function _refreshToken(options, responseCallback) {
var authClient = new AppAuthClient();//thin wrapper around the google oauth2client - simply initializing it with app's client id and secret
authClient.setCredentials(_.clone(options.tokens));
authClient.refreshAccessToken(_onTokenRefresh.bind(this, options, responseCallback));
}
function _wrapResponseCallback(callback){
return function(err, res, body){
if (err) {
this.emit("error", err);
}
this.emit("response", err, res, body);
if (callback) {
callback(err, res, body); // res is: http://nodejs.org/api/http.html#http_http_incomingmessage
}
};
}
return SimpleAuthTransporter;
})();
module.exports = SimpleAuthTransporter;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment