alp-node-auth 7.2.2 → 9.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 +32 -0
- package/README.md +1 -1
- package/dist/definitions/MongoUsersManager.d.ts +4 -2
- package/dist/definitions/MongoUsersManager.d.ts.map +1 -1
- package/dist/definitions/authApolloContext.d.ts +2 -2
- package/dist/definitions/authApolloContext.d.ts.map +1 -1
- package/dist/definitions/authSocketIO.d.ts +2 -2
- package/dist/definitions/authSocketIO.d.ts.map +1 -1
- package/dist/definitions/createAuthController.d.ts +2 -2
- package/dist/definitions/createAuthController.d.ts.map +1 -1
- package/dist/definitions/index.d.ts +10 -9
- package/dist/definitions/index.d.ts.map +1 -1
- package/dist/definitions/services/authentification/AuthenticationService.d.ts +6 -12
- package/dist/definitions/services/authentification/AuthenticationService.d.ts.map +1 -1
- package/dist/definitions/services/authentification/types.d.ts +2 -2
- package/dist/definitions/services/authentification/types.d.ts.map +1 -1
- package/dist/definitions/services/user/UserAccountSlackService.d.ts.map +1 -1
- package/dist/definitions/services/user/UserAccountsService.d.ts +2 -2
- package/dist/definitions/services/user/UserAccountsService.d.ts.map +1 -1
- package/dist/definitions/services/user/types.d.ts +2 -2
- package/dist/definitions/services/user/types.d.ts.map +1 -1
- package/dist/definitions/types.d.ts +42 -0
- package/dist/definitions/types.d.ts.map +1 -0
- package/dist/definitions/utils/cookies.d.ts +3 -2
- package/dist/definitions/utils/cookies.d.ts.map +1 -1
- package/dist/definitions/utils/createFindLoggedInUser.d.ts +6 -0
- package/dist/definitions/utils/createFindLoggedInUser.d.ts.map +1 -0
- package/dist/{index-node16.mjs → index-node18.mjs} +125 -80
- package/dist/index-node18.mjs.map +1 -0
- package/package.json +67 -30
- package/src/MongoUsersManager.ts +8 -2
- package/src/authApolloContext.ts +10 -10
- package/src/authSocketIO.ts +9 -8
- package/src/createAuthController.ts +10 -9
- package/src/index.ts +74 -46
- package/src/services/authentification/AuthenticationService.ts +30 -33
- package/src/services/authentification/types.ts +2 -2
- package/src/services/user/UserAccountGoogleService.ts +1 -1
- package/src/services/user/UserAccountSlackService.ts +2 -8
- package/src/services/user/UserAccountsService.ts +10 -5
- package/src/services/user/types.ts +2 -2
- package/{types.d.ts → src/types.ts} +2 -3
- package/src/utils/cookies.ts +8 -3
- package/src/utils/{createFindConnectedAndUser.ts → createFindLoggedInUser.ts} +19 -20
- package/src/utils/generators.ts +2 -2
- package/strategies/dropbox.js +22 -12
- package/strategies/facebook.js +22 -12
- package/strategies/foursquare.js +22 -12
- package/strategies/github.js +22 -12
- package/strategies/google.js +23 -12
- package/strategies/slack.js +22 -12
- package/strategies/strategies.d.ts +9 -4
- package/dist/definitions/utils/createFindConnectedAndUser.d.ts +0 -6
- package/dist/definitions/utils/createFindConnectedAndUser.d.ts.map +0 -1
- package/dist/index-node16.mjs.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "alp-node-auth",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.0",
|
|
4
4
|
"description": "authentication with alp",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"alp"
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
"homepage": "https://github.com/christophehurpeau/alp",
|
|
16
16
|
"type": "module",
|
|
17
17
|
"engines": {
|
|
18
|
-
"node": ">=
|
|
18
|
+
"node": ">=18.12.0"
|
|
19
19
|
},
|
|
20
|
-
"main": "./dist/index-
|
|
20
|
+
"main": "./dist/index-node18.mjs",
|
|
21
21
|
"types": "./dist/definitions/index.d.ts",
|
|
22
22
|
"typesVersions": {
|
|
23
23
|
">=3.1": {
|
|
@@ -29,16 +29,35 @@
|
|
|
29
29
|
"exports": {
|
|
30
30
|
"./package.json": "./package.json",
|
|
31
31
|
".": {
|
|
32
|
+
"types": "./dist/definitions/index.d.ts",
|
|
32
33
|
"node": {
|
|
33
|
-
"import": "./dist/index-
|
|
34
|
+
"import": "./dist/index-node18.mjs"
|
|
34
35
|
}
|
|
35
36
|
},
|
|
36
|
-
"./strategies/dropbox":
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"./strategies/
|
|
41
|
-
|
|
37
|
+
"./strategies/dropbox": {
|
|
38
|
+
"types": "./strategies/strategies.d.ts",
|
|
39
|
+
"default": "./strategies/dropbox.js"
|
|
40
|
+
},
|
|
41
|
+
"./strategies/facebook": {
|
|
42
|
+
"types": "./strategies/strategies.d.ts",
|
|
43
|
+
"default": "./strategies/facebook.js"
|
|
44
|
+
},
|
|
45
|
+
"./strategies/foursquare": {
|
|
46
|
+
"types": "./strategies/strategies.d.ts",
|
|
47
|
+
"default": "./strategies/foursquare.js"
|
|
48
|
+
},
|
|
49
|
+
"./strategies/github": {
|
|
50
|
+
"types": "./strategies/strategies.d.ts",
|
|
51
|
+
"default": "./strategies/github.js"
|
|
52
|
+
},
|
|
53
|
+
"./strategies/google": {
|
|
54
|
+
"types": "./strategies/strategies.d.ts",
|
|
55
|
+
"default": "./strategies/google.js"
|
|
56
|
+
},
|
|
57
|
+
"./strategies/slack": {
|
|
58
|
+
"types": "./strategies/strategies.d.ts",
|
|
59
|
+
"default": "./strategies/slack.js"
|
|
60
|
+
}
|
|
42
61
|
},
|
|
43
62
|
"sideEffects": false,
|
|
44
63
|
"scripts": {
|
|
@@ -55,44 +74,62 @@
|
|
|
55
74
|
"babelEnvs": [
|
|
56
75
|
{
|
|
57
76
|
"target": "node",
|
|
58
|
-
"version": "
|
|
77
|
+
"version": "18"
|
|
59
78
|
}
|
|
60
79
|
],
|
|
61
80
|
"entries": [
|
|
62
81
|
"index"
|
|
63
82
|
],
|
|
64
83
|
"extraEntries": [
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
84
|
+
{
|
|
85
|
+
"name": "strategies/dropbox",
|
|
86
|
+
"types": "strategies/strategies.d.ts"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"name": "strategies/facebook",
|
|
90
|
+
"types": "strategies/strategies.d.ts"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"name": "strategies/foursquare",
|
|
94
|
+
"types": "strategies/strategies.d.ts"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"name": "strategies/github",
|
|
98
|
+
"types": "strategies/strategies.d.ts"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"name": "strategies/google",
|
|
102
|
+
"types": "strategies/strategies.d.ts"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"name": "strategies/slack",
|
|
106
|
+
"types": "strategies/strategies.d.ts"
|
|
107
|
+
}
|
|
71
108
|
]
|
|
72
109
|
},
|
|
73
110
|
"peerDependencies": {
|
|
74
111
|
"alp-node": "^5.0.0",
|
|
75
112
|
"alp-router": "^6.0.0",
|
|
76
|
-
"liwi-mongo": "^10.
|
|
77
|
-
"router-segments": "^
|
|
113
|
+
"liwi-mongo": "^10.5.0",
|
|
114
|
+
"router-segments": "^7.0.0"
|
|
78
115
|
},
|
|
79
116
|
"dependencies": {
|
|
80
117
|
"@types/jsonwebtoken": "^9.0.1",
|
|
81
|
-
"@types/simple-oauth2": "^
|
|
118
|
+
"@types/simple-oauth2": "^5.0.4",
|
|
82
119
|
"alp-types": "3.1.0",
|
|
83
120
|
"cookies": "~0.8.0",
|
|
84
121
|
"jsonwebtoken": "^9.0.0",
|
|
85
|
-
"nightingale-logger": "^
|
|
86
|
-
"simple-oauth2": "^
|
|
122
|
+
"nightingale-logger": "^14.1.0",
|
|
123
|
+
"simple-oauth2": "^5.0.0"
|
|
87
124
|
},
|
|
88
125
|
"devDependencies": {
|
|
89
|
-
"@babel/core": "7.
|
|
90
|
-
"alp-node": "
|
|
91
|
-
"alp-router": "
|
|
92
|
-
"liwi-mongo": "10.
|
|
93
|
-
"pob-babel": "
|
|
94
|
-
"router-segments": "
|
|
95
|
-
"typescript": "
|
|
126
|
+
"@babel/core": "7.22.9",
|
|
127
|
+
"alp-node": "6.0.0",
|
|
128
|
+
"alp-router": "7.0.0",
|
|
129
|
+
"liwi-mongo": "10.5.0",
|
|
130
|
+
"pob-babel": "36.2.0",
|
|
131
|
+
"router-segments": "7.0.0",
|
|
132
|
+
"typescript": "5.1.6"
|
|
96
133
|
},
|
|
97
|
-
"gitHead": "
|
|
134
|
+
"gitHead": "c01392e16b2d914a332fe835333dd6a82c677ab8"
|
|
98
135
|
}
|
package/src/MongoUsersManager.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { MongoInsertType, MongoStore, Update } from 'liwi-mongo';
|
|
2
|
-
import type { User, Account, UserSanitized } from '
|
|
2
|
+
import type { User, Account, UserSanitized } from './types';
|
|
3
3
|
|
|
4
4
|
export default class MongoUsersManager<
|
|
5
5
|
U extends User = User,
|
|
@@ -11,10 +11,15 @@ export default class MongoUsersManager<
|
|
|
11
11
|
this.store = store;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
/** @deprecated use findById instead */
|
|
14
15
|
findConnected(connected: string): Promise<U | undefined> {
|
|
15
16
|
return this.store.findByKey(connected);
|
|
16
17
|
}
|
|
17
18
|
|
|
19
|
+
findById(userId: string): Promise<U | undefined> {
|
|
20
|
+
return this.store.findByKey(userId);
|
|
21
|
+
}
|
|
22
|
+
|
|
18
23
|
insertOne(user: MongoInsertType<U>): Promise<any> {
|
|
19
24
|
return this.store.insertOne(user);
|
|
20
25
|
}
|
|
@@ -32,7 +37,7 @@ export default class MongoUsersManager<
|
|
|
32
37
|
emails,
|
|
33
38
|
provider,
|
|
34
39
|
}: {
|
|
35
|
-
accountId:
|
|
40
|
+
accountId: number | string;
|
|
36
41
|
emails?: string[];
|
|
37
42
|
provider: string;
|
|
38
43
|
}): Promise<U | undefined> {
|
|
@@ -69,6 +74,7 @@ export default class MongoUsersManager<
|
|
|
69
74
|
} as Update<U>);
|
|
70
75
|
}
|
|
71
76
|
|
|
77
|
+
// eslint-disable-next-line @typescript-eslint/class-methods-use-this
|
|
72
78
|
sanitizeBaseUser(user: U): UserSanitized {
|
|
73
79
|
return {
|
|
74
80
|
_id: user._id,
|
package/src/authApolloContext.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import type { IncomingMessage } from 'http';
|
|
1
|
+
import type { IncomingMessage } from 'node:http';
|
|
2
2
|
import type { NodeConfig } from 'alp-types';
|
|
3
3
|
import { Logger } from 'nightingale-logger';
|
|
4
|
-
import type { User } from '../types.d';
|
|
5
4
|
import type MongoUsersManager from './MongoUsersManager';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
5
|
+
import type { User } from './types';
|
|
6
|
+
import { getTokenFromRequest, COOKIE_NAME_TOKEN } from './utils/cookies';
|
|
7
|
+
import { createFindLoggedInUser } from './utils/createFindLoggedInUser';
|
|
8
8
|
|
|
9
9
|
const logger = new Logger('alp:auth');
|
|
10
10
|
|
|
11
11
|
const getTokenFromReq = (
|
|
12
12
|
req: IncomingMessage & { cookies?: Record<string, string> },
|
|
13
13
|
): string | undefined => {
|
|
14
|
-
if (req.cookies) return req.cookies[
|
|
14
|
+
if (req.cookies) return req.cookies[COOKIE_NAME_TOKEN];
|
|
15
15
|
return getTokenFromRequest(req);
|
|
16
16
|
};
|
|
17
17
|
|
|
@@ -23,15 +23,15 @@ export const createAuthApolloContext = <U extends User = User>(
|
|
|
23
23
|
config: NodeConfig,
|
|
24
24
|
usersManager: MongoUsersManager<U>,
|
|
25
25
|
): any => {
|
|
26
|
-
const
|
|
26
|
+
const findLoggedInUser = createFindLoggedInUser(
|
|
27
27
|
config.get<Map<string, string>>('authentication').get('secretKey')!,
|
|
28
28
|
usersManager,
|
|
29
29
|
logger,
|
|
30
30
|
);
|
|
31
31
|
|
|
32
32
|
return async ({ req, connection }: { req: any; connection: any }) => {
|
|
33
|
-
if (connection?.
|
|
34
|
-
return { user: connection.
|
|
33
|
+
if (connection?.loggedInUser) {
|
|
34
|
+
return { user: connection.loggedInUser };
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
if (!req) return null;
|
|
@@ -41,12 +41,12 @@ export const createAuthApolloContext = <U extends User = User>(
|
|
|
41
41
|
|
|
42
42
|
if (!token) return { user: undefined };
|
|
43
43
|
|
|
44
|
-
const [,
|
|
44
|
+
const [, loggedInUser] = await findLoggedInUser(
|
|
45
45
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
46
46
|
req.headers['user-agent'],
|
|
47
47
|
token,
|
|
48
48
|
);
|
|
49
49
|
|
|
50
|
-
return { user };
|
|
50
|
+
return { user: loggedInUser };
|
|
51
51
|
};
|
|
52
52
|
};
|
package/src/authSocketIO.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { NodeApplication } from 'alp-types';
|
|
2
2
|
import { Logger } from 'nightingale-logger';
|
|
3
|
-
import type { User } from '../types.d';
|
|
4
3
|
import type MongoUsersManager from './MongoUsersManager';
|
|
4
|
+
import type { User } from './types';
|
|
5
5
|
import { getTokenFromRequest } from './utils/cookies';
|
|
6
|
-
import {
|
|
6
|
+
import { createFindLoggedInUser } from './utils/createFindLoggedInUser';
|
|
7
7
|
|
|
8
8
|
const logger = new Logger('alp:auth');
|
|
9
9
|
|
|
@@ -12,8 +12,9 @@ export const authSocketIO = <U extends User = User>(
|
|
|
12
12
|
usersManager: MongoUsersManager<U>,
|
|
13
13
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
14
14
|
io: any,
|
|
15
|
+
jwtAudience?: string,
|
|
15
16
|
): void => {
|
|
16
|
-
const
|
|
17
|
+
const findLoggedInUser = createFindLoggedInUser(
|
|
17
18
|
app.config.get<Map<string, string>>('authentication').get('secretKey')!,
|
|
18
19
|
usersManager,
|
|
19
20
|
logger,
|
|
@@ -29,16 +30,16 @@ export const authSocketIO = <U extends User = User>(
|
|
|
29
30
|
|
|
30
31
|
if (!token) return next();
|
|
31
32
|
|
|
32
|
-
const [
|
|
33
|
+
const [loggedInUserId, loggedInUser] = await findLoggedInUser(
|
|
33
34
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
34
|
-
handshakeData.headers['user-agent'],
|
|
35
|
+
jwtAudience || handshakeData.headers['user-agent'],
|
|
35
36
|
token,
|
|
36
37
|
);
|
|
37
38
|
|
|
38
|
-
if (!
|
|
39
|
+
if (!loggedInUserId || !loggedInUser) return next();
|
|
39
40
|
|
|
40
|
-
socket.user =
|
|
41
|
-
users.set(socket.client.id,
|
|
41
|
+
socket.user = loggedInUser;
|
|
42
|
+
users.set(socket.client.id, loggedInUser);
|
|
42
43
|
|
|
43
44
|
socket.on('disconnected', () => users.delete(socket.client.id));
|
|
44
45
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { Context } from 'alp-node';
|
|
2
2
|
import 'alp-router';
|
|
3
|
-
import type { User, UserSanitized } from '../types.d';
|
|
4
3
|
import type MongoUsersManager from './MongoUsersManager';
|
|
5
4
|
import type {
|
|
6
5
|
AuthenticationService,
|
|
@@ -10,6 +9,7 @@ import type {
|
|
|
10
9
|
AllowedStrategyKeys,
|
|
11
10
|
AllowedMapParamsStrategy,
|
|
12
11
|
} from './services/authentification/types';
|
|
12
|
+
import type { User, UserSanitized } from './types';
|
|
13
13
|
|
|
14
14
|
export interface CreateAuthControllerParams<
|
|
15
15
|
StrategyKeys extends AllowedStrategyKeys,
|
|
@@ -37,11 +37,12 @@ export interface AuthHooks<StrategyKeys extends AllowedStrategyKeys>
|
|
|
37
37
|
paramsForLogin?: <StrategyKey extends StrategyKeys>(
|
|
38
38
|
strategy: StrategyKey,
|
|
39
39
|
ctx: Context,
|
|
40
|
-
) =>
|
|
41
|
-
| void
|
|
42
|
-
| Promise<void>
|
|
40
|
+
) =>
|
|
43
41
|
| OptionalRecord<AllowedMapParamsStrategy[StrategyKey], any>
|
|
44
|
-
| Promise<OptionalRecord<AllowedMapParamsStrategy[StrategyKey], any
|
|
42
|
+
| Promise<OptionalRecord<AllowedMapParamsStrategy[StrategyKey], any>>
|
|
43
|
+
| Promise<void>
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
|
45
|
+
| void;
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
export function createAuthController<
|
|
@@ -72,7 +73,7 @@ export function createAuthController<
|
|
|
72
73
|
* The user must already be connected
|
|
73
74
|
*/
|
|
74
75
|
async addScope(ctx: Context): Promise<void> {
|
|
75
|
-
if (!ctx.state.
|
|
76
|
+
if (!ctx.state.loggedInUser) {
|
|
76
77
|
await ctx.redirectTo(homeRouterKey);
|
|
77
78
|
return;
|
|
78
79
|
}
|
|
@@ -89,17 +90,17 @@ export function createAuthController<
|
|
|
89
90
|
const strategy: StrategyKeys = ctx.namedParam('strategy') as StrategyKeys;
|
|
90
91
|
ctx.assert(strategy);
|
|
91
92
|
|
|
92
|
-
const
|
|
93
|
+
const loggedInUser = await authenticationService.accessResponse(
|
|
93
94
|
ctx,
|
|
94
95
|
strategy,
|
|
95
|
-
ctx.state.
|
|
96
|
+
!!ctx.state.loggedInUser,
|
|
96
97
|
{
|
|
97
98
|
afterLoginSuccess: authHooks.afterLoginSuccess,
|
|
98
99
|
afterScopeUpdate: authHooks.afterScopeUpdate,
|
|
99
100
|
},
|
|
100
101
|
);
|
|
101
102
|
const keyPath = usersManager.store.keyPath;
|
|
102
|
-
await ctx.
|
|
103
|
+
await ctx.setLoggedIn(loggedInUser[keyPath], loggedInUser);
|
|
103
104
|
await ctx.redirectTo(homeRouterKey);
|
|
104
105
|
},
|
|
105
106
|
|
package/src/index.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
1
|
+
/* eslint-disable max-lines */
|
|
2
|
+
import type { IncomingMessage } from 'node:http';
|
|
3
|
+
import { promisify } from 'node:util';
|
|
3
4
|
import type { Context } from 'alp-node';
|
|
4
5
|
import type { ContextState, NodeApplication } from 'alp-types';
|
|
5
6
|
import jsonwebtoken from 'jsonwebtoken';
|
|
6
7
|
import { Logger } from 'nightingale-logger';
|
|
7
|
-
import type { User, UserSanitized } from '../types.d';
|
|
8
8
|
import type MongoUsersManager from './MongoUsersManager';
|
|
9
9
|
import type {
|
|
10
10
|
AuthController as AuthControllerType,
|
|
@@ -18,8 +18,13 @@ import { AuthenticationService } from './services/authentification/Authenticatio
|
|
|
18
18
|
import type { AllowedStrategyKeys } from './services/authentification/types';
|
|
19
19
|
import UserAccountsService from './services/user/UserAccountsService';
|
|
20
20
|
import type { AccountService } from './services/user/types';
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
21
|
+
import type { User, UserSanitized } from './types';
|
|
22
|
+
import {
|
|
23
|
+
getTokenFromRequest,
|
|
24
|
+
COOKIE_NAME_TOKEN,
|
|
25
|
+
COOKIE_NAME_STATE,
|
|
26
|
+
} from './utils/cookies';
|
|
27
|
+
import { createFindLoggedInUser } from './utils/createFindLoggedInUser';
|
|
23
28
|
|
|
24
29
|
export { default as MongoUsersManager } from './MongoUsersManager';
|
|
25
30
|
export { default as UserAccountGoogleService } from './services/user/UserAccountGoogleService';
|
|
@@ -28,25 +33,30 @@ export { authSocketIO } from './authSocketIO';
|
|
|
28
33
|
export { createAuthApolloContext } from './authApolloContext';
|
|
29
34
|
export { STATUSES } from './services/user/UserAccountsService';
|
|
30
35
|
|
|
36
|
+
export * from './types';
|
|
37
|
+
|
|
31
38
|
declare module 'alp-types' {
|
|
32
39
|
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
33
40
|
interface ContextState {
|
|
34
|
-
|
|
35
|
-
|
|
41
|
+
loggedInUserId:
|
|
42
|
+
| NonNullable<ContextState['loggedInUser']>['_id']
|
|
43
|
+
| null
|
|
44
|
+
| undefined;
|
|
45
|
+
loggedInUser: User | null | undefined;
|
|
36
46
|
}
|
|
37
47
|
|
|
38
48
|
interface ContextSanitizedState {
|
|
39
|
-
|
|
40
|
-
| NonNullable<ContextSanitizedState['
|
|
49
|
+
loggedInUserId:
|
|
50
|
+
| NonNullable<ContextSanitizedState['loggedInUser']>['_id']
|
|
41
51
|
| null
|
|
42
52
|
| undefined;
|
|
43
|
-
|
|
53
|
+
loggedInUser: UserSanitized | null | undefined;
|
|
44
54
|
}
|
|
45
55
|
|
|
46
56
|
interface BaseContext {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
57
|
+
setLoggedIn: (
|
|
58
|
+
loggedInUserId: NonNullable<ContextState['loggedInUserId']>,
|
|
59
|
+
loggedInUser: NonNullable<ContextState['loggedInUser']>,
|
|
50
60
|
) => Promise<void>;
|
|
51
61
|
logout: () => void;
|
|
52
62
|
}
|
|
@@ -102,21 +112,21 @@ export default function init<
|
|
|
102
112
|
authHooks,
|
|
103
113
|
});
|
|
104
114
|
|
|
105
|
-
app.context.
|
|
115
|
+
app.context.setLoggedIn = async function (
|
|
106
116
|
this: Context,
|
|
107
|
-
|
|
108
|
-
|
|
117
|
+
loggedInUserId: NonNullable<ContextState['loggedInUser']>['_id'],
|
|
118
|
+
loggedInUser: NonNullable<ContextState['loggedInUser']>,
|
|
109
119
|
): Promise<void> {
|
|
110
|
-
logger.debug('
|
|
111
|
-
if (!
|
|
112
|
-
throw new Error('Illegal value for
|
|
120
|
+
logger.debug('setLoggedIn', { loggedInUser });
|
|
121
|
+
if (!loggedInUserId) {
|
|
122
|
+
throw new Error('Illegal value for setLoggedIn');
|
|
113
123
|
}
|
|
114
124
|
|
|
115
|
-
this.state.
|
|
116
|
-
this.state.
|
|
125
|
+
this.state.loggedInUserId = loggedInUserId;
|
|
126
|
+
this.state.loggedInUser = loggedInUser;
|
|
117
127
|
|
|
118
128
|
const token = await signPromisified(
|
|
119
|
-
{
|
|
129
|
+
{ loggedInUserId, time: Date.now() },
|
|
120
130
|
this.config
|
|
121
131
|
.get<Map<string, unknown>>('authentication')
|
|
122
132
|
.get('secretKey'),
|
|
@@ -127,20 +137,36 @@ export default function init<
|
|
|
127
137
|
},
|
|
128
138
|
);
|
|
129
139
|
|
|
140
|
+
const calcExpiresTime = (): number => {
|
|
141
|
+
const date = new Date();
|
|
142
|
+
date.setDate(date.getDate() + 30);
|
|
143
|
+
return date.getTime();
|
|
144
|
+
};
|
|
145
|
+
|
|
130
146
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
131
|
-
this.cookies.set(
|
|
147
|
+
this.cookies.set(COOKIE_NAME_TOKEN, token, {
|
|
132
148
|
httpOnly: true,
|
|
133
149
|
secure: this.config.get('allowHttps'),
|
|
134
150
|
});
|
|
151
|
+
|
|
152
|
+
this.cookies.set(
|
|
153
|
+
COOKIE_NAME_STATE,
|
|
154
|
+
JSON.stringify({ loggedInUserId, expiresIn: calcExpiresTime() }),
|
|
155
|
+
{
|
|
156
|
+
httpOnly: false,
|
|
157
|
+
secure: this.config.get('allowHttps'),
|
|
158
|
+
},
|
|
159
|
+
);
|
|
135
160
|
};
|
|
136
161
|
|
|
137
162
|
app.context.logout = function (this: Context): void {
|
|
138
|
-
delete this.state.
|
|
139
|
-
delete this.state.
|
|
140
|
-
this.cookies.set(
|
|
163
|
+
delete this.state.loggedInUserId;
|
|
164
|
+
delete this.state.loggedInUser;
|
|
165
|
+
this.cookies.set(COOKIE_NAME_TOKEN, '', { expires: new Date(1) });
|
|
166
|
+
this.cookies.set(COOKIE_NAME_STATE, '', { expires: new Date(1) });
|
|
141
167
|
};
|
|
142
168
|
|
|
143
|
-
const
|
|
169
|
+
const findLoggedInUser = createFindLoggedInUser(
|
|
144
170
|
app.config
|
|
145
171
|
.get<Map<string, unknown>>('authentication')
|
|
146
172
|
.get('secretKey') as string,
|
|
@@ -150,49 +176,51 @@ export default function init<
|
|
|
150
176
|
|
|
151
177
|
return {
|
|
152
178
|
routes: createRoutes(controller),
|
|
153
|
-
|
|
154
|
-
getConnectedAndUserFromRequest: (
|
|
179
|
+
findLoggedInUserFromRequest: (
|
|
155
180
|
req: IncomingMessage,
|
|
156
|
-
): ReturnType<typeof
|
|
181
|
+
): ReturnType<typeof findLoggedInUser> => {
|
|
157
182
|
const token = getTokenFromRequest(req);
|
|
158
|
-
return
|
|
183
|
+
return findLoggedInUser(
|
|
159
184
|
jwtAudience || req.headers['user-agent'],
|
|
160
185
|
token,
|
|
161
186
|
);
|
|
162
187
|
},
|
|
163
|
-
|
|
164
|
-
|
|
188
|
+
findLoggedInUser,
|
|
165
189
|
middleware: async <T>(
|
|
166
190
|
ctx: Context,
|
|
167
|
-
next: () => T |
|
|
191
|
+
next: () => Promise<T> | T,
|
|
168
192
|
): Promise<T> => {
|
|
169
|
-
const token = ctx.cookies.get(
|
|
193
|
+
const token = ctx.cookies.get(COOKIE_NAME_TOKEN);
|
|
170
194
|
const userAgent = ctx.request.headers['user-agent'];
|
|
171
195
|
logger.debug('middleware', { token });
|
|
172
196
|
|
|
173
197
|
const setState = (
|
|
174
|
-
|
|
175
|
-
|
|
198
|
+
loggedInUserId: U['_id'] | null | undefined,
|
|
199
|
+
loggedInUser: U | null | undefined,
|
|
176
200
|
): void => {
|
|
177
|
-
ctx.state.
|
|
178
|
-
ctx.state.user =
|
|
179
|
-
ctx.sanitizedState.
|
|
180
|
-
ctx.sanitizedState.
|
|
201
|
+
ctx.state.loggedInUserId = loggedInUserId;
|
|
202
|
+
ctx.state.user = loggedInUser;
|
|
203
|
+
ctx.sanitizedState.loggedInUserId = loggedInUserId;
|
|
204
|
+
ctx.sanitizedState.loggedInUser =
|
|
205
|
+
loggedInUser && usersManager.sanitize(loggedInUser);
|
|
181
206
|
};
|
|
182
207
|
|
|
183
|
-
const [
|
|
208
|
+
const [loggedInUserId, loggedInUser] = await findLoggedInUser(
|
|
184
209
|
jwtAudience || userAgent,
|
|
185
210
|
token,
|
|
186
211
|
);
|
|
187
|
-
logger.debug('middleware', {
|
|
212
|
+
logger.debug('middleware', { loggedInUserId });
|
|
188
213
|
|
|
189
|
-
if (
|
|
190
|
-
if (token)
|
|
214
|
+
if (loggedInUserId == null || loggedInUser == null) {
|
|
215
|
+
if (token) {
|
|
216
|
+
ctx.cookies.set(COOKIE_NAME_TOKEN, '', { expires: new Date(1) });
|
|
217
|
+
ctx.cookies.set(COOKIE_NAME_STATE, '', { expires: new Date(1) });
|
|
218
|
+
}
|
|
191
219
|
setState(null, null);
|
|
192
220
|
return next();
|
|
193
221
|
}
|
|
194
222
|
|
|
195
|
-
setState(
|
|
223
|
+
setState(loggedInUserId, loggedInUser);
|
|
196
224
|
return next();
|
|
197
225
|
},
|
|
198
226
|
};
|