@@ -13,6 +13,9 @@ exports.OAuth= function(requestUrl, accessUrl, consumerKey, consumerSecret, vers
13
13
this . _accessUrl = accessUrl ;
14
14
this . _consumerKey = consumerKey ;
15
15
this . _consumerSecret = this . _encodeData ( consumerSecret ) ;
16
+ if ( signatureMethod == "RSA-SHA1" ) {
17
+ this . _privateKey = consumerSecret ;
18
+ }
16
19
this . _version = version ;
17
20
if ( authorize_callback === undefined ) {
18
21
this . _authorize_callback = "oob" ;
@@ -21,15 +24,16 @@ exports.OAuth= function(requestUrl, accessUrl, consumerKey, consumerSecret, vers
21
24
this . _authorize_callback = authorize_callback ;
22
25
}
23
26
24
- if ( signatureMethod != "PLAINTEXT" && signatureMethod != "HMAC-SHA1" )
27
+ if ( signatureMethod != "PLAINTEXT" && signatureMethod != "HMAC-SHA1" && signatureMethod != "RSA-SHA1" )
25
28
throw new Error ( "Un-supported signature method: " + signatureMethod )
26
29
this . _signatureMethod = signatureMethod ;
27
30
this . _nonceSize = nonceSize || 32 ;
28
31
this . _headers = customHeaders || { "Accept" : "*/*" ,
29
32
"Connection" : "close" ,
30
33
"User-Agent" : "Node authentication" }
31
34
this . _clientOptions = this . _defaultClientOptions = { "requestTokenHttpMethod" : "POST" ,
32
- "accessTokenHttpMethod" : "POST" } ;
35
+ "accessTokenHttpMethod" : "POST" ,
36
+ "followRedirects" : true } ;
33
37
this . _oauthParameterSeperator = "," ;
34
38
} ;
35
39
@@ -40,9 +44,12 @@ exports.OAuthEcho= function(realm, verify_credentials, consumerKey, consumerSecr
40
44
this . _verifyCredentials = verify_credentials ;
41
45
this . _consumerKey = consumerKey ;
42
46
this . _consumerSecret = this . _encodeData ( consumerSecret ) ;
47
+ if ( signatureMethod == "RSA-SHA1" ) {
48
+ this . _privateKey = consumerSecret ;
49
+ }
43
50
this . _version = version ;
44
51
45
- if ( signatureMethod != "PLAINTEXT" && signatureMethod != "HMAC-SHA1" )
52
+ if ( signatureMethod != "PLAINTEXT" && signatureMethod != "HMAC-SHA1" && signatureMethod != "RSA-SHA1" )
46
53
throw new Error ( "Un-supported signature method: " + signatureMethod ) ;
47
54
this . _signatureMethod = signatureMethod ;
48
55
this . _nonceSize = nonceSize || 32 ;
@@ -86,15 +93,15 @@ exports.OAuth.prototype._getSignature= function(method, url, parameters, tokenSe
86
93
exports . OAuth . prototype . _normalizeUrl = function ( url ) {
87
94
var parsedUrl = URL . parse ( url , true )
88
95
var port = "" ;
89
- if ( parsedUrl . port ) {
96
+ if ( parsedUrl . port ) {
90
97
if ( ( parsedUrl . protocol == "http:" && parsedUrl . port != "80" ) ||
91
98
( parsedUrl . protocol == "https:" && parsedUrl . port != "443" ) ) {
92
99
port = ":" + parsedUrl . port ;
93
100
}
94
101
}
95
102
96
103
if ( ! parsedUrl . pathname || parsedUrl . pathname == "" ) parsedUrl . pathname = "/" ;
97
-
104
+
98
105
return parsedUrl . protocol + "//" + parsedUrl . hostname + port + parsedUrl . pathname ;
99
106
}
100
107
@@ -124,7 +131,7 @@ exports.OAuth.prototype._buildAuthorizationHeaders= function(orderedParameters)
124
131
}
125
132
}
126
133
127
- authHeader = authHeader . substring ( 0 , authHeader . length - this . _oauthParameterSeperator . length ) ;
134
+ authHeader = authHeader . substring ( 0 , authHeader . length - this . _oauthParameterSeperator . length ) ;
128
135
return authHeader ;
129
136
}
130
137
@@ -143,66 +150,70 @@ exports.OAuth.prototype._makeArrayOfArgumentsHash= function(argumentsHash) {
143
150
argument_pairs [ argument_pairs . length ] = [ key , value ] ;
144
151
}
145
152
}
146
- return argument_pairs ;
147
- }
153
+ return argument_pairs ;
154
+ }
148
155
149
156
// Sorts the encoded key value pairs by encoded name, then encoded value
150
157
exports . OAuth . prototype . _sortRequestParams = function ( argument_pairs ) {
151
158
// Sort by name, then value.
152
159
argument_pairs . sort ( function ( a , b ) {
153
160
if ( a [ 0 ] == b [ 0 ] ) {
154
- return a [ 1 ] < b [ 1 ] ? - 1 : 1 ;
161
+ return a [ 1 ] < b [ 1 ] ? - 1 : 1 ;
155
162
}
156
- else return a [ 0 ] < b [ 0 ] ? - 1 : 1 ;
163
+ else return a [ 0 ] < b [ 0 ] ? - 1 : 1 ;
157
164
} ) ;
158
165
159
166
return argument_pairs ;
160
167
}
161
168
162
- exports . OAuth . prototype . _normaliseRequestParams = function ( arguments ) {
163
- var argument_pairs = this . _makeArrayOfArgumentsHash ( arguments ) ;
169
+ exports . OAuth . prototype . _normaliseRequestParams = function ( args ) {
170
+ var argument_pairs = this . _makeArrayOfArgumentsHash ( args ) ;
164
171
// First encode them #3.4.1.3.2 .1
165
172
for ( var i = 0 ; i < argument_pairs . length ; i ++ ) {
166
173
argument_pairs [ i ] [ 0 ] = this . _encodeData ( argument_pairs [ i ] [ 0 ] ) ;
167
174
argument_pairs [ i ] [ 1 ] = this . _encodeData ( argument_pairs [ i ] [ 1 ] ) ;
168
175
}
169
-
176
+
170
177
// Then sort them #3.4.1.3.2 .2
171
178
argument_pairs = this . _sortRequestParams ( argument_pairs ) ;
172
-
179
+
173
180
// Then concatenate together #3.4.1.3.2 .3 & .4
174
181
var args = "" ;
175
182
for ( var i = 0 ; i < argument_pairs . length ; i ++ ) {
176
183
args += argument_pairs [ i ] [ 0 ] ;
177
184
args += "="
178
185
args += argument_pairs [ i ] [ 1 ] ;
179
186
if ( i < argument_pairs . length - 1 ) args += "&" ;
180
- }
187
+ }
181
188
return args ;
182
189
}
183
190
184
191
exports . OAuth . prototype . _createSignatureBase = function ( method , url , parameters ) {
185
- url = this . _encodeData ( this . _normalizeUrl ( url ) ) ;
192
+ url = this . _encodeData ( this . _normalizeUrl ( url ) ) ;
186
193
parameters = this . _encodeData ( parameters ) ;
187
194
return method . toUpperCase ( ) + "&" + url + "&" + parameters ;
188
195
}
189
196
190
197
exports . OAuth . prototype . _createSignature = function ( signatureBase , tokenSecret ) {
191
198
if ( tokenSecret === undefined ) var tokenSecret = "" ;
192
- else tokenSecret = this . _encodeData ( tokenSecret ) ;
199
+ else tokenSecret = this . _encodeData ( tokenSecret ) ;
193
200
// consumerSecret is already encoded
194
201
var key = this . _consumerSecret + "&" + tokenSecret ;
195
202
196
203
var hash = ""
197
204
if ( this . _signatureMethod == "PLAINTEXT" ) {
198
205
hash = key ;
199
206
}
207
+ else if ( this . _signatureMethod == "RSA-SHA1" ) {
208
+ key = this . _privateKey || "" ;
209
+ hash = crypto . createSign ( "RSA-SHA1" ) . update ( signatureBase ) . sign ( key , 'base64' ) ;
210
+ }
200
211
else {
201
212
if ( crypto . Hmac ) {
202
213
hash = crypto . createHmac ( "sha1" , key ) . update ( signatureBase ) . digest ( "base64" ) ;
203
214
}
204
215
else {
205
- hash = sha1 . HMACSHA1 ( key , signatureBase ) ;
216
+ hash = sha1 . HMACSHA1 ( key , signatureBase ) ;
206
217
}
207
218
}
208
219
return hash ;
@@ -218,7 +229,7 @@ exports.OAuth.prototype._getNonce= function(nonceSize) {
218
229
var chars = this . NONCE_CHARS ;
219
230
var char_pos ;
220
231
var nonce_chars_length = chars . length ;
221
-
232
+
222
233
for ( var i = 0 ; i < nonceSize ; i ++ ) {
223
234
char_pos = Math . floor ( Math . random ( ) * nonce_chars_length ) ;
224
235
result [ i ] = chars [ char_pos ] ;
@@ -240,7 +251,7 @@ exports.OAuth.prototype._createClient= function( port, hostname, method, path, h
240
251
} else {
241
252
httpModel = http ;
242
253
}
243
- return httpModel . request ( options ) ;
254
+ return httpModel . request ( options ) ;
244
255
}
245
256
246
257
exports . OAuth . prototype . _prepareParameters = function ( oauth_token , oauth_token_secret , method , url , extra_params ) {
@@ -361,22 +372,23 @@ exports.OAuth.prototype._performSecureRequest= function( oauth_token, oauth_toke
361
372
request = this . _createClient ( parsedUrl . port , parsedUrl . hostname , method , path , headers ) ;
362
373
}
363
374
375
+ var clientOptions = this . _clientOptions ;
364
376
if ( callback ) {
365
- var data = "" ;
377
+ var data = "" ;
366
378
var self = this ;
367
379
368
380
// Some hosts *cough* google appear to close the connection early / send no content-length header
369
381
// allow this behaviour.
370
382
var allowEarlyClose = OAuthUtils . isAnEarlyCloseHost ( parsedUrl . hostname ) ;
371
383
var callbackCalled = false ;
372
- function passBackControl ( response ) {
384
+ var passBackControl = function ( response ) {
373
385
if ( ! callbackCalled ) {
374
386
callbackCalled = true ;
375
387
if ( response . statusCode >= 200 && response . statusCode <= 299 ) {
376
388
callback ( null , data , response ) ;
377
389
} else {
378
390
// Follow 301 or 302 redirects with Location HTTP header
379
- if ( ( response . statusCode == 301 || response . statusCode == 302 ) && response . headers && response . headers . location ) {
391
+ if ( ( response . statusCode == 301 || response . statusCode == 302 ) && clientOptions . followRedirects && response . headers && response . headers . location ) {
380
392
self . _performSecureRequest ( oauth_token , oauth_token_secret , method , response . headers . location , extra_params , post_body , post_content_type , callback ) ;
381
393
}
382
394
else {
@@ -400,12 +412,14 @@ exports.OAuth.prototype._performSecureRequest= function( oauth_token, oauth_toke
400
412
}
401
413
} ) ;
402
414
} ) ;
403
-
415
+
404
416
request . on ( "error" , function ( err ) {
405
- callbackCalled = true ;
406
- callback ( err )
417
+ if ( ! callbackCalled ) {
418
+ callbackCalled = true ;
419
+ callback ( err )
420
+ }
407
421
} ) ;
408
-
422
+
409
423
if ( ( method == "POST" || method == "PUT" ) && post_body != null && post_body != "" ) {
410
424
request . write ( post_body ) ;
411
425
}
@@ -417,7 +431,7 @@ exports.OAuth.prototype._performSecureRequest= function( oauth_token, oauth_toke
417
431
}
418
432
return request ;
419
433
}
420
-
434
+
421
435
return ;
422
436
}
423
437
@@ -444,7 +458,7 @@ exports.OAuth.prototype.getOAuthAccessToken= function(oauth_token, oauth_token_s
444
458
} else {
445
459
extraParams . oauth_verifier = oauth_verifier ;
446
460
}
447
-
461
+
448
462
this . _performSecureRequest ( oauth_token , oauth_token_secret , this . _clientOptions . accessTokenHttpMethod , this . _accessUrl , extraParams , null , null , function ( error , data , response ) {
449
463
if ( error ) callback ( error ) ;
450
464
else {
@@ -484,7 +498,7 @@ exports.OAuth.prototype._putOrPost= function(method, url, oauth_token, oauth_tok
484
498
}
485
499
return this . _performSecureRequest ( oauth_token , oauth_token_secret , method , url , extra_params , post_body , post_content_type , callback ) ;
486
500
}
487
-
501
+
488
502
489
503
exports . OAuth . prototype . put = function ( url , oauth_token , oauth_token_secret , post_body , post_content_type , callback ) {
490
504
return this . _putOrPost ( "PUT" , url , oauth_token , oauth_token_secret , post_body , post_content_type , callback ) ;
@@ -500,7 +514,7 @@ exports.OAuth.prototype.post= function(url, oauth_token, oauth_token_secret, pos
500
514
*
501
515
* The callback should expect a function of the following form:
502
516
*
503
- * function(err, token, token_secret, parsedQueryString) {}
517
+ * function(err, token, token_secret, parsedQueryString) {}
504
518
*
505
519
* This method has optional parameters so can be called in the following 2 ways:
506
520
*
@@ -519,7 +533,7 @@ exports.OAuth.prototype.getOAuthRequestToken= function( extraParams, callback )
519
533
callback = extraParams ;
520
534
extraParams = { } ;
521
535
}
522
- // Callbacks are 1.0A related
536
+ // Callbacks are 1.0A related
523
537
if ( this . _authorize_callback ) {
524
538
extraParams [ "oauth_callback" ] = this . _authorize_callback ;
525
539
}
@@ -546,12 +560,12 @@ exports.OAuth.prototype.signUrl= function(url, oauth_token, oauth_token_secret,
546
560
var orderedParameters = this . _prepareParameters ( oauth_token , oauth_token_secret , method , url , { } ) ;
547
561
var parsedUrl = URL . parse ( url , false ) ;
548
562
549
- var query = "" ;
563
+ var query = "" ;
550
564
for ( var i = 0 ; i < orderedParameters . length ; i ++ ) {
551
565
query += orderedParameters [ i ] [ 0 ] + "=" + this . _encodeData ( orderedParameters [ i ] [ 1 ] ) + "&" ;
552
566
}
553
567
query = query . substring ( 0 , query . length - 1 ) ;
554
-
568
+
555
569
return parsedUrl . protocol + "//" + parsedUrl . host + parsedUrl . pathname + "?" + query ;
556
570
} ;
557
571
0 commit comments