alp-node-auth 5.3.1 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/.eslintrc.json +1 -1
  2. package/CHANGELOG.md +21 -0
  3. package/dist/MongoUsersManager.d.ts.map +1 -1
  4. package/dist/authSocketIO.d.ts.map +1 -1
  5. package/dist/{index-node12-dev.mjs → index-node14.mjs} +33 -21
  6. package/dist/index-node14.mjs.map +1 -0
  7. package/dist/index.d.ts +1 -2
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/services/authentification/AuthenticationService.d.ts.map +1 -1
  10. package/dist/services/user/UserAccountGoogleService.d.ts.map +1 -1
  11. package/dist/services/user/UserAccountSlackService.d.ts.map +1 -1
  12. package/dist/services/user/UserAccountsService.d.ts.map +1 -1
  13. package/dist/utils/cookies.d.ts.map +1 -1
  14. package/dist/utils/createFindConnectedAndUser.d.ts +1 -1
  15. package/dist/utils/createFindConnectedAndUser.d.ts.map +1 -1
  16. package/package.json +18 -24
  17. package/rollup.config.mjs +3 -0
  18. package/src/.eslintrc.json +19 -2
  19. package/src/MongoUsersManager.ts +2 -1
  20. package/src/authApolloContext.ts +4 -4
  21. package/src/authSocketIO.ts +5 -4
  22. package/src/createAuthController.ts +2 -2
  23. package/src/index.ts +6 -3
  24. package/src/services/authentification/AuthenticationService.ts +5 -3
  25. package/src/services/user/UserAccountGoogleService.ts +8 -5
  26. package/src/services/user/UserAccountSlackService.ts +7 -5
  27. package/src/services/user/UserAccountsService.ts +10 -9
  28. package/src/utils/cookies.ts +2 -1
  29. package/src/utils/createFindConnectedAndUser.ts +11 -12
  30. package/strategies/dropbox.js +4 -6
  31. package/strategies/facebook.js +4 -6
  32. package/strategies/foursquare.js +4 -6
  33. package/strategies/github.js +4 -6
  34. package/strategies/google.js +4 -6
  35. package/strategies/slack.js +4 -6
  36. package/dist/index-node12-dev.cjs.js +0 -848
  37. package/dist/index-node12-dev.cjs.js.map +0 -1
  38. package/dist/index-node12-dev.mjs.map +0 -1
  39. package/dist/index-node12.cjs.js +0 -848
  40. package/dist/index-node12.cjs.js.map +0 -1
  41. package/dist/index-node12.mjs +0 -832
  42. package/dist/index-node12.mjs.map +0 -1
  43. package/index.js +0 -6
  44. package/strategies/dropbox.mjs +0 -18
  45. package/strategies/facebook.mjs +0 -18
  46. package/strategies/foursquare.mjs +0 -18
  47. package/strategies/github.mjs +0 -18
  48. package/strategies/google.mjs +0 -18
  49. package/strategies/slack.mjs +0 -18
@@ -1,832 +0,0 @@
1
- import { promisify } from 'util';
2
- import jsonwebtoken from 'jsonwebtoken';
3
- import Logger from 'nightingale-logger';
4
- import 'alp-router';
5
- import { EventEmitter } from 'events';
6
- import { randomBytes } from 'crypto';
7
- import Cookies from 'cookies';
8
-
9
- function createAuthController({
10
- usersManager,
11
- authenticationService,
12
- homeRouterKey = '/',
13
- defaultStrategy,
14
- authHooks = {}
15
- }) {
16
- return {
17
- async login(ctx) {
18
- const strategy = ctx.namedParam('strategy') || defaultStrategy;
19
- if (!strategy) throw new Error('Strategy missing');
20
- const params = authHooks.paramsForLogin && (await authHooks.paramsForLogin(strategy, ctx)) || {};
21
- await authenticationService.redirectAuthUrl(ctx, strategy, {}, params);
22
- },
23
-
24
- async addScope(ctx) {
25
- if (ctx.state.connected) {
26
- await ctx.redirectTo(homeRouterKey);
27
- return;
28
- }
29
-
30
- const strategy = ctx.namedParam('strategy') || defaultStrategy;
31
- if (!strategy) throw new Error('Strategy missing');
32
- const scopeKey = ctx.namedParam('scopeKey');
33
- if (!scopeKey) throw new Error('Scope missing');
34
- await authenticationService.redirectAuthUrl(ctx, strategy, {
35
- scopeKey
36
- });
37
- },
38
-
39
- async loginResponse(ctx) {
40
- if (ctx.state.connected) {
41
- await ctx.redirectTo(homeRouterKey);
42
- return;
43
- }
44
-
45
- const strategy = ctx.namedParam('strategy');
46
- ctx.assert(strategy);
47
- const connectedUser = await authenticationService.accessResponse(ctx, strategy, ctx.state.connected, {
48
- afterLoginSuccess: authHooks.afterLoginSuccess,
49
- afterScopeUpdate: authHooks.afterScopeUpdate
50
- });
51
- const keyPath = usersManager.store.keyPath;
52
- await ctx.setConnected(connectedUser[keyPath], connectedUser);
53
- await ctx.redirectTo(homeRouterKey);
54
- },
55
-
56
- async logout(ctx) {
57
- ctx.logout();
58
- await ctx.redirectTo(homeRouterKey);
59
- }
60
-
61
- };
62
- }
63
-
64
- const createRoutes = controller => ({
65
- login: ['/login/:strategy?', segment => {
66
- segment.add('/response', controller.loginResponse, 'loginResponse');
67
- segment.defaultRoute(controller.login, 'login');
68
- }],
69
- addScope: ['/auth/add-scope/:strategy/:scopeKey', controller.addScope],
70
- logout: ['/logout', controller.logout]
71
- });
72
-
73
- const randomBytesPromisified = promisify(randomBytes);
74
- async function randomHex(size) {
75
- const buffer = await randomBytesPromisified(size);
76
- return buffer.toString('hex');
77
- }
78
-
79
- /* eslint-disable @typescript-eslint/no-unsafe-assignment */
80
- const logger$4 = new Logger('alp:auth:authentication');
81
- class AuthenticationService extends EventEmitter {
82
- constructor(config, strategies, userAccountsService) {
83
- super();
84
- this.config = config;
85
- this.strategies = strategies;
86
- this.userAccountsService = userAccountsService;
87
- }
88
-
89
- generateAuthUrl(strategy, params) {
90
- logger$4.debug('generateAuthUrl', {
91
- strategy,
92
- params
93
- });
94
- const strategyInstance = this.strategies[strategy];
95
-
96
- switch (strategyInstance.type) {
97
- case 'oauth2':
98
- return strategyInstance.oauth2.authorizationCode.authorizeURL(params);
99
-
100
- default:
101
- throw new Error('Invalid strategy');
102
- }
103
- }
104
-
105
- async getTokens(strategy, options) {
106
- logger$4.debug('getTokens', {
107
- strategy,
108
- options
109
- });
110
- const strategyInstance = this.strategies[strategy];
111
-
112
- switch (strategyInstance.type) {
113
- case 'oauth2':
114
- {
115
- const result = await strategyInstance.oauth2.authorizationCode.getToken({
116
- code: options.code,
117
- redirect_uri: options.redirectUri
118
- });
119
- if (!result) return result;
120
- return {
121
- accessToken: result.access_token,
122
- refreshToken: result.refresh_token,
123
- tokenType: result.token_type,
124
- expiresIn: result.expires_in,
125
- expireDate: (() => {
126
- const d = new Date();
127
- d.setTime(d.getTime() + result.expires_in * 1000);
128
- return d;
129
- })(),
130
- idToken: result.id_token
131
- }; // return strategyInstance.accessToken.create(result);
132
- }
133
-
134
- default:
135
- throw new Error('Invalid stategy');
136
- }
137
- }
138
-
139
- async refreshToken(strategy, tokensParam) {
140
- logger$4.debug('refreshToken', {
141
- strategy
142
- });
143
-
144
- if (!tokensParam.refreshToken) {
145
- throw new Error('Missing refresh token');
146
- }
147
-
148
- const strategyInstance = this.strategies[strategy];
149
-
150
- switch (strategyInstance.type) {
151
- case 'oauth2':
152
- {
153
- const token = strategyInstance.oauth2.accessToken.create({
154
- refresh_token: tokensParam.refreshToken
155
- });
156
- const result = await token.refresh();
157
- const tokens = result.token;
158
- return {
159
- accessToken: tokens.access_token,
160
- tokenType: tokens.token_type,
161
- expiresIn: tokens.expires_in,
162
- expireDate: (() => {
163
- const d = new Date();
164
- d.setTime(d.getTime() + tokens.expires_in * 1000);
165
- return d;
166
- })(),
167
- idToken: tokens.id_token
168
- };
169
- }
170
-
171
- default:
172
- throw new Error('Invalid stategy');
173
- }
174
- }
175
-
176
- redirectUri(ctx, strategy) {
177
- const host = `http${this.config.get('allowHttps') ? 's' : ''}://${ctx.request.host}`;
178
- return `${host}${ctx.urlGenerator('loginResponse', {
179
- strategy
180
- })}`;
181
- }
182
-
183
- async redirectAuthUrl(ctx, strategy, {
184
- refreshToken,
185
- scopeKey,
186
- user,
187
- accountId
188
- }, params) {
189
- logger$4.debug('redirectAuthUrl', {
190
- strategy,
191
- scopeKey,
192
- refreshToken
193
- });
194
- const state = await randomHex(8);
195
- const scope = this.userAccountsService.getScope(strategy, scopeKey || 'login', user, accountId);
196
-
197
- if (!scope) {
198
- throw new Error('Invalid empty scope');
199
- }
200
-
201
- ctx.cookies.set(`auth_${strategy}_${state}`, JSON.stringify({
202
- scopeKey,
203
- scope,
204
- isLoginAccess: !scopeKey || scopeKey === 'login'
205
- }), {
206
- maxAge: 600000,
207
- httpOnly: true,
208
- secure: this.config.get('allowHttps')
209
- });
210
- const redirectUri = this.generateAuthUrl(strategy, {
211
- redirect_uri: this.redirectUri(ctx, strategy),
212
- scope,
213
- state,
214
- access_type: refreshToken ? 'offline' : 'online',
215
- ...params
216
- });
217
- return ctx.redirect(redirectUri);
218
- }
219
-
220
- async accessResponse(ctx, strategy, isConnected, hooks) {
221
- if (ctx.query.error) {
222
- const error = new Error(ctx.query.error);
223
- error.status = 403;
224
- error.expose = true;
225
- throw error;
226
- }
227
-
228
- const code = ctx.query.code;
229
- const state = ctx.query.state;
230
- const cookieName = `auth_${strategy}_${state}`;
231
- let cookie = ctx.cookies.get(cookieName);
232
- ctx.cookies.set(cookieName, '', {
233
- expires: new Date(1)
234
- });
235
-
236
- if (!cookie) {
237
- throw new Error('No cookie for this state');
238
- }
239
-
240
- cookie = JSON.parse(cookie);
241
-
242
- if (!cookie || !cookie.scope) {
243
- throw new Error('Unexpected cookie value');
244
- }
245
-
246
- if (!cookie.isLoginAccess) {
247
- if (!isConnected) {
248
- throw new Error('You are not connected');
249
- }
250
- }
251
-
252
- const tokens = await this.getTokens(strategy, {
253
- code,
254
- redirectUri: this.redirectUri(ctx, strategy)
255
- });
256
-
257
- if (cookie.isLoginAccess) {
258
- const user = await this.userAccountsService.findOrCreateFromStrategy(strategy, tokens, cookie.scope, cookie.scopeKey);
259
-
260
- if (hooks.afterLoginSuccess) {
261
- await hooks.afterLoginSuccess(strategy, user);
262
- }
263
-
264
- return user;
265
- }
266
-
267
- const connectedUser = ctx.state.user;
268
- const {
269
- account,
270
- user
271
- } = await this.userAccountsService.update(connectedUser, strategy, tokens, cookie.scope, cookie.scopeKey);
272
-
273
- if (hooks.afterScopeUpdate) {
274
- await hooks.afterScopeUpdate(strategy, cookie.scopeKey, account, user);
275
- }
276
-
277
- return connectedUser;
278
- }
279
-
280
- refreshAccountTokens(user, account) {
281
- if (account.tokenExpireDate && account.tokenExpireDate.getTime() > Date.now()) {
282
- return Promise.resolve(false);
283
- }
284
-
285
- return this.refreshToken(account.provider, {
286
- // accessToken: account.accessToken,
287
- refreshToken: account.refreshToken
288
- }).then(tokens => {
289
- if (!tokens) {
290
- // serviceGoogle.updateFields({ accessToken:null, refreshToken:null, status: .OUTDATED });
291
- return false;
292
- }
293
-
294
- account.accessToken = tokens.accessToken;
295
- account.tokenExpireDate = tokens.expireDate;
296
- return this.userAccountsService.updateAccount(user, account).then(() => true);
297
- });
298
- }
299
-
300
- }
301
-
302
- const logger$3 = new Logger('alp:auth:userAccounts');
303
- const STATUSES = {
304
- VALIDATED: 'validated',
305
- DELETED: 'deleted'
306
- };
307
- class UserAccountsService extends EventEmitter {
308
- constructor(usersManager, strategyToService) {
309
- super();
310
- this.usersManager = usersManager;
311
- this.strategyToService = strategyToService;
312
- }
313
-
314
- getScope(strategy, scopeKey, user, accountId) {
315
- logger$3.debug('getScope', {
316
- strategy,
317
- userId: user === null || user === void 0 ? void 0 : user._id
318
- });
319
- const service = this.strategyToService[strategy];
320
-
321
- if (!service) {
322
- throw new Error('Strategy not supported');
323
- }
324
-
325
- const newScope = service.scopeKeyToScope[scopeKey];
326
-
327
- if (!user || !accountId) {
328
- return newScope;
329
- }
330
-
331
- const account = user.accounts.find(account => account.provider === strategy && account.accountId === accountId);
332
-
333
- if (!account) {
334
- throw new Error('Could not found associated account');
335
- }
336
-
337
- return service.getScope(account.scope, newScope).join(' ');
338
- }
339
-
340
- async update(user, strategy, tokens, scope, subservice) {
341
- const service = this.strategyToService[strategy];
342
- const profile = await service.getProfile(tokens);
343
- const accountId = service.getId(profile);
344
- const account = user.accounts.find(account => account.provider === strategy && account.accountId === accountId);
345
-
346
- if (!account) {
347
- // TODO check if already exists in other user => merge
348
- // TODO else add a new account in this user
349
- throw new Error('Could not found associated account');
350
- }
351
-
352
- account.status = 'valid';
353
- account.accessToken = tokens.accessToken;
354
-
355
- if (tokens.refreshToken) {
356
- account.refreshToken = tokens.refreshToken;
357
- }
358
-
359
- if (tokens.expireDate) {
360
- account.tokenExpireDate = tokens.expireDate;
361
- }
362
-
363
- account.scope = service.getScope(account.scope, scope);
364
- account.subservices = account.subservices || [];
365
-
366
- if (subservice && !account.subservices.includes(subservice)) {
367
- account.subservices.push(subservice);
368
- }
369
-
370
- await this.usersManager.replaceOne(user);
371
- return {
372
- user,
373
- account
374
- };
375
- }
376
-
377
- async findOrCreateFromStrategy(strategy, tokens, scope, subservice) {
378
- const service = this.strategyToService[strategy];
379
- if (!service) throw new Error('Strategy not supported');
380
- const profile = await service.getProfile(tokens);
381
- const accountId = service.getId(profile);
382
- if (!accountId) throw new Error('Invalid profile: no id found');
383
- const emails = service.getEmails(profile);
384
- let user = await this.usersManager.findOneByAccountOrEmails({
385
- provider: service.providerKey,
386
- accountId,
387
- emails
388
- });
389
- logger$3.info(!user ? 'create user' : 'existing user', {
390
- emails,
391
- user
392
- });
393
-
394
- if (!user) {
395
- user = {};
396
- }
397
-
398
- Object.assign(user, {
399
- displayName: service.getDisplayName(profile),
400
- fullName: service.getFullName(profile),
401
- status: STATUSES.VALIDATED
402
- });
403
- if (!user.accounts) user.accounts = [];
404
- let account = user.accounts.find(account => account.provider === strategy && account.accountId === accountId);
405
-
406
- if (!account) {
407
- account = {
408
- provider: strategy,
409
- accountId
410
- }; // @ts-expect-error well...
411
-
412
- user.accounts.push(account);
413
- }
414
-
415
- account.name = service.getAccountName(profile);
416
- account.status = 'valid';
417
- account.profile = profile;
418
- account.accessToken = tokens.accessToken;
419
-
420
- if (tokens.refreshToken) {
421
- account.refreshToken = tokens.refreshToken;
422
- }
423
-
424
- if (tokens.expireDate) {
425
- account.tokenExpireDate = tokens.expireDate;
426
- }
427
-
428
- account.scope = service.getScope(account.scope, scope);
429
- if (!account.subservices) account.subservices = [];
430
-
431
- if (subservice && !account.subservices.includes(subservice)) {
432
- account.subservices.push(subservice);
433
- }
434
-
435
- if (!user.emails) user.emails = [];
436
- const userEmails = user.emails;
437
- emails.forEach(email => {
438
- if (!userEmails.includes(email)) {
439
- userEmails.push(email);
440
- }
441
- });
442
- user.emailDomains = [...user.emails.reduce((domains, email) => domains.add(email.split('@', 2)[1]), new Set())];
443
- const keyPath = this.usersManager.store.keyPath;
444
-
445
- if (user[keyPath]) {
446
- await this.usersManager.replaceOne(user);
447
- } else {
448
- await this.usersManager.insertOne(user);
449
- }
450
-
451
- return user;
452
- }
453
-
454
- async updateAccount(user, account) {
455
- await this.usersManager.updateAccount(user, account);
456
- return user;
457
- }
458
-
459
- }
460
-
461
- const COOKIE_NAME = 'connectedUser';
462
- const getTokenFromRequest = (req, options) => {
463
- const cookies = new Cookies(req, null, { ...options,
464
- secure: true
465
- });
466
- return cookies.get(COOKIE_NAME);
467
- };
468
-
469
- const verifyPromisified = promisify(jsonwebtoken.verify);
470
-
471
- const createDecodeJWT = secretKey => async (token, jwtAudience) => {
472
- const result = await verifyPromisified(token, secretKey, {
473
- algorithms: ['HS512'],
474
- audience: jwtAudience
475
- });
476
- return result === null || result === void 0 ? void 0 : result.connected;
477
- };
478
-
479
- const createFindConnectedAndUser = (secretKey, usersManager, logger) => {
480
- const decodeJwt = createDecodeJWT(secretKey);
481
- return async (jwtAudience, token) => {
482
- if (!token || !jwtAudience) return [null, null];
483
- let connected;
484
-
485
- try {
486
- connected = await decodeJwt(token, jwtAudience);
487
- } catch (err) {
488
- logger.debug('failed to verify authentification', {
489
- err
490
- });
491
- }
492
-
493
- if (connected == null) return [null, null];
494
- const user = await usersManager.findConnected(connected);
495
- return [connected, user];
496
- };
497
- };
498
-
499
- class MongoUsersManager {
500
- constructor(store) {
501
- this.store = store;
502
- }
503
-
504
- findConnected(connected) {
505
- return this.store.findByKey(connected);
506
- }
507
-
508
- insertOne(user) {
509
- return this.store.insertOne(user);
510
- }
511
-
512
- replaceOne(user) {
513
- return this.store.replaceOne(user);
514
- }
515
-
516
- sanitize(user) {
517
- return this.sanitizeBaseUser(user);
518
- }
519
-
520
- findOneByAccountOrEmails({
521
- accountId,
522
- emails,
523
- provider
524
- }) {
525
- let query = {
526
- 'accounts.provider': provider,
527
- 'accounts.accountId': accountId
528
- };
529
-
530
- if (emails && emails.length > 0) {
531
- query = {
532
- $or: [query, {
533
- emails: {
534
- $in: emails
535
- }
536
- }]
537
- };
538
- }
539
-
540
- return this.store.findOne(query);
541
- }
542
-
543
- updateAccount(user, account) {
544
- const accountIndex = user.accounts.indexOf(account);
545
-
546
- if (accountIndex === -1) {
547
- throw new Error('Invalid account');
548
- }
549
-
550
- return this.store.partialUpdateOne(user, {
551
- $set: {
552
- [`accounts.${accountIndex}`]: account
553
- }
554
- });
555
- }
556
-
557
- sanitizeBaseUser(user) {
558
- return {
559
- _id: user._id,
560
- created: user.created,
561
- updated: user.updated,
562
- displayName: user.displayName,
563
- fullName: user.fullName,
564
- status: user.status,
565
- emails: user.emails,
566
- emailDomains: user.emailDomains,
567
- accounts: user.accounts.map(account => ({
568
- provider: account.provider,
569
- accountId: account.accountId,
570
- name: account.name,
571
- status: account.status,
572
- profile: account.profile
573
- }))
574
- };
575
- }
576
-
577
- }
578
-
579
- /* global fetch */
580
- class UserAccountGoogleService {
581
- constructor(scopeKeyToScope) {
582
- this.providerKey = 'google';
583
- this.scopeKeyToScope = { ...scopeKeyToScope,
584
- login: 'openid profile email'
585
- };
586
- }
587
-
588
- getProfile(tokens) {
589
- return fetch(`https://www.googleapis.com/oauth2/v1/userinfo?access_token=${tokens.accessToken}`).then(response => response.json());
590
- }
591
-
592
- getId(profile) {
593
- return profile.id;
594
- }
595
-
596
- getAccountName(profile) {
597
- return profile.email;
598
- }
599
-
600
- getEmails(profile) {
601
- const emails = [];
602
-
603
- if (profile.email) {
604
- emails.push(profile.email);
605
- }
606
-
607
- return emails;
608
- }
609
-
610
- getDisplayName(profile) {
611
- return profile.name;
612
- }
613
-
614
- getFullName(profile) {
615
- return {
616
- givenName: profile.given_name,
617
- familyName: profile.family_name
618
- };
619
- }
620
-
621
- getDefaultScope(newScope) {
622
- return this.getScope(undefined, newScope);
623
- }
624
-
625
- getScope(oldScope, newScope) {
626
- return !oldScope ? newScope.split(' ') : oldScope.concat(newScope.split(' ')).filter((item, i, ar) => ar.indexOf(item) === i);
627
- }
628
-
629
- }
630
-
631
- /* global fetch */
632
- // https://api.slack.com/methods/users.identity
633
- class UserAccountSlackService {
634
- constructor(scopeKeyToScope) {
635
- this.providerKey = 'google';
636
- this.scopeKeyToScope = { ...scopeKeyToScope,
637
- login: 'identity.basic identity.email identity.avatar'
638
- };
639
- }
640
-
641
- getProfile(tokens) {
642
- return fetch(`https://slack.com/api/users.identity?token=${tokens.accessToken}`).then(response => response.json());
643
- }
644
-
645
- getId(profile) {
646
- if (!profile || !profile.team || !profile.team.id || !profile.user || !profile.user.id) {
647
- return null;
648
- }
649
-
650
- return `team:${profile.team.id};user:${profile.user.id}`;
651
- }
652
-
653
- getAccountName(profile) {
654
- return profile.user.email;
655
- }
656
-
657
- getEmails(profile) {
658
- return profile.user.email ? [profile.user.email] : [];
659
- }
660
-
661
- getDisplayName(profile) {
662
- return profile.user.name;
663
- }
664
-
665
- getFullName() {
666
- return null;
667
- }
668
-
669
- getDefaultScope(newScope) {
670
- return this.getScope(undefined, newScope);
671
- }
672
-
673
- getScope(oldScope, newScope) {
674
- return !oldScope ? newScope.split(' ') : oldScope.concat(newScope.split(' ')).filter((item, i, ar) => ar.indexOf(item) === i);
675
- }
676
-
677
- }
678
-
679
- const logger$2 = new Logger('alp:auth');
680
- const authSocketIO = (app, usersManager, io) => {
681
- const findConnectedAndUser = createFindConnectedAndUser(app.config.get('authentication').get('secretKey'), usersManager, logger$2);
682
- const users = new Map();
683
- io.users = users;
684
- io.use(async (socket, next) => {
685
- const handshakeData = socket.request;
686
- const token = getTokenFromRequest(handshakeData);
687
- if (!token) return next();
688
- const [connected, user] = await findConnectedAndUser(handshakeData.headers['user-agent'], token);
689
- if (!connected || !user) return next();
690
- socket.user = user;
691
- users.set(socket.client.id, user);
692
- socket.on('disconnected', () => users.delete(socket.client.id));
693
- await next();
694
- });
695
- };
696
-
697
- const logger$1 = new Logger('alp:auth');
698
-
699
- const getTokenFromReq = req => {
700
- if (req.cookies) return req.cookies[COOKIE_NAME];
701
- return getTokenFromRequest(req);
702
- };
703
- /*
704
- * Not tested yet.
705
- * @internal
706
- */
707
-
708
-
709
- const createAuthApolloContext = (config, usersManager) => {
710
- const findConnectedAndUser = createFindConnectedAndUser(config.get('authentication').get('secretKey'), usersManager, logger$1);
711
- return async ({
712
- req,
713
- connection
714
- }) => {
715
- if (connection !== null && connection !== void 0 && connection.user) {
716
- return {
717
- user: connection.user
718
- };
719
- }
720
-
721
- if (!req) return null;
722
- const token = getTokenFromReq(req);
723
- if (!token) return {
724
- user: undefined
725
- };
726
- const [, user] = await findConnectedAndUser(req.headers['user-agent'], token);
727
- return {
728
- user
729
- };
730
- };
731
- };
732
-
733
- const logger = new Logger('alp:auth');
734
- const signPromisified = promisify(jsonwebtoken.sign);
735
- function init({
736
- homeRouterKey,
737
- usersManager,
738
- strategies,
739
- defaultStrategy,
740
- strategyToService,
741
- authHooks,
742
- jwtAudience
743
- }) {
744
- return app => {
745
- const userAccountsService = new UserAccountsService(usersManager, strategyToService);
746
- const authenticationService = new AuthenticationService(app.config, strategies, userAccountsService);
747
- const controller = createAuthController({
748
- usersManager,
749
- authenticationService,
750
- homeRouterKey,
751
- defaultStrategy,
752
- authHooks
753
- });
754
-
755
- app.context.setConnected = async function (connected, user) {
756
- logger.debug('setConnected', {
757
- connected
758
- });
759
-
760
- if (!connected) {
761
- throw new Error('Illegal value for setConnected');
762
- }
763
-
764
- this.state.connected = connected;
765
- this.state.user = user;
766
- const token = await signPromisified({
767
- connected,
768
- time: Date.now()
769
- }, this.config.get('authentication').get('secretKey'), {
770
- algorithm: 'HS512',
771
- audience: jwtAudience || this.request.headers['user-agent'],
772
- expiresIn: '30 days'
773
- });
774
- this.cookies.set(COOKIE_NAME, token, {
775
- httpOnly: true,
776
- secure: this.config.get('allowHttps')
777
- });
778
- };
779
-
780
- app.context.logout = function () {
781
- delete this.state.connected;
782
- delete this.state.user;
783
- this.cookies.set(COOKIE_NAME, '', {
784
- expires: new Date(1)
785
- });
786
- };
787
-
788
- const getConnectedAndUser = createFindConnectedAndUser(app.config.get('authentication').get('secretKey'), usersManager, logger);
789
- return {
790
- routes: createRoutes(controller),
791
- getConnectedAndUserFromRequest: req => {
792
- const token = getTokenFromRequest(req);
793
- return getConnectedAndUser(jwtAudience || req.headers['user-agent'], token);
794
- },
795
- getConnectedAndUser,
796
- middleware: async (ctx, next) => {
797
- const token = ctx.cookies.get(COOKIE_NAME);
798
- const userAgent = ctx.request.headers['user-agent'];
799
- logger.debug('middleware', {
800
- token
801
- });
802
-
803
- const setState = (connected, user) => {
804
- ctx.state.connected = connected;
805
- ctx.state.user = user;
806
- ctx.sanitizedState.connected = connected;
807
- ctx.sanitizedState.user = user && usersManager.sanitize(user);
808
- };
809
-
810
- const [connected, user] = await getConnectedAndUser(jwtAudience || userAgent, token);
811
- logger.debug('middleware', {
812
- connected
813
- });
814
-
815
- if (connected == null || user == null) {
816
- if (token) ctx.cookies.set(COOKIE_NAME, '', {
817
- expires: new Date(1)
818
- });
819
- setState(null, null);
820
- return next();
821
- }
822
-
823
- setState(connected, user);
824
- return next();
825
- }
826
- };
827
- };
828
- }
829
-
830
- export default init;
831
- export { AuthenticationService, MongoUsersManager, STATUSES, UserAccountGoogleService, UserAccountSlackService, authSocketIO, createAuthApolloContext };
832
- //# sourceMappingURL=index-node12.mjs.map