Skip to content

Instantly share code, notes, and snippets.

@warmwaffles
Created December 1, 2013 04:55
Show Gist options
  • Save warmwaffles/7728653 to your computer and use it in GitHub Desktop.
Save warmwaffles/7728653 to your computer and use it in GitHub Desktop.
Based loosely on `simple-oauth2`
'use strict';
require('date-utils');
var underscore = require('underscore');
/**
* Constructs a brand new AccessToken
*
* @param client {OAuth2.Client} The OAuth2 client that will be used for
* requests.
* @param token {String} The access token. A null can be provided, but a
* refresh token must be passed in with the options.
* @param options {Object} Allowable options include the following:
* @option options refreshToken {String} This must be provided if the token
* that was passed is null.
* @option options expiresAt {Date} If this is not provided it will be assumed
* that the token will expire in 120 seconds from now.
* @constructor
*/
function AccessToken(client, token, options) {
options = options || {};
this.client = client;
this.token = token;
this.refreshToken = options.refreshToken || null;
if (this.token === null && this.refreshToken === null) {
throw new Error('a token or refreshToken must be provided');
}
this.expiresAt = options.expiresAt || new Date().addSeconds(120);
this.authorizePath = options.authorizePath || '/oauth/authorize';
this.tokenPath = options.tokenPath || '/oauth/token';
this.params = options;
}
AccessToken.prototype.get = function (path, params, callback) {
return this.execute('GET', path, params, callback);
};
AccessToken.prototype.post = function (path, params, callback) {
return this.execute('POST', path, params, callback);
};
AccessToken.prototype.put = function (path, params, callback) {
return this.execute('PUT', path, params, callback);
};
AccessToken.prototype.del = function (path, params, callback) {
return this.execute('DELETE', path, params, callback);
};
AccessToken.prototype.head = function (path, params, callback) {
return this.execute('HEAD', path, params, callback);
};
AccessToken.prototype.execute = function (method, path, params, callback) {
var headers = {
'Authorization': 'Bearer ' + this.token
};
return this.client.execute(method, path, params, headers, callback);
};
/**
* Refreshes the current access token.
*
* @param callback {function} Is called when the request is complete
*/
AccessToken.prototype.refresh = function (callback) {
if (this.refreshToken === undefined || this.refreshToken === null) {
throw new Error('refreshToken is not set');
}
// Clear the old token
this.token = null;
var params = {
grant_type: 'refresh_token',
refresh_token: this.refreshToken,
client_id: this.client.id,
client_secret: this.client.secret
},
self = this,
now = new Date();
this.client.post(this.tokenPath, params, function (error, results) {
if (results) {
self.token = results.access_token;
self.expiresAt = now.addSeconds(results.expires_in);
}
callback(error, results);
});
};
/**
* Check to see if the access token is expired
* @returns {boolean}
*/
AccessToken.prototype.hasExpired = function () {
return Date.compare(this.expiresAt, new Date()) === -1;
};
module.exports = AccessToken;
'use strict';
var request = require('request'),
crypto = require('crypto'),
util = require("util"),
underscore = require('underscore'),
HTTPError = require('./http_error');
/**
*
* @param id {String} the client id
* @param secret {String} the client secret
* @param site {String} the OAuth2 provider site host
* @param options {Object}
* @constructor
*/
function Client(id, secret, site, options) {
options = options || {};
this.id = id;
this.secret = secret;
this.site = site;
this.clientSecretParameterName = options.clientSecretParameterName || 'client_secret';
this.params = options;
}
/**
* Performs a GET request
*
* @param path {String}
* @param params {Object}
* @param headers {Object}
* @param callback {function}
* @returns what the callback returns
*/
Client.prototype.get = function (path, params, headers, callback) {
return this.execute('GET', path, params, headers, callback);
};
/**
* Performs a POST request
*
* @param path {String}
* @param params {Object}
* @param headers {Object}
* @param callback {function}
* @returns what the callback returns
*/
Client.prototype.post = function (path, params, headers, callback) {
return this.execute('POST', path, params, headers, callback);
};
/**
* Performs a PUT request
*
* @param path {String}
* @param params {Object}
* @param headers {Object}
* @param callback {function}
* @returns what the callback returns
*/
Client.prototype.put = function (path, params, headers, callback) {
return this.execute('PUT', path, params, headers, callback);
};
/**
* Performs a DELETE request
*
* @param path {String}
* @param params {Object}
* @param headers {Object}
* @param callback {function}
* @returns what the callback returns
*/
Client.prototype.del = function (path, params, headers, callback) {
return this.execute('DELETE', path, params, headers, callback);
};
/**
* Performs a PATCH request
*
* @param path {String}
* @param params {Object}
* @param headers {Object}
* @param callback {function}
* @returns what the callback returns
*/
Client.prototype.patch = function (path, params, headers, callback) {
return this.execute('PATCH', path, params, headers, callback);
};
/**
* Performs a HEAD request
*
* @param path {String}
* @param params {Object}
* @param headers {Object}
* @param callback {function}
* @returns what the callback returns
*/
Client.prototype.head = function (path, params, headers, callback) {
return this.execute('HEAD', path, params, headers, callback);
};
/**
*
* @param method {String} the http verb
* @param path {String} the relative path of the resource
* @param params {Object}
* @param headers {Object}
* @param callback {function}
*/
Client.prototype.execute = function (method, path, params, headers, callback) {
if (!this.id || !this.secret || !this.site) {
throw new Error('Client is no properly configured');
}
if (!callback || typeof callback !== 'function') {
throw new Error('Callback not provided on API call');
}
var options = {
uri: this.site + path,
method: method,
headers: headers || {}
};
if (method === 'GET') {
options.qs = params;
} else {
options.form = params;
}
request(options, function (error, response, body) {
if (error) {
return callback(error, body);
}
try {
body = JSON.parse(body);
} catch (e) {
console.error(e);
}
if (response.statusCode >= 400) {
return callback(new HTTPError(response.statusCode), null);
}
return callback(error, body);
});
};
module.exports = Client;
'use strict';
var statusCodes = {
400: "Bad Request",
401: "Unauthorized",
402: "Payment Required",
403: "Forbidden",
404: "Not Found",
405: "Method Not Allowed",
406: "Not Acceptable",
407: "Proxy Authentication Required",
408: "Request Timeout",
409: "Conflict",
410: "Gone",
411: "Length Required",
412: "Precondition Failed",
413: "Request Entity Too Large",
414: "Request-URI Too Long",
415: "Unsupported Media Type",
416: "Requested Range Not Satisfiable",
417: "Expectation Failed",
420: "Enhance Your Calm",
422: "Unprocessable Entity",
423: "Locked",
424: "Failed Dependency",
425: "Unordered Collection",
426: "Upgrade Required",
428: "Precondition Required",
429: "Too Many Requests",
431: "Request Header Fields Too Large",
444: "No Response",
449: "Retry With",
499: "Client Closed Request",
500: "Internal Server Error",
501: "Not Implemented",
502: "Bad Gateway",
503: "Service Unavailable",
504: "Gateway Timeout",
505: "HTTP Version Not Supported",
506: "Variant Also Negotiates",
507: "Insufficient Storage",
508: "Loop Detected",
509: "Bandwidth Limit Exceeded",
510: "Not Extended",
511: "Network Authentication Required"
};
function HTTPError(status) {
this.message = {
status: status,
message: statusCodes[status]
};
this.stack = (new Error()).stack;
}
HTTPError.prototype = Object.create(Error.prototype);
HTTPError.prototype.name = 'HTTPError';
module.exports = HTTPError;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment