Adds support for 1.0A callback urls, and HTTPS endpoints
Introduces a breaking constructing change, there is now a 'callback url' argument that can be supplied prior to the signatureMethod in the constructor. Pass 'null' to explicitly ensure the callback url is never used, 'undefined' to use 'oob', 'oob' to use 'oob' or an absolute url.
This commit is contained in:
parent
6b7b8f3198
commit
63dc8facb6
124
lib/oauth.js
124
lib/oauth.js
@ -1,14 +1,21 @@
|
|||||||
var sha1= require('./sha1'),
|
var crypto= require('crypto'),
|
||||||
|
sha1= require('./sha1'),
|
||||||
http= require('http'),
|
http= require('http'),
|
||||||
URL= require('url'),
|
URL= require('url'),
|
||||||
querystring= require('querystring');
|
querystring= require('querystring');
|
||||||
|
|
||||||
exports.OAuth= function(requestUrl, accessUrl, consumerKey, consumerSecret, version, signatureMethod, nonceSize) {
|
exports.OAuth= function(requestUrl, accessUrl, consumerKey, consumerSecret, version, authorize_callback, signatureMethod, nonceSize) {
|
||||||
this._requestUrl= requestUrl;
|
this._requestUrl= requestUrl;
|
||||||
this._accessUrl= accessUrl;
|
this._accessUrl= accessUrl;
|
||||||
this._consumerKey= consumerKey;
|
this._consumerKey= consumerKey;
|
||||||
this._consumerSecret= this._encodeData( consumerSecret );
|
this._consumerSecret= this._encodeData( consumerSecret );
|
||||||
this._version= version;
|
this._version= version;
|
||||||
|
if( authorize_callback === undefined ) {
|
||||||
|
this._authorize_callback= "oob";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._authorize_callback= authorize_callback;
|
||||||
|
}
|
||||||
|
|
||||||
if( signatureMethod != "PLAINTEXT" && signatureMethod != "HMAC-SHA1")
|
if( signatureMethod != "PLAINTEXT" && signatureMethod != "HMAC-SHA1")
|
||||||
throw new Error("Un-supported signature method: " + signatureMethod )
|
throw new Error("Un-supported signature method: " + signatureMethod )
|
||||||
@ -81,9 +88,9 @@ exports.OAuth.prototype._normaliseRequestParams= function(arguments) {
|
|||||||
var argument_pairs= this._sortRequestParams( arguments );
|
var argument_pairs= this._sortRequestParams( arguments );
|
||||||
var args= "";
|
var args= "";
|
||||||
for(var i=0;i<argument_pairs.length;i++) {
|
for(var i=0;i<argument_pairs.length;i++) {
|
||||||
args+= argument_pairs[i][0];
|
args+= this._encodeData( argument_pairs[i][0] );
|
||||||
args+= "="
|
args+= "="
|
||||||
args+= argument_pairs[i][1];
|
args+= this._encodeData( argument_pairs[i][1] );
|
||||||
if( i < argument_pairs.length-1 ) args+= "&";
|
if( i < argument_pairs.length-1 ) args+= "&";
|
||||||
}
|
}
|
||||||
return args;
|
return args;
|
||||||
@ -91,7 +98,7 @@ exports.OAuth.prototype._normaliseRequestParams= function(arguments) {
|
|||||||
|
|
||||||
exports.OAuth.prototype._createSignatureBase= function(method, url, parameters) {
|
exports.OAuth.prototype._createSignatureBase= function(method, url, parameters) {
|
||||||
url= this._encodeData( this._normalizeUrl(url) );
|
url= this._encodeData( this._normalizeUrl(url) );
|
||||||
parameters= this._encodeData(parameters);
|
parameters= this._encodeData( parameters );
|
||||||
return method.toUpperCase() + "&" + url + "&" + parameters;
|
return method.toUpperCase() + "&" + url + "&" + parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,8 +126,8 @@ exports.OAuth.prototype.NONCE_CHARS= ['a','b','c','d','e','f','g','h','i','j','k
|
|||||||
'Q','R','S','T','U','V','W','X','Y','Z','0','1','2','3',
|
'Q','R','S','T','U','V','W','X','Y','Z','0','1','2','3',
|
||||||
'4','5','6','7','8','9'];
|
'4','5','6','7','8','9'];
|
||||||
|
|
||||||
exports.OAuth.prototype._createClient= function( port, hostname ) {
|
exports.OAuth.prototype._createClient= function( port, hostname, sshEnabled, credentials ) {
|
||||||
return http.createClient(port, hostname);
|
return http.createClient(port, hostname, sshEnabled, credentials);
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.OAuth.prototype._getNonce= function(nonceSize) {
|
exports.OAuth.prototype._getNonce= function(nonceSize) {
|
||||||
@ -136,7 +143,7 @@ exports.OAuth.prototype._getNonce= function(nonceSize) {
|
|||||||
return result.join('');
|
return result.join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.OAuth.prototype._performSecureRequest= function( oauth_token, oauth_token_secret, method, url, callback ) {
|
exports.OAuth.prototype._performSecureRequest= function( oauth_token, oauth_token_secret, method, url, extra_params, callback ) {
|
||||||
var oauthParameters= {
|
var oauthParameters= {
|
||||||
"oauth_timestamp": this._getTimestamp(),
|
"oauth_timestamp": this._getTimestamp(),
|
||||||
"oauth_nonce": this._getNonce(this._nonceSize),
|
"oauth_nonce": this._getNonce(this._nonceSize),
|
||||||
@ -148,6 +155,11 @@ exports.OAuth.prototype._performSecureRequest= function( oauth_token, oauth_toke
|
|||||||
if( oauth_token ) {
|
if( oauth_token ) {
|
||||||
oauthParameters["oauth_token"]= oauth_token;
|
oauthParameters["oauth_token"]= oauth_token;
|
||||||
}
|
}
|
||||||
|
if( extra_params ) {
|
||||||
|
for( var key in extra_params ) {
|
||||||
|
oauthParameters[key]= extra_params[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var parsedUrl= URL.parse( url, false );
|
var parsedUrl= URL.parse( url, false );
|
||||||
if( parsedUrl.protocol == "http:" && !parsedUrl.port ) parsedUrl.port= 80;
|
if( parsedUrl.protocol == "http:" && !parsedUrl.port ) parsedUrl.port= 80;
|
||||||
@ -166,14 +178,41 @@ exports.OAuth.prototype._performSecureRequest= function( oauth_token, oauth_toke
|
|||||||
|
|
||||||
var query="";
|
var query="";
|
||||||
for( var i= 0 ; i < orderedParameters.length; i++) {
|
for( var i= 0 ; i < orderedParameters.length; i++) {
|
||||||
query+= orderedParameters[i][0]+"="+ this._encodeData(orderedParameters[i][1]) + "&";
|
query+= this._encodeData(orderedParameters[i][0])+"="+ this._encodeData(orderedParameters[i][1]) + "&";
|
||||||
}
|
}
|
||||||
query= query.substring(0, query.length-1);
|
query= query.substring(0, query.length-1);
|
||||||
|
|
||||||
var oauthProvider= this._createClient(parsedUrl.port, parsedUrl.hostname)
|
|
||||||
var headers= {'Host': parsedUrl.host}
|
|
||||||
var request = oauthProvider.request(method, parsedUrl.pathname + "?" + query, headers);
|
|
||||||
|
|
||||||
|
var oauthProvider;
|
||||||
|
if( parsedUrl.protocol == "https:" ) {
|
||||||
|
oauthProvider= this._createClient(parsedUrl.port, parsedUrl.hostname, true, crypto.createCredentials({}));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
oauthProvider= this._createClient(parsedUrl.port, parsedUrl.hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
var headers= {}
|
||||||
|
|
||||||
|
// build request authorization header
|
||||||
|
var authHeader="OAuth ";
|
||||||
|
for( var i= 0 ; i < orderedParameters.length; i++) {
|
||||||
|
authHeader+= this._encodeData(orderedParameters[i][0])+"=\""+ this._encodeData(orderedParameters[i][1])+"\",";
|
||||||
|
}
|
||||||
|
authHeader= authHeader.substring(0, authHeader.length-1);
|
||||||
|
|
||||||
|
headers["Authorization"]= authHeader;
|
||||||
|
headers["Host"] = parsedUrl.host
|
||||||
|
headers["Accept"]= "*/*"
|
||||||
|
headers["Connection"]= "close"
|
||||||
|
headers["User-Agent"]= "Express authentication"
|
||||||
|
headers["Content-length"]= 0
|
||||||
|
headers["Content-Type"]= "application/x-www-form-urlencoded"
|
||||||
|
|
||||||
|
var path;
|
||||||
|
if( parsedUrl.query ) path= parsedUrl.pathname + "?"+ parsedUrl.query ;
|
||||||
|
else path= parsedUrl.pathname;
|
||||||
|
|
||||||
|
var request = oauthProvider.request(method, path , headers);
|
||||||
var data="";
|
var data="";
|
||||||
var self= this;
|
var self= this;
|
||||||
request.addListener('response', function (response) {
|
request.addListener('response', function (response) {
|
||||||
@ -189,12 +228,12 @@ exports.OAuth.prototype._performSecureRequest= function( oauth_token, oauth_toke
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
request.end();
|
request.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
exports.OAuth.prototype.getOauthAccessToken= function(oauth_token, oauth_token_secret, callback) {
|
exports.OAuth.prototype.getOauthAccessToken= function(oauth_token, oauth_token_secret, callback) {
|
||||||
this._performSecureRequest( oauth_token, oauth_token_secret, "GET", this._accessUrl, function(error, data, response) {
|
this._performSecureRequest( oauth_token, oauth_token_secret, "GET", this._accessUrl, null, function(error, data, response) {
|
||||||
if( error ) callback(error);
|
if( error ) callback(error);
|
||||||
else {
|
else {
|
||||||
var results= querystring.parse( data );
|
var results= querystring.parse( data );
|
||||||
@ -208,57 +247,18 @@ exports.OAuth.prototype.getOauthAccessToken= function(oauth_token, oauth_token_s
|
|||||||
}
|
}
|
||||||
|
|
||||||
exports.OAuth.prototype.getProtectedResource= function(url, method, oauth_token, oauth_token_secret, callback) {
|
exports.OAuth.prototype.getProtectedResource= function(url, method, oauth_token, oauth_token_secret, callback) {
|
||||||
this._performSecureRequest( oauth_token, oauth_token_secret, method, url, callback );
|
this._performSecureRequest( oauth_token, oauth_token_secret, method, url, null, callback );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
exports.OAuth.prototype.getOAuthRequestToken= function(callback) {
|
exports.OAuth.prototype.getOAuthRequestToken= function(callback) {
|
||||||
var oauthParameters= {
|
var extraParams= {};
|
||||||
"oauth_timestamp": this._getTimestamp(),
|
// Callbacks are 1.0A related
|
||||||
"oauth_nonce": this._getNonce(this._nonceSize),
|
if( this._authorize_callback ) {
|
||||||
"oauth_version": this._version,
|
extraParams["oauth_callback"]= this._authorize_callback;
|
||||||
"oauth_signature_method": this._signatureMethod,
|
|
||||||
"oauth_consumer_key": this._consumerKey
|
|
||||||
};
|
|
||||||
var method= "POST";
|
|
||||||
var sig= this._getSignature( method, this._requestUrl, this._normaliseRequestParams(oauthParameters));
|
|
||||||
|
|
||||||
var parsedUrl= URL.parse( this._requestUrl, false );
|
|
||||||
if( parsedUrl.protocol == "http:" && !parsedUrl.port ) parsedUrl.port= 80;
|
|
||||||
if( parsedUrl.protocol == "https:" && !parsedUrl.port ) parsedUrl.port= 443;
|
|
||||||
|
|
||||||
var orderedParameters= this._sortRequestParams( oauthParameters );
|
|
||||||
orderedParameters[orderedParameters.length]= ["oauth_signature", sig];
|
|
||||||
var headers= {};
|
|
||||||
|
|
||||||
// build request authorization header
|
|
||||||
var authHeader="OAuth ";
|
|
||||||
for( var i= 0 ; i < orderedParameters.length; i++) {
|
|
||||||
authHeader+= orderedParameters[i][0]+"=\""+ this._encodeData(orderedParameters[i][1])+"\",";
|
|
||||||
}
|
}
|
||||||
authHeader= authHeader.substring(0, authHeader.length-1);
|
this._performSecureRequest( null, null, "POST", this._requestUrl, extraParams, function(error, data, response) {
|
||||||
|
if( error ) callback(error);
|
||||||
headers["Authorization"]= authHeader;
|
else {
|
||||||
headers["Host"] = parsedUrl.host
|
|
||||||
headers["Accept"]= "*/*"
|
|
||||||
headers["Connection"]= "close"
|
|
||||||
headers["User-Agent"]= "Express authentication"
|
|
||||||
headers["Content-length"]= 0
|
|
||||||
headers["Content-Type"]= "application/x-www-form-urlencoded"
|
|
||||||
|
|
||||||
var oauthProvider= this._createClient(parsedUrl.port, parsedUrl.hostname);
|
|
||||||
var request = oauthProvider.request(method, parsedUrl.pathname, headers);
|
|
||||||
var data="";
|
|
||||||
var self= this;
|
|
||||||
request.addListener('response', function (response) {
|
|
||||||
response.setEncoding('utf8');
|
|
||||||
response.addListener('data', function (chunk) {
|
|
||||||
data+=chunk;
|
|
||||||
});
|
|
||||||
response.addListener('end', function () {
|
|
||||||
if( response.statusCode != 200 ) {
|
|
||||||
callback( response.statusCode +" : " + data );
|
|
||||||
} else {
|
|
||||||
var results= querystring.parse(data);
|
var results= querystring.parse(data);
|
||||||
|
|
||||||
var oauth_token= results["oauth_token"];
|
var oauth_token= results["oauth_token"];
|
||||||
@ -268,8 +268,6 @@ exports.OAuth.prototype.getOAuthRequestToken= function(callback) {
|
|||||||
callback(null, oauth_token, oauth_token_secret, results );
|
callback(null, oauth_token, oauth_token_secret, results );
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
|
||||||
request.end();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.OAuth.prototype.signUrl= function(url, oauth_token, oauth_token_secret, method) {
|
exports.OAuth.prototype.signUrl= function(url, oauth_token, oauth_token_secret, method) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user