@@ -6,6 +6,7 @@ import { HTTP } from 'meteor/http';
6
6
import { ServiceConfiguration } from 'meteor/service-configuration' ;
7
7
import _ from 'underscore' ;
8
8
9
+ import { normalizers , fromTemplate , renameInvalidProperties } from './transform_helpers' ;
9
10
import { mapRolesFromSSO , updateRolesFromSSO } from './oauth_helpers' ;
10
11
import { Logger } from '../../logger' ;
11
12
import { Users } from '../../models' ;
@@ -17,107 +18,6 @@ const logger = new Logger('CustomOAuth');
17
18
const Services = { } ;
18
19
const BeforeUpdateOrCreateUserFromExternalService = [ ] ;
19
20
20
- const normalizers = {
21
- // Set 'id' to '_id' for any sources that provide it
22
- _id ( identity ) {
23
- if ( identity . _id && ! identity . id ) {
24
- identity . id = identity . _id ;
25
- }
26
- } ,
27
-
28
- // Fix for Reddit
29
- redit ( identity ) {
30
- if ( identity . result ) {
31
- return identity . result ;
32
- }
33
- } ,
34
-
35
- // Fix WordPress-like identities having 'ID' instead of 'id'
36
- wordpress ( identity ) {
37
- if ( identity . ID && ! identity . id ) {
38
- identity . id = identity . ID ;
39
- }
40
- } ,
41
-
42
- // Fix Auth0-like identities having 'user_id' instead of 'id'
43
- user_id ( identity ) {
44
- if ( identity . user_id && ! identity . id ) {
45
- identity . id = identity . user_id ;
46
- }
47
- } ,
48
-
49
- characterid ( identity ) {
50
- if ( identity . CharacterID && ! identity . id ) {
51
- identity . id = identity . CharacterID ;
52
- }
53
- } ,
54
-
55
- // Fix Dataporten having 'user.userid' instead of 'id'
56
- dataporten ( identity ) {
57
- if ( identity . user && identity . user . userid && ! identity . id ) {
58
- if ( identity . user . userid_sec && identity . user . userid_sec [ 0 ] ) {
59
- identity . id = identity . user . userid_sec [ 0 ] ;
60
- } else {
61
- identity . id = identity . user . userid ;
62
- }
63
- identity . email = identity . user . email ;
64
- }
65
- } ,
66
-
67
- // Fix for Xenforo [BD]API plugin for 'user.user_id; instead of 'id'
68
- xenforo ( identity ) {
69
- if ( identity . user && identity . user . user_id && ! identity . id ) {
70
- identity . id = identity . user . user_id ;
71
- identity . email = identity . user . user_email ;
72
- }
73
- } ,
74
-
75
- // Fix general 'phid' instead of 'id' from phabricator
76
- phabricator ( identity ) {
77
- if ( identity . phid && ! identity . id ) {
78
- identity . id = identity . phid ;
79
- }
80
- } ,
81
-
82
- // Fix Keycloak-like identities having 'sub' instead of 'id'
83
- kaycloak ( identity ) {
84
- if ( identity . sub && ! identity . id ) {
85
- identity . id = identity . sub ;
86
- }
87
- } ,
88
-
89
- // Fix OpenShift identities where id is in 'metadata' object
90
- openshift ( identity ) {
91
- if ( ! identity . id && identity . metadata && identity . metadata . uid ) {
92
- identity . id = identity . metadata . uid ;
93
- identity . name = identity . fullName ;
94
- }
95
- } ,
96
-
97
- // Fix general 'userid' instead of 'id' from provider
98
- userid ( identity ) {
99
- if ( identity . userid && ! identity . id ) {
100
- identity . id = identity . userid ;
101
- }
102
- } ,
103
-
104
- // Fix Nextcloud provider
105
- nextcloud ( identity ) {
106
- if ( ! identity . id && identity . ocs && identity . ocs . data && identity . ocs . data . id ) {
107
- identity . id = identity . ocs . data . id ;
108
- identity . name = identity . ocs . data . displayname ;
109
- identity . email = identity . ocs . data . email ;
110
- }
111
- } ,
112
-
113
- // Fix when authenticating from a meteor app with 'emails' field
114
- meteor ( identity ) {
115
- if ( ! identity . email && ( identity . emails && Array . isArray ( identity . emails ) && identity . emails . length >= 1 ) ) {
116
- identity . email = identity . emails [ 0 ] . address ? identity . emails [ 0 ] . address : undefined ;
117
- }
118
- } ,
119
- } ;
120
-
121
21
export class CustomOAuth {
122
22
constructor ( name , options ) {
123
23
logger . debug ( 'Init CustomOAuth' , name , options ) ;
@@ -174,6 +74,7 @@ export class CustomOAuth {
174
74
this . tokenSentVia = options . tokenSentVia ;
175
75
this . identityTokenSentVia = options . identityTokenSentVia ;
176
76
this . usernameField = ( options . usernameField || '' ) . trim ( ) ;
77
+ this . emailField = ( options . emailField || '' ) . trim ( ) ;
177
78
this . nameField = ( options . nameField || '' ) . trim ( ) ;
178
79
this . avatarField = ( options . avatarField || '' ) . trim ( ) ;
179
80
this . mergeUsers = options . mergeUsers ;
@@ -334,6 +235,10 @@ export class CustomOAuth {
334
235
identity . username = this . getUsername ( identity ) ;
335
236
}
336
237
238
+ if ( this . emailField ) {
239
+ identity . email = this . getEmail ( identity ) ;
240
+ }
241
+
337
242
if ( this . avatarField ) {
338
243
identity . avatarUrl = this . getAvatarUrl ( identity ) ;
339
244
}
@@ -344,50 +249,64 @@ export class CustomOAuth {
344
249
identity . name = this . getName ( identity ) ;
345
250
}
346
251
347
- return identity ;
252
+ return renameInvalidProperties ( identity ) ;
348
253
}
349
254
350
255
retrieveCredential ( credentialToken , credentialSecret ) {
351
256
return OAuth . retrieveCredential ( credentialToken , credentialSecret ) ;
352
257
}
353
258
354
259
getUsername ( data ) {
355
- let username = '' ;
260
+ try {
261
+ const value = fromTemplate ( this . usernameField , data ) ;
262
+
263
+ if ( ! value ) {
264
+ throw new Meteor . Error ( 'field_not_found' , `Username field "${ this . usernameField } " not found in data` , data ) ;
265
+ }
266
+ return value ;
267
+ } catch ( error ) {
268
+ throw new Error ( 'CustomOAuth: Failed to extract username' , error . message ) ;
269
+ }
270
+ }
356
271
357
- username = this . usernameField . split ( '.' ) . reduce ( function ( prev , curr ) {
358
- return prev ? prev [ curr ] : undefined ;
359
- } , data ) ;
272
+ getEmail ( data ) {
273
+ try {
274
+ const value = fromTemplate ( this . emailField , data ) ;
360
275
361
- if ( ! username ) {
362
- throw new Meteor . Error ( 'field_not_found' , `Username field "${ this . usernameField } " not found in data` , data ) ;
276
+ if ( ! value ) {
277
+ throw new Meteor . Error ( 'field_not_found' , `Email field "${ this . emailField } " not found in data` , data ) ;
278
+ }
279
+ return value ;
280
+ } catch ( error ) {
281
+ throw new Error ( 'CustomOAuth: Failed to extract email' , error . message ) ;
363
282
}
364
- return username ;
365
283
}
366
284
367
285
getCustomName ( data ) {
368
- let customName = '' ;
286
+ try {
287
+ const value = fromTemplate ( this . nameField , data ) ;
369
288
370
- customName = this . nameField . split ( '.' ) . reduce ( function ( prev , curr ) {
371
- return prev ? prev [ curr ] : undefined ;
372
- } , data ) ;
289
+ if ( ! value ) {
290
+ return this . getName ( data ) ;
291
+ }
373
292
374
- if ( ! customName ) {
375
- return this . getName ( data ) ;
293
+ return value ;
294
+ } catch ( error ) {
295
+ throw new Error ( 'CustomOAuth: Failed to extract custom name' , error . message ) ;
376
296
}
377
-
378
- return customName ;
379
297
}
380
298
381
299
getAvatarUrl ( data ) {
382
- const avatarUrl = this . avatarField . split ( '.' ) . reduce ( function ( prev , curr ) {
383
- return prev ? prev [ curr ] : undefined ;
384
- } , data ) ;
300
+ try {
301
+ const value = fromTemplate ( this . avatarField , data ) ;
385
302
386
- if ( ! avatarUrl ) {
387
- logger . debug ( `Avatar field "${ this . avatarField } " not found in data` , data ) ;
303
+ if ( ! value ) {
304
+ logger . debug ( `Avatar field "${ this . avatarField } " not found in data` , data ) ;
305
+ }
306
+ return value ;
307
+ } catch ( error ) {
308
+ throw new Error ( 'CustomOAuth: Failed to extract avatar url' , error . message ) ;
388
309
}
389
-
390
- return avatarUrl ;
391
310
}
392
311
393
312
getName ( identity ) {
@@ -438,11 +357,15 @@ export class CustomOAuth {
438
357
}
439
358
440
359
if ( this . usernameField ) {
441
- user . username = this . getUsername ( user . services [ this . name ] ) ;
360
+ user . username = user . services [ this . name ] . username ;
361
+ }
362
+
363
+ if ( this . emailField ) {
364
+ user . email = user . services [ this . name ] . email ;
442
365
}
443
366
444
367
if ( this . nameField ) {
445
- user . name = this . getCustomName ( user . services [ this . name ] ) ;
368
+ user . name = user . services [ this . name ] . name ;
446
369
}
447
370
448
371
if ( this . mergeRoles ) {
0 commit comments