1
+ var OAuth = require ( "../src/oauth/OAuth1Client" ) ;
2
+ var request = require ( 'request' ) ;
3
+
4
+ describe ( 'OAuth' , function ( ) {
5
+
6
+ it ( "Nonce should have right length" , ( done ) => {
7
+ jequal ( OAuth . nonce ( ) . length , 30 ) ;
8
+ done ( ) ;
9
+ } ) ;
10
+
11
+ it ( "Should properly build parameter string" , ( done ) => {
12
+ var string = OAuth . buildParameterString ( { c :1 , a :2 , b :3 } )
13
+ jequal ( string , "a=2&b=3&c=1" ) ;
14
+ done ( ) ;
15
+ } ) ;
16
+
17
+ it ( "Should properly build empty parameter string" , ( done ) => {
18
+ var string = OAuth . buildParameterString ( )
19
+ jequal ( string , "" ) ;
20
+ done ( ) ;
21
+ } ) ;
22
+
23
+ it ( "Should properly build signature string" , ( done ) => {
24
+ var string = OAuth . buildSignatureString ( "get" , "http://dummy.com" , "" ) ;
25
+ jequal ( string , "GET&http%3A%2F%2Fdummy.com&" ) ;
26
+ done ( ) ;
27
+ } ) ;
28
+
29
+ it ( "Should properly generate request signature" , ( done ) => {
30
+ var request = {
31
+ host : "dummy.com" ,
32
+ path : "path"
33
+ } ;
34
+
35
+ var oauth_params = {
36
+ oauth_timestamp : 123450000 ,
37
+ oauth_nonce : "AAAAAAAAAAAAAAAAA" ,
38
+ oauth_consumer_key : "hello" ,
39
+ oauth_token : "token"
40
+ } ;
41
+
42
+ var consumer_secret = "world" ;
43
+ var auth_token_secret = "secret" ;
44
+ request = OAuth . signRequest ( request , oauth_params , consumer_secret , auth_token_secret ) ;
45
+ jequal ( request . headers [ 'Authorization' ] , 'OAuth oauth_consumer_key="hello", oauth_nonce="AAAAAAAAAAAAAAAAA", oauth_signature="8K95bpQcDi9Nd2GkhumTVcw4%2BXw%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="123450000", oauth_token="token", oauth_version="1.0"' ) ;
46
+ done ( ) ;
47
+ } ) ;
48
+
49
+ it ( "Should properly build request" , ( done ) => {
50
+ var options = {
51
+ host : "dummy.com" ,
52
+ consumer_key : "hello" ,
53
+ consumer_secret : "world" ,
54
+ auth_token : "token" ,
55
+ auth_token_secret : "secret" ,
56
+ // Custom oauth params for tests
57
+ oauth_params : {
58
+ oauth_timestamp : 123450000 ,
59
+ oauth_nonce : "AAAAAAAAAAAAAAAAA"
60
+ }
61
+ } ;
62
+ var path = "path" ;
63
+ var method = "get" ;
64
+
65
+ var oauthClient = new OAuth ( options ) ;
66
+ var req = oauthClient . buildRequest ( method , path , { "query" : "param" } ) ;
67
+
68
+ jequal ( req . host , options . host ) ;
69
+ jequal ( req . path , "/" + path + "?query=param" ) ;
70
+ jequal ( req . method , "GET" ) ;
71
+ jequal ( req . headers [ 'Content-Type' ] , 'application/x-www-form-urlencoded' ) ;
72
+ jequal ( req . headers [ 'Authorization' ] , 'OAuth oauth_consumer_key="hello", oauth_nonce="AAAAAAAAAAAAAAAAA", oauth_signature="wNkyEkDE%2F0JZ2idmqyrgHdvC0rs%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="123450000", oauth_token="token", oauth_version="1.0"' )
73
+ done ( ) ;
74
+ } ) ;
75
+
76
+
77
+ function validateCannotAuthenticateError ( data , done ) {
78
+ jequal ( typeof data , "object" ) ;
79
+ jequal ( typeof data . errors , "object" ) ;
80
+ var errors = data . errors ;
81
+ jequal ( typeof errors [ 0 ] , "object" ) ;
82
+ // Cannot authenticate error
83
+ jequal ( errors [ 0 ] . code , 32 ) ;
84
+ done ( ) ;
85
+ }
86
+
87
+ it ( "Should fail a GET request" , ( done ) => {
88
+ var options = {
89
+ host : "api.twitter.com" ,
90
+ consumer_key : "XXXXXXXXXXXXXXXXXXXXXXXXX" ,
91
+ consumer_secret : "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ,
92
+ } ;
93
+ var path = "/1.1/help/configuration.json" ;
94
+ var params = { "lang" : "en" } ;
95
+ var oauthClient = new OAuth ( options ) ;
96
+ oauthClient . get ( path , params ) . then ( function ( data ) {
97
+ validateCannotAuthenticateError ( data , done ) ;
98
+ } )
99
+ } ) ;
100
+
101
+ it ( "Should fail a POST request" , ( done ) => {
102
+ var options = {
103
+ host : "api.twitter.com" ,
104
+ consumer_key : "XXXXXXXXXXXXXXXXXXXXXXXXX" ,
105
+ consumer_secret : "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ,
106
+ } ;
107
+ var body = {
108
+ lang : "en"
109
+ } ;
110
+ var path = "/1.1/account/settings.json" ;
111
+
112
+ var oauthClient = new OAuth ( options ) ;
113
+ oauthClient . post ( path , null , body ) . then ( function ( data ) {
114
+ validateCannotAuthenticateError ( data , done ) ;
115
+ } )
116
+ } ) ;
117
+
118
+ it ( "Should fail a request" , ( done ) => {
119
+ var options = {
120
+ host : "localhost" ,
121
+ consumer_key : "XXXXXXXXXXXXXXXXXXXXXXXXX" ,
122
+ consumer_secret : "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ,
123
+ } ;
124
+ var body = {
125
+ lang : "en"
126
+ } ;
127
+ var path = "/" ;
128
+
129
+ var oauthClient = new OAuth ( options ) ;
130
+ oauthClient . post ( path , null , body ) . then ( function ( data ) {
131
+ jequal ( false , true ) ;
132
+ done ( ) ;
133
+ } ) . catch ( function ( ) {
134
+ jequal ( true , true ) ;
135
+ done ( ) ;
136
+ } )
137
+ } ) ;
138
+
139
+ [ "facebook" , "github" , "instagram" , "google" , "linkedin" , "meetup" , "twitter" ] . map ( function ( providerName ) {
140
+ it ( "Should validate structure of " + providerName , ( done ) => {
141
+ var provider = require ( "../src/oauth/" + providerName ) ;
142
+ jequal ( typeof provider . validateAuthData , "function" ) ;
143
+ jequal ( typeof provider . validateAppId , "function" ) ;
144
+ jequal ( provider . validateAuthData ( { } , { } ) . constructor , Promise . prototype . constructor ) ;
145
+ jequal ( provider . validateAppId ( "app" , "key" , { } ) . constructor , Promise . prototype . constructor ) ;
146
+ done ( ) ;
147
+ } ) ;
148
+ } ) ;
149
+
150
+ var getMockMyOauthProvider = function ( ) {
151
+ return {
152
+ authData : {
153
+ id : "12345" ,
154
+ access_token : "12345" ,
155
+ expiration_date : new Date ( ) . toJSON ( ) ,
156
+ } ,
157
+ shouldError : false ,
158
+ loggedOut : false ,
159
+ synchronizedUserId : null ,
160
+ synchronizedAuthToken : null ,
161
+ synchronizedExpiration : null ,
162
+
163
+ authenticate : function ( options ) {
164
+ if ( this . shouldError ) {
165
+ options . error ( this , "An error occurred" ) ;
166
+ } else if ( this . shouldCancel ) {
167
+ options . error ( this , null ) ;
168
+ } else {
169
+ options . success ( this , this . authData ) ;
170
+ }
171
+ } ,
172
+ restoreAuthentication : function ( authData ) {
173
+ if ( ! authData ) {
174
+ this . synchronizedUserId = null ;
175
+ this . synchronizedAuthToken = null ;
176
+ this . synchronizedExpiration = null ;
177
+ return true ;
178
+ }
179
+ this . synchronizedUserId = authData . id ;
180
+ this . synchronizedAuthToken = authData . access_token ;
181
+ this . synchronizedExpiration = authData . expiration_date ;
182
+ return true ;
183
+ } ,
184
+ getAuthType : function ( ) {
185
+ return "myoauth" ;
186
+ } ,
187
+ deauthenticate : function ( ) {
188
+ this . loggedOut = true ;
189
+ this . restoreAuthentication ( null ) ;
190
+ }
191
+ } ;
192
+ } ;
193
+
194
+ var ExtendedUser = Parse . User . extend ( {
195
+ extended : function ( ) {
196
+ return true ;
197
+ }
198
+ } ) ;
199
+
200
+ var createOAuthUser = function ( callback ) {
201
+ var jsonBody = {
202
+ authData : {
203
+ myoauth : getMockMyOauthProvider ( ) . authData
204
+ }
205
+ } ;
206
+ var headers = { 'X-Parse-Application-Id' : 'test' ,
207
+ 'X-Parse-REST-API-Key' : 'rest' ,
208
+ 'Content-Type' : 'application/json' }
209
+
210
+ var options = {
211
+ headers : { 'X-Parse-Application-Id' : 'test' ,
212
+ 'X-Parse-REST-API-Key' : 'rest' ,
213
+ 'Content-Type' : 'application/json' } ,
214
+ url : 'http://localhost:8378/1/users' ,
215
+ body : JSON . stringify ( jsonBody )
216
+ } ;
217
+
218
+ return request . post ( options , callback ) ;
219
+ }
220
+
221
+ it ( "should create user with REST API" , ( done ) => {
222
+
223
+ createOAuthUser ( ( error , response , body ) => {
224
+ expect ( error ) . toBe ( null ) ;
225
+ var b = JSON . parse ( body ) ;
226
+ expect ( b . objectId ) . not . toBeNull ( ) ;
227
+ expect ( b . objectId ) . not . toBeUndefined ( ) ;
228
+ done ( ) ;
229
+ } ) ;
230
+
231
+ } ) ;
232
+
233
+ it ( "should only create a single user with REST API" , ( done ) => {
234
+ var objectId ;
235
+ createOAuthUser ( ( error , response , body ) => {
236
+ expect ( error ) . toBe ( null ) ;
237
+ var b = JSON . parse ( body ) ;
238
+ expect ( b . objectId ) . not . toBeNull ( ) ;
239
+ expect ( b . objectId ) . not . toBeUndefined ( ) ;
240
+ objectId = b . objectId ;
241
+
242
+ createOAuthUser ( ( error , response , body ) => {
243
+ expect ( error ) . toBe ( null ) ;
244
+ var b = JSON . parse ( body ) ;
245
+ expect ( b . objectId ) . not . toBeNull ( ) ;
246
+ expect ( b . objectId ) . not . toBeUndefined ( ) ;
247
+ expect ( b . objectId ) . toBe ( objectId ) ;
248
+ done ( ) ;
249
+ } ) ;
250
+ } ) ;
251
+
252
+ } ) ;
253
+
254
+ it ( "unlink and link with custom provider" , ( done ) => {
255
+ var provider = getMockMyOauthProvider ( ) ;
256
+ Parse . User . _registerAuthenticationProvider ( provider ) ;
257
+ Parse . User . _logInWith ( "myoauth" , {
258
+ success : function ( model ) {
259
+ ok ( model instanceof Parse . User , "Model should be a Parse.User" ) ;
260
+ strictEqual ( Parse . User . current ( ) , model ) ;
261
+ ok ( model . extended ( ) , "Should have used the subclass." ) ;
262
+ strictEqual ( provider . authData . id , provider . synchronizedUserId ) ;
263
+ strictEqual ( provider . authData . access_token , provider . synchronizedAuthToken ) ;
264
+ strictEqual ( provider . authData . expiration_date , provider . synchronizedExpiration ) ;
265
+ ok ( model . _isLinked ( "myoauth" ) , "User should be linked to myoauth" ) ;
266
+
267
+ model . _unlinkFrom ( "myoauth" , {
268
+ success : function ( model ) {
269
+ ok ( ! model . _isLinked ( "myoauth" ) ,
270
+ "User should not be linked to myoauth" ) ;
271
+ ok ( ! provider . synchronizedUserId , "User id should be cleared" ) ;
272
+ ok ( ! provider . synchronizedAuthToken , "Auth token should be cleared" ) ;
273
+ ok ( ! provider . synchronizedExpiration ,
274
+ "Expiration should be cleared" ) ;
275
+
276
+ model . _linkWith ( "myoauth" , {
277
+ success : function ( model ) {
278
+ ok ( provider . synchronizedUserId , "User id should have a value" ) ;
279
+ ok ( provider . synchronizedAuthToken ,
280
+ "Auth token should have a value" ) ;
281
+ ok ( provider . synchronizedExpiration ,
282
+ "Expiration should have a value" ) ;
283
+ ok ( model . _isLinked ( "myoauth" ) ,
284
+ "User should be linked to myoauth" ) ;
285
+ done ( ) ;
286
+ } ,
287
+ error : function ( model , error ) {
288
+ ok ( false , "linking again should succeed" ) ;
289
+ done ( ) ;
290
+ }
291
+ } ) ;
292
+ } ,
293
+ error : function ( model , error ) {
294
+ ok ( false , "unlinking should succeed" ) ;
295
+ done ( ) ;
296
+ }
297
+ } ) ;
298
+ } ,
299
+ error : function ( model , error ) {
300
+ ok ( false , "linking should have worked" ) ;
301
+ done ( ) ;
302
+ }
303
+ } ) ;
304
+ } ) ;
305
+
306
+
307
+ } )
0 commit comments