alp-node-auth 10.0.0 → 11.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.
- package/CHANGELOG.md +27 -0
- package/README.md +13 -13
- package/dist/definitions/MongoUsersManager.d.ts +2 -2
- package/dist/definitions/MongoUsersManager.d.ts.map +1 -1
- package/dist/definitions/authApolloContext.d.ts +4 -4
- package/dist/definitions/authApolloContext.d.ts.map +1 -1
- package/dist/definitions/authSocketIO.d.ts +4 -4
- package/dist/definitions/authSocketIO.d.ts.map +1 -1
- package/dist/definitions/createAuthController.d.ts +6 -9
- package/dist/definitions/createAuthController.d.ts.map +1 -1
- package/dist/definitions/createRoutes.d.ts +3 -3
- package/dist/definitions/createRoutes.d.ts.map +1 -1
- package/dist/definitions/index.d.ts +24 -25
- package/dist/definitions/index.d.ts.map +1 -1
- package/dist/definitions/services/authentification/AuthenticationService.d.ts +6 -8
- package/dist/definitions/services/authentification/AuthenticationService.d.ts.map +1 -1
- package/dist/definitions/services/authentification/types.d.ts +3 -3
- package/dist/definitions/services/user/UserAccountGoogleService.d.ts +4 -4
- package/dist/definitions/services/user/UserAccountGoogleService.d.ts.map +1 -1
- package/dist/definitions/services/user/UserAccountSlackService.d.ts +4 -4
- package/dist/definitions/services/user/UserAccountSlackService.d.ts.map +1 -1
- package/dist/definitions/services/user/UserAccountsService.d.ts +6 -7
- package/dist/definitions/services/user/UserAccountsService.d.ts.map +1 -1
- package/dist/definitions/services/user/types.d.ts +1 -1
- package/dist/definitions/types.d.ts +1 -1
- package/dist/definitions/utils/cookies.d.ts +3 -4
- package/dist/definitions/utils/cookies.d.ts.map +1 -1
- package/dist/definitions/utils/createFindLoggedInUser.d.ts +4 -4
- package/dist/definitions/utils/createFindLoggedInUser.d.ts.map +1 -1
- package/dist/{index-node18.mjs → index-node20.mjs} +101 -107
- package/dist/index-node20.mjs.map +1 -0
- package/package.json +24 -23
- package/src/MongoUsersManager.ts +5 -6
- package/src/authApolloContext.ts +10 -10
- package/src/authSocketIO.ts +10 -10
- package/src/createAuthController.ts +19 -16
- package/src/createRoutes.ts +8 -8
- package/src/index.ts +58 -63
- package/src/services/authentification/AuthenticationService.ts +37 -37
- package/src/services/authentification/types.ts +6 -6
- package/src/services/user/UserAccountGoogleService.ts +9 -9
- package/src/services/user/UserAccountSlackService.ts +9 -9
- package/src/services/user/UserAccountsService.ts +23 -25
- package/src/services/user/types.ts +1 -1
- package/src/types.ts +1 -1
- package/src/utils/cookies.ts +8 -8
- package/src/utils/createFindLoggedInUser.ts +9 -9
- package/src/utils/generators.ts +4 -4
- package/strategies/dropbox.js +7 -7
- package/strategies/facebook.js +7 -7
- package/strategies/foursquare.js +7 -7
- package/strategies/github.js +7 -7
- package/strategies/google.js +7 -7
- package/strategies/slack.js +7 -7
- package/strategies/strategies.d.ts +7 -7
- package/dist/index-node18.mjs.map +0 -1
- package/src/.eslintrc.json +0 -38
- package/strategies/.eslintrc.json +0 -3
|
@@ -8,14 +8,14 @@ import Cookies from 'cookies';
|
|
|
8
8
|
function createAuthController({
|
|
9
9
|
usersManager,
|
|
10
10
|
authenticationService,
|
|
11
|
-
homeRouterKey =
|
|
11
|
+
homeRouterKey = "/",
|
|
12
12
|
defaultStrategy,
|
|
13
13
|
authHooks = {}
|
|
14
14
|
}) {
|
|
15
15
|
return {
|
|
16
16
|
async login(ctx) {
|
|
17
|
-
const strategy = ctx.
|
|
18
|
-
if (!strategy) throw new Error(
|
|
17
|
+
const strategy = ctx.namedRouteParam("strategy") || defaultStrategy;
|
|
18
|
+
if (!strategy) throw new Error("Strategy missing");
|
|
19
19
|
const params = authHooks.paramsForLogin && (await authHooks.paramsForLogin(strategy, ctx)) || {};
|
|
20
20
|
await authenticationService.redirectAuthUrl(ctx, strategy, {}, params);
|
|
21
21
|
},
|
|
@@ -28,16 +28,16 @@ function createAuthController({
|
|
|
28
28
|
ctx.redirectTo(homeRouterKey);
|
|
29
29
|
return;
|
|
30
30
|
}
|
|
31
|
-
const strategy = ctx.
|
|
32
|
-
if (!strategy) throw new Error(
|
|
33
|
-
const scopeKey = ctx.
|
|
34
|
-
if (!scopeKey) throw new Error(
|
|
31
|
+
const strategy = ctx.namedRouteParam("strategy") || defaultStrategy;
|
|
32
|
+
if (!strategy) throw new Error("Strategy missing");
|
|
33
|
+
const scopeKey = ctx.namedRouteParam("scopeKey");
|
|
34
|
+
if (!scopeKey) throw new Error("Scope missing");
|
|
35
35
|
await authenticationService.redirectAuthUrl(ctx, strategy, {
|
|
36
36
|
scopeKey
|
|
37
37
|
});
|
|
38
38
|
},
|
|
39
39
|
async response(ctx) {
|
|
40
|
-
const strategy = ctx.
|
|
40
|
+
const strategy = ctx.namedRouteParam("strategy");
|
|
41
41
|
ctx.assert(strategy);
|
|
42
42
|
const loggedInUser = await authenticationService.accessResponse(ctx, strategy, !!ctx.state.loggedInUser, {
|
|
43
43
|
afterLoginSuccess: authHooks.afterLoginSuccess,
|
|
@@ -47,6 +47,7 @@ function createAuthController({
|
|
|
47
47
|
await ctx.setLoggedIn(loggedInUser[keyPath], loggedInUser);
|
|
48
48
|
ctx.redirectTo(homeRouterKey);
|
|
49
49
|
},
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- keep async in case i later need await in this method
|
|
50
51
|
async logout(ctx) {
|
|
51
52
|
ctx.logout();
|
|
52
53
|
ctx.redirectTo(homeRouterKey);
|
|
@@ -55,25 +56,25 @@ function createAuthController({
|
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
const createRoutes = controller => ({
|
|
58
|
-
login: [
|
|
59
|
-
segment.add(
|
|
60
|
-
segment.defaultRoute(controller.login,
|
|
59
|
+
login: ["/login/:strategy?", segment => {
|
|
60
|
+
segment.add("/response", controller.response, "authResponse");
|
|
61
|
+
segment.defaultRoute(controller.login, "login");
|
|
61
62
|
}],
|
|
62
|
-
addScope: [
|
|
63
|
-
logout: [
|
|
63
|
+
addScope: ["/add-scope/:strategy/:scopeKey", controller.addScope],
|
|
64
|
+
logout: ["/logout", controller.logout]
|
|
64
65
|
});
|
|
65
66
|
|
|
66
67
|
const randomBytesPromisified = promisify(randomBytes);
|
|
67
68
|
async function randomHex(size) {
|
|
68
69
|
const buffer = await randomBytesPromisified(size);
|
|
69
|
-
return buffer.toString(
|
|
70
|
+
return buffer.toString("hex");
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
73
74
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
|
74
75
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
75
|
-
/* eslint-disable camelcase
|
|
76
|
-
const logger$4 = new Logger(
|
|
76
|
+
/* eslint-disable camelcase */
|
|
77
|
+
const logger$4 = new Logger("alp:auth:authentication");
|
|
77
78
|
class AuthenticationService extends EventEmitter {
|
|
78
79
|
constructor(config, strategies, userAccountsService) {
|
|
79
80
|
super();
|
|
@@ -82,26 +83,26 @@ class AuthenticationService extends EventEmitter {
|
|
|
82
83
|
this.userAccountsService = userAccountsService;
|
|
83
84
|
}
|
|
84
85
|
generateAuthUrl(strategy, params) {
|
|
85
|
-
logger$4.debug(
|
|
86
|
+
logger$4.debug("generateAuthUrl", {
|
|
86
87
|
strategy,
|
|
87
88
|
params
|
|
88
89
|
});
|
|
89
90
|
const strategyInstance = this.strategies[strategy];
|
|
90
91
|
switch (strategyInstance.type) {
|
|
91
|
-
case
|
|
92
|
+
case "oauth2":
|
|
92
93
|
return strategyInstance.oauth2.authorizationCode.authorizeURL(params);
|
|
93
94
|
default:
|
|
94
|
-
throw new Error(
|
|
95
|
+
throw new Error("Invalid strategy");
|
|
95
96
|
}
|
|
96
97
|
}
|
|
97
98
|
async getTokens(strategy, options) {
|
|
98
|
-
logger$4.debug(
|
|
99
|
+
logger$4.debug("getTokens", {
|
|
99
100
|
strategy,
|
|
100
101
|
options
|
|
101
102
|
});
|
|
102
103
|
const strategyInstance = this.strategies[strategy];
|
|
103
104
|
switch (strategyInstance.type) {
|
|
104
|
-
case
|
|
105
|
+
case "oauth2":
|
|
105
106
|
{
|
|
106
107
|
const result = await strategyInstance.oauth2.authorizationCode.getToken({
|
|
107
108
|
code: options.code,
|
|
@@ -125,19 +126,19 @@ class AuthenticationService extends EventEmitter {
|
|
|
125
126
|
// return strategyInstance.accessToken.create(result);
|
|
126
127
|
}
|
|
127
128
|
default:
|
|
128
|
-
throw new Error(
|
|
129
|
+
throw new Error("Invalid stategy");
|
|
129
130
|
}
|
|
130
131
|
}
|
|
131
132
|
async refreshToken(strategy, tokensParam) {
|
|
132
|
-
logger$4.debug(
|
|
133
|
+
logger$4.debug("refreshToken", {
|
|
133
134
|
strategy
|
|
134
135
|
});
|
|
135
136
|
if (!tokensParam.refreshToken) {
|
|
136
|
-
throw new Error(
|
|
137
|
+
throw new Error("Missing refresh token");
|
|
137
138
|
}
|
|
138
139
|
const strategyInstance = this.strategies[strategy];
|
|
139
140
|
switch (strategyInstance.type) {
|
|
140
|
-
case
|
|
141
|
+
case "oauth2":
|
|
141
142
|
{
|
|
142
143
|
const token = strategyInstance.oauth2.clientCredentials.createToken({
|
|
143
144
|
refresh_token: tokensParam.refreshToken
|
|
@@ -158,12 +159,12 @@ class AuthenticationService extends EventEmitter {
|
|
|
158
159
|
};
|
|
159
160
|
}
|
|
160
161
|
default:
|
|
161
|
-
throw new Error(
|
|
162
|
+
throw new Error("Invalid stategy");
|
|
162
163
|
}
|
|
163
164
|
}
|
|
164
165
|
redirectUri(ctx, strategy) {
|
|
165
|
-
const host = `http${this.config.get(
|
|
166
|
-
return `${host}${ctx.urlGenerator(
|
|
166
|
+
const host = `http${this.config.get("allowHttps") ? "s" : ""}://${ctx.request.host}`;
|
|
167
|
+
return `${host}${ctx.urlGenerator("authResponse", {
|
|
167
168
|
strategy
|
|
168
169
|
})}`;
|
|
169
170
|
}
|
|
@@ -173,56 +174,56 @@ class AuthenticationService extends EventEmitter {
|
|
|
173
174
|
user,
|
|
174
175
|
accountId
|
|
175
176
|
}, params) {
|
|
176
|
-
logger$4.debug(
|
|
177
|
+
logger$4.debug("redirectAuthUrl", {
|
|
177
178
|
strategy,
|
|
178
179
|
scopeKey,
|
|
179
180
|
refreshToken
|
|
180
181
|
});
|
|
181
182
|
const state = await randomHex(8);
|
|
182
|
-
const scope = this.userAccountsService.getScope(strategy, scopeKey ||
|
|
183
|
+
const scope = this.userAccountsService.getScope(strategy, scopeKey || "login", user, accountId);
|
|
183
184
|
if (!scope) {
|
|
184
|
-
throw new Error(
|
|
185
|
+
throw new Error("Invalid empty scope");
|
|
185
186
|
}
|
|
186
187
|
ctx.cookies.set(`auth_${strategy}_${state}`, JSON.stringify({
|
|
187
188
|
scopeKey,
|
|
188
189
|
scope,
|
|
189
|
-
isLoginAccess: !scopeKey || scopeKey ===
|
|
190
|
+
isLoginAccess: !scopeKey || scopeKey === "login"
|
|
190
191
|
}), {
|
|
191
192
|
maxAge: 600000,
|
|
192
193
|
httpOnly: true,
|
|
193
|
-
secure: this.config.get(
|
|
194
|
+
secure: this.config.get("allowHttps")
|
|
194
195
|
});
|
|
195
196
|
const redirectUri = this.generateAuthUrl(strategy, {
|
|
196
197
|
redirect_uri: this.redirectUri(ctx, strategy),
|
|
197
198
|
scope,
|
|
198
199
|
state,
|
|
199
|
-
access_type: refreshToken ?
|
|
200
|
+
access_type: refreshToken ? "offline" : "online",
|
|
200
201
|
...params
|
|
201
202
|
});
|
|
202
203
|
ctx.redirect(redirectUri);
|
|
203
204
|
}
|
|
204
205
|
async accessResponse(ctx, strategy, isLoggedIn, hooks) {
|
|
205
|
-
const errorParam = ctx.params.queryParam(
|
|
206
|
+
const errorParam = ctx.params.queryParam("error").notEmpty();
|
|
206
207
|
if (errorParam.isValid()) {
|
|
207
|
-
ctx.throw(errorParam.value
|
|
208
|
+
ctx.throw(403, errorParam.value);
|
|
208
209
|
}
|
|
209
|
-
const code = ctx.validParams.queryParam(
|
|
210
|
-
const state = ctx.validParams.queryParam(
|
|
210
|
+
const code = ctx.validParams.queryParam("code").notEmpty().value;
|
|
211
|
+
const state = ctx.validParams.queryParam("state").notEmpty().value;
|
|
211
212
|
const cookieName = `auth_${strategy}_${state}`;
|
|
212
213
|
const cookie = ctx.cookies.get(cookieName);
|
|
213
|
-
ctx.cookies.set(cookieName,
|
|
214
|
+
ctx.cookies.set(cookieName, "", {
|
|
214
215
|
expires: new Date(1)
|
|
215
216
|
});
|
|
216
217
|
if (!cookie) {
|
|
217
|
-
throw new Error(
|
|
218
|
+
throw new Error("No cookie for this state");
|
|
218
219
|
}
|
|
219
220
|
const parsedCookie = JSON.parse(cookie);
|
|
220
221
|
if (!parsedCookie?.scope) {
|
|
221
|
-
throw new Error(
|
|
222
|
+
throw new Error("Unexpected cookie value");
|
|
222
223
|
}
|
|
223
224
|
if (!parsedCookie.isLoginAccess) {
|
|
224
225
|
if (!isLoggedIn) {
|
|
225
|
-
throw new Error(
|
|
226
|
+
throw new Error("You are not connected");
|
|
226
227
|
}
|
|
227
228
|
}
|
|
228
229
|
const tokens = await this.getTokens(strategy, {
|
|
@@ -265,11 +266,10 @@ class AuthenticationService extends EventEmitter {
|
|
|
265
266
|
}
|
|
266
267
|
}
|
|
267
268
|
|
|
268
|
-
|
|
269
|
-
const logger$3 = new Logger('alp:auth:userAccounts');
|
|
269
|
+
const logger$3 = new Logger("alp:auth:userAccounts");
|
|
270
270
|
const STATUSES = {
|
|
271
|
-
VALIDATED:
|
|
272
|
-
DELETED:
|
|
271
|
+
VALIDATED: "validated",
|
|
272
|
+
DELETED: "deleted"
|
|
273
273
|
};
|
|
274
274
|
class UserAccountsService extends EventEmitter {
|
|
275
275
|
constructor(usersManager, strategyToService) {
|
|
@@ -278,13 +278,13 @@ class UserAccountsService extends EventEmitter {
|
|
|
278
278
|
this.strategyToService = strategyToService;
|
|
279
279
|
}
|
|
280
280
|
getScope(strategy, scopeKey, user, accountId) {
|
|
281
|
-
logger$3.debug(
|
|
281
|
+
logger$3.debug("getScope", {
|
|
282
282
|
strategy,
|
|
283
283
|
userId: user?._id
|
|
284
284
|
});
|
|
285
285
|
const service = this.strategyToService[strategy];
|
|
286
286
|
if (!service) {
|
|
287
|
-
throw new Error(
|
|
287
|
+
throw new Error("Strategy not supported");
|
|
288
288
|
}
|
|
289
289
|
const newScope = service.scopeKeyToScope[scopeKey];
|
|
290
290
|
if (!user || !accountId) {
|
|
@@ -292,9 +292,9 @@ class UserAccountsService extends EventEmitter {
|
|
|
292
292
|
}
|
|
293
293
|
const account = user.accounts.find(account => account.provider === strategy && account.accountId === accountId);
|
|
294
294
|
if (!account) {
|
|
295
|
-
throw new Error(
|
|
295
|
+
throw new Error("Could not found associated account");
|
|
296
296
|
}
|
|
297
|
-
return service.getScope(account.scope, newScope).join(
|
|
297
|
+
return service.getScope(account.scope, newScope).join(" ");
|
|
298
298
|
}
|
|
299
299
|
async update(user, strategy, tokens, scope, subservice) {
|
|
300
300
|
const service = this.strategyToService[strategy];
|
|
@@ -304,9 +304,9 @@ class UserAccountsService extends EventEmitter {
|
|
|
304
304
|
if (!account) {
|
|
305
305
|
// TODO check if already exists in other user => merge
|
|
306
306
|
// TODO else add a new account in this user
|
|
307
|
-
throw new Error(
|
|
307
|
+
throw new Error("Could not found associated account");
|
|
308
308
|
}
|
|
309
|
-
account.status =
|
|
309
|
+
account.status = "valid";
|
|
310
310
|
account.accessToken = tokens.accessToken;
|
|
311
311
|
if (tokens.refreshToken) {
|
|
312
312
|
account.refreshToken = tokens.refreshToken;
|
|
@@ -327,17 +327,17 @@ class UserAccountsService extends EventEmitter {
|
|
|
327
327
|
}
|
|
328
328
|
async findOrCreateFromStrategy(strategy, tokens, scope, subservice) {
|
|
329
329
|
const service = this.strategyToService[strategy];
|
|
330
|
-
if (!service) throw new Error(
|
|
330
|
+
if (!service) throw new Error("Strategy not supported");
|
|
331
331
|
const profile = await service.getProfile(tokens);
|
|
332
332
|
const accountId = service.getId(profile);
|
|
333
|
-
if (!accountId) throw new Error(
|
|
333
|
+
if (!accountId) throw new Error("Invalid profile: no id found");
|
|
334
334
|
const emails = service.getEmails(profile);
|
|
335
335
|
let user = await this.usersManager.findOneByAccountOrEmails({
|
|
336
336
|
provider: service.providerKey,
|
|
337
337
|
accountId,
|
|
338
338
|
emails
|
|
339
339
|
});
|
|
340
|
-
logger$3.info(!user ?
|
|
340
|
+
logger$3.info(!user ? "create user" : "existing user", {
|
|
341
341
|
userId: user?._id,
|
|
342
342
|
accountId
|
|
343
343
|
/*emails , user*/
|
|
@@ -357,11 +357,10 @@ class UserAccountsService extends EventEmitter {
|
|
|
357
357
|
provider: strategy,
|
|
358
358
|
accountId
|
|
359
359
|
};
|
|
360
|
-
// @ts-expect-error well...
|
|
361
360
|
user.accounts.push(account);
|
|
362
361
|
}
|
|
363
362
|
account.name = service.getAccountName(profile);
|
|
364
|
-
account.status =
|
|
363
|
+
account.status = "valid";
|
|
365
364
|
account.profile = profile;
|
|
366
365
|
account.accessToken = tokens.accessToken;
|
|
367
366
|
if (tokens.refreshToken) {
|
|
@@ -384,7 +383,7 @@ class UserAccountsService extends EventEmitter {
|
|
|
384
383
|
});
|
|
385
384
|
user.emailDomains = [
|
|
386
385
|
// eslint-disable-next-line unicorn/no-array-reduce
|
|
387
|
-
...user.emails.reduce((domains, email) => domains.add(email.split(
|
|
386
|
+
...user.emails.reduce((domains, email) => domains.add(email.split("@", 2)[1]), new Set())];
|
|
388
387
|
const keyPath = this.usersManager.store.keyPath;
|
|
389
388
|
if (user[keyPath]) {
|
|
390
389
|
await this.usersManager.replaceOne(user);
|
|
@@ -399,10 +398,10 @@ class UserAccountsService extends EventEmitter {
|
|
|
399
398
|
}
|
|
400
399
|
}
|
|
401
400
|
|
|
402
|
-
const COOKIE_NAME_TOKEN =
|
|
403
|
-
const COOKIE_NAME_STATE =
|
|
401
|
+
const COOKIE_NAME_TOKEN = "loggedInUserToken";
|
|
402
|
+
const COOKIE_NAME_STATE = "loggedInUserState";
|
|
404
403
|
const getTokenFromRequest = (req, options) => {
|
|
405
|
-
if (req.headers.authorization?.startsWith(
|
|
404
|
+
if (req.headers.authorization?.startsWith("Bearer ")) {
|
|
406
405
|
return req.headers.authorization.slice(7);
|
|
407
406
|
}
|
|
408
407
|
|
|
@@ -417,7 +416,7 @@ const getTokenFromRequest = (req, options) => {
|
|
|
417
416
|
const verifyPromisified = promisify(jsonwebtoken.verify);
|
|
418
417
|
const createDecodeJWT = secretKey => async (token, jwtAudience) => {
|
|
419
418
|
const result = await verifyPromisified(token, secretKey, {
|
|
420
|
-
algorithms: [
|
|
419
|
+
algorithms: ["HS512"],
|
|
421
420
|
audience: jwtAudience
|
|
422
421
|
});
|
|
423
422
|
return result?.loggedInUserId;
|
|
@@ -430,7 +429,7 @@ const createFindLoggedInUser = (secretKey, usersManager, logger) => {
|
|
|
430
429
|
try {
|
|
431
430
|
loggedInUserId = await decodeJwt(token, jwtAudience);
|
|
432
431
|
} catch (error) {
|
|
433
|
-
logger.debug(
|
|
432
|
+
logger.debug("failed to verify authentification", {
|
|
434
433
|
err: error
|
|
435
434
|
});
|
|
436
435
|
}
|
|
@@ -468,8 +467,8 @@ class MongoUsersManager {
|
|
|
468
467
|
provider
|
|
469
468
|
}) {
|
|
470
469
|
let query = {
|
|
471
|
-
|
|
472
|
-
|
|
470
|
+
"accounts.provider": provider,
|
|
471
|
+
"accounts.accountId": accountId
|
|
473
472
|
};
|
|
474
473
|
if (emails && emails.length > 0) {
|
|
475
474
|
query = {
|
|
@@ -487,7 +486,7 @@ class MongoUsersManager {
|
|
|
487
486
|
updateAccount(user, account) {
|
|
488
487
|
const accountIndex = user.accounts.indexOf(account);
|
|
489
488
|
if (accountIndex === -1) {
|
|
490
|
-
throw new Error(
|
|
489
|
+
throw new Error("Invalid account");
|
|
491
490
|
}
|
|
492
491
|
return this.store.partialUpdateOne(user, {
|
|
493
492
|
$set: {
|
|
@@ -495,8 +494,6 @@ class MongoUsersManager {
|
|
|
495
494
|
}
|
|
496
495
|
});
|
|
497
496
|
}
|
|
498
|
-
|
|
499
|
-
// eslint-disable-next-line @typescript-eslint/class-methods-use-this
|
|
500
497
|
sanitizeBaseUser(user) {
|
|
501
498
|
return {
|
|
502
499
|
_id: user._id,
|
|
@@ -518,7 +515,6 @@ class MongoUsersManager {
|
|
|
518
515
|
}
|
|
519
516
|
}
|
|
520
517
|
|
|
521
|
-
/* eslint-disable @typescript-eslint/class-methods-use-this */
|
|
522
518
|
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
523
519
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
|
524
520
|
|
|
@@ -526,11 +522,12 @@ class UserAccountGoogleService {
|
|
|
526
522
|
constructor(scopeKeyToScope) {
|
|
527
523
|
this.scopeKeyToScope = {
|
|
528
524
|
...scopeKeyToScope,
|
|
529
|
-
login:
|
|
525
|
+
login: "openid profile email"
|
|
530
526
|
};
|
|
531
527
|
}
|
|
532
|
-
providerKey =
|
|
528
|
+
providerKey = "google";
|
|
533
529
|
getProfile(tokens) {
|
|
530
|
+
// eslint-disable-next-line n/no-unsupported-features/node-builtins
|
|
534
531
|
return fetch(`https://www.googleapis.com/oauth2/v1/userinfo?access_token=${tokens.accessToken}`).then(response => response.json());
|
|
535
532
|
}
|
|
536
533
|
getId(profile) {
|
|
@@ -559,11 +556,10 @@ class UserAccountGoogleService {
|
|
|
559
556
|
return this.getScope(undefined, newScope);
|
|
560
557
|
}
|
|
561
558
|
getScope(oldScope, newScope) {
|
|
562
|
-
return !oldScope ? newScope.split(
|
|
559
|
+
return !oldScope ? newScope.split(" ") : [...oldScope, ...newScope.split(" ")].filter((item, i, ar) => ar.indexOf(item) === i);
|
|
563
560
|
}
|
|
564
561
|
}
|
|
565
562
|
|
|
566
|
-
/* eslint-disable @typescript-eslint/class-methods-use-this */
|
|
567
563
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
|
568
564
|
|
|
569
565
|
// https://api.slack.com/methods/users.identity
|
|
@@ -572,11 +568,12 @@ class UserAccountSlackService {
|
|
|
572
568
|
constructor(scopeKeyToScope) {
|
|
573
569
|
this.scopeKeyToScope = {
|
|
574
570
|
...scopeKeyToScope,
|
|
575
|
-
login:
|
|
571
|
+
login: "identity.basic identity.email identity.avatar"
|
|
576
572
|
};
|
|
577
573
|
}
|
|
578
|
-
providerKey =
|
|
574
|
+
providerKey = "google";
|
|
579
575
|
getProfile(tokens) {
|
|
576
|
+
// eslint-disable-next-line n/no-unsupported-features/node-builtins
|
|
580
577
|
return fetch(`https://slack.com/api/users.identity?token=${tokens.accessToken}`).then(response => response.json());
|
|
581
578
|
}
|
|
582
579
|
getId(profile) {
|
|
@@ -601,13 +598,13 @@ class UserAccountSlackService {
|
|
|
601
598
|
return this.getScope(undefined, newScope);
|
|
602
599
|
}
|
|
603
600
|
getScope(oldScope, newScope) {
|
|
604
|
-
return !oldScope ? newScope.split(
|
|
601
|
+
return !oldScope ? newScope.split(" ") : [...oldScope, ...newScope.split(" ")].filter((item, i, ar) => ar.indexOf(item) === i);
|
|
605
602
|
}
|
|
606
603
|
}
|
|
607
604
|
|
|
608
|
-
const logger$2 = new Logger(
|
|
605
|
+
const logger$2 = new Logger("alp:auth");
|
|
609
606
|
const authSocketIO = (app, usersManager, io, jwtAudience) => {
|
|
610
|
-
const findLoggedInUser = createFindLoggedInUser(app.config.get(
|
|
607
|
+
const findLoggedInUser = createFindLoggedInUser(app.config.get("authentication").secretKey, usersManager, logger$2);
|
|
611
608
|
const users = new Map();
|
|
612
609
|
io.users = users;
|
|
613
610
|
io.use(async (socket, next) => {
|
|
@@ -617,16 +614,16 @@ const authSocketIO = (app, usersManager, io, jwtAudience) => {
|
|
|
617
614
|
if (!token) return next();
|
|
618
615
|
const [loggedInUserId, loggedInUser] = await findLoggedInUser(
|
|
619
616
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
620
|
-
jwtAudience || handshakeData.headers[
|
|
617
|
+
jwtAudience || handshakeData.headers["user-agent"], token);
|
|
621
618
|
if (!loggedInUserId || !loggedInUser) return next();
|
|
622
619
|
socket.user = loggedInUser;
|
|
623
620
|
users.set(socket.client.id, loggedInUser);
|
|
624
|
-
socket.on(
|
|
621
|
+
socket.on("disconnected", () => users.delete(socket.client.id));
|
|
625
622
|
await next();
|
|
626
623
|
});
|
|
627
624
|
};
|
|
628
625
|
|
|
629
|
-
const logger$1 = new Logger(
|
|
626
|
+
const logger$1 = new Logger("alp:auth");
|
|
630
627
|
const getTokenFromReq = req => {
|
|
631
628
|
if (req.cookies) return req.cookies[COOKIE_NAME_TOKEN];
|
|
632
629
|
return getTokenFromRequest(req);
|
|
@@ -637,7 +634,7 @@ const getTokenFromReq = req => {
|
|
|
637
634
|
* @internal
|
|
638
635
|
*/
|
|
639
636
|
const createAuthApolloContext = (config, usersManager) => {
|
|
640
|
-
const findLoggedInUser = createFindLoggedInUser(config.get(
|
|
637
|
+
const findLoggedInUser = createFindLoggedInUser(config.get("authentication").secretKey, usersManager, logger$1);
|
|
641
638
|
return async ({
|
|
642
639
|
req,
|
|
643
640
|
connection
|
|
@@ -656,16 +653,14 @@ const createAuthApolloContext = (config, usersManager) => {
|
|
|
656
653
|
};
|
|
657
654
|
const [, loggedInUser] = await findLoggedInUser(
|
|
658
655
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
659
|
-
req.headers[
|
|
656
|
+
req.headers["user-agent"], token);
|
|
660
657
|
return {
|
|
661
658
|
user: loggedInUser
|
|
662
659
|
};
|
|
663
660
|
};
|
|
664
661
|
};
|
|
665
662
|
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
const logger = new Logger('alp:auth');
|
|
663
|
+
const logger = new Logger("alp:auth");
|
|
669
664
|
const signPromisified = promisify(jsonwebtoken.sign);
|
|
670
665
|
function init({
|
|
671
666
|
homeRouterKey,
|
|
@@ -687,27 +682,26 @@ function init({
|
|
|
687
682
|
defaultStrategy,
|
|
688
683
|
authHooks
|
|
689
684
|
});
|
|
690
|
-
app.context.setLoggedIn = async function (loggedInUserId, loggedInUser) {
|
|
691
|
-
logger.debug(
|
|
685
|
+
app.context.setLoggedIn = async function setLoggedIn(loggedInUserId, loggedInUser) {
|
|
686
|
+
logger.debug("setLoggedIn", {
|
|
692
687
|
loggedInUser
|
|
693
688
|
});
|
|
694
689
|
if (!loggedInUserId) {
|
|
695
|
-
throw new Error(
|
|
690
|
+
throw new Error("Illegal value for setLoggedIn");
|
|
696
691
|
}
|
|
697
692
|
this.state.loggedInUserId = loggedInUserId;
|
|
698
693
|
this.state.loggedInUser = loggedInUser;
|
|
699
694
|
const token = await signPromisified({
|
|
700
695
|
loggedInUserId,
|
|
701
696
|
time: Date.now()
|
|
702
|
-
}, this.config.get(
|
|
703
|
-
algorithm:
|
|
704
|
-
audience: jwtAudience || this.request.headers[
|
|
705
|
-
expiresIn:
|
|
697
|
+
}, this.config.get("authentication").get("secretKey"), {
|
|
698
|
+
algorithm: "HS512",
|
|
699
|
+
audience: jwtAudience || this.request.headers["user-agent"],
|
|
700
|
+
expiresIn: "30 days"
|
|
706
701
|
});
|
|
707
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
708
702
|
this.cookies.set(COOKIE_NAME_TOKEN, token, {
|
|
709
703
|
httpOnly: true,
|
|
710
|
-
secure: this.config.get(
|
|
704
|
+
secure: this.config.get("allowHttps")
|
|
711
705
|
});
|
|
712
706
|
this.cookies.set(COOKIE_NAME_STATE, JSON.stringify({
|
|
713
707
|
loggedInUserId,
|
|
@@ -718,31 +712,31 @@ function init({
|
|
|
718
712
|
})()
|
|
719
713
|
}), {
|
|
720
714
|
httpOnly: false,
|
|
721
|
-
secure: this.config.get(
|
|
715
|
+
secure: this.config.get("allowHttps")
|
|
722
716
|
});
|
|
723
717
|
};
|
|
724
|
-
app.context.logout = function () {
|
|
718
|
+
app.context.logout = function logout() {
|
|
725
719
|
delete this.state.loggedInUserId;
|
|
726
720
|
delete this.state.loggedInUser;
|
|
727
|
-
this.cookies.set(COOKIE_NAME_TOKEN,
|
|
721
|
+
this.cookies.set(COOKIE_NAME_TOKEN, "", {
|
|
728
722
|
expires: new Date(1)
|
|
729
723
|
});
|
|
730
|
-
this.cookies.set(COOKIE_NAME_STATE,
|
|
724
|
+
this.cookies.set(COOKIE_NAME_STATE, "", {
|
|
731
725
|
expires: new Date(1)
|
|
732
726
|
});
|
|
733
727
|
};
|
|
734
|
-
const findLoggedInUser = createFindLoggedInUser(app.config.get(
|
|
728
|
+
const findLoggedInUser = createFindLoggedInUser(app.config.get("authentication").secretKey, usersManager, logger);
|
|
735
729
|
return {
|
|
736
730
|
routes: createRoutes(controller),
|
|
737
731
|
findLoggedInUserFromRequest: req => {
|
|
738
732
|
const token = getTokenFromRequest(req);
|
|
739
|
-
return findLoggedInUser(jwtAudience || req.headers[
|
|
733
|
+
return findLoggedInUser(jwtAudience || req.headers["user-agent"], token);
|
|
740
734
|
},
|
|
741
735
|
findLoggedInUser,
|
|
742
736
|
middleware: async (ctx, next) => {
|
|
743
737
|
const token = ctx.cookies.get(COOKIE_NAME_TOKEN);
|
|
744
|
-
const userAgent = ctx.request.headers[
|
|
745
|
-
logger.debug(
|
|
738
|
+
const userAgent = ctx.request.headers["user-agent"];
|
|
739
|
+
logger.debug("middleware", {
|
|
746
740
|
token
|
|
747
741
|
});
|
|
748
742
|
const setState = (loggedInUserId, loggedInUser) => {
|
|
@@ -752,15 +746,15 @@ function init({
|
|
|
752
746
|
ctx.sanitizedState.loggedInUser = loggedInUser && usersManager.sanitize(loggedInUser);
|
|
753
747
|
};
|
|
754
748
|
const [loggedInUserId, loggedInUser] = await findLoggedInUser(jwtAudience || userAgent, token);
|
|
755
|
-
logger.debug(
|
|
749
|
+
logger.debug("middleware", {
|
|
756
750
|
loggedInUserId
|
|
757
751
|
});
|
|
758
752
|
if (loggedInUserId == null || loggedInUser == null) {
|
|
759
753
|
if (token) {
|
|
760
|
-
ctx.cookies.set(COOKIE_NAME_TOKEN,
|
|
754
|
+
ctx.cookies.set(COOKIE_NAME_TOKEN, "", {
|
|
761
755
|
expires: new Date(1)
|
|
762
756
|
});
|
|
763
|
-
ctx.cookies.set(COOKIE_NAME_STATE,
|
|
757
|
+
ctx.cookies.set(COOKIE_NAME_STATE, "", {
|
|
764
758
|
expires: new Date(1)
|
|
765
759
|
});
|
|
766
760
|
}
|
|
@@ -775,4 +769,4 @@ function init({
|
|
|
775
769
|
}
|
|
776
770
|
|
|
777
771
|
export { AuthenticationService, MongoUsersManager, STATUSES, UserAccountGoogleService, UserAccountSlackService, authSocketIO, createAuthApolloContext, init as default };
|
|
778
|
-
//# sourceMappingURL=index-
|
|
772
|
+
//# sourceMappingURL=index-node20.mjs.map
|