@entity-access/server-pages 1.1.548 → 1.1.552
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/dist/ServerPages.js +3 -3
- package/dist/ServerPages.js.map +1 -1
- package/dist/core/SessionUser.d.ts +2 -3
- package/dist/core/SessionUser.d.ts.map +1 -1
- package/dist/core/SessionUser.js +4 -12
- package/dist/core/SessionUser.js.map +1 -1
- package/dist/services/{AuthenticationService.d.ts → AuthorizationService.d.ts} +9 -3
- package/dist/services/AuthorizationService.d.ts.map +1 -0
- package/dist/services/AuthorizationService.js +65 -0
- package/dist/services/AuthorizationService.js.map +1 -0
- package/dist/services/CookieService.d.ts +1 -8
- package/dist/services/CookieService.d.ts.map +1 -1
- package/dist/services/CookieService.js +82 -154
- package/dist/services/CookieService.js.map +1 -1
- package/dist/services/IAuthKey.d.ts +7 -0
- package/dist/services/IAuthKey.d.ts.map +1 -0
- package/dist/services/IAuthKey.js +2 -0
- package/dist/services/IAuthKey.js.map +1 -0
- package/dist/services/IAuthorizationCookie.d.ts +2 -4
- package/dist/services/IAuthorizationCookie.d.ts.map +1 -1
- package/dist/services/KeyProvider.d.ts +1 -0
- package/dist/services/KeyProvider.d.ts.map +1 -1
- package/dist/services/KeyProvider.js +1 -0
- package/dist/services/KeyProvider.js.map +1 -1
- package/dist/socket/SocketService.d.ts +0 -1
- package/dist/socket/SocketService.d.ts.map +1 -1
- package/dist/socket/SocketService.js +4 -18
- package/dist/socket/SocketService.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/ServerPages.ts +3 -3
- package/src/core/SessionUser.ts +5 -8
- package/src/services/AuthorizationService.ts +73 -0
- package/src/services/CookieService.ts +89 -157
- package/src/services/IAuthKey.ts +7 -0
- package/src/services/IAuthorizationCookie.ts +2 -4
- package/src/services/KeyProvider.ts +2 -0
- package/src/socket/SocketService.ts +4 -12
- package/dist/services/AuthenticationService.d.ts.map +0 -1
- package/dist/services/AuthenticationService.js +0 -40
- package/dist/services/AuthenticationService.js.map +0 -1
- package/dist/services/TokenService.d.ts +0 -31
- package/dist/services/TokenService.d.ts.map +0 -1
- package/dist/services/TokenService.js +0 -60
- package/dist/services/TokenService.js.map +0 -1
- package/dist/services/UserSessionProvider.d.ts +0 -6
- package/dist/services/UserSessionProvider.d.ts.map +0 -1
- package/dist/services/UserSessionProvider.js +0 -10
- package/dist/services/UserSessionProvider.js.map +0 -1
- package/src/services/AuthenticationService.ts +0 -44
- package/src/services/TokenService.ts +0 -81
- package/src/services/UserSessionProvider.ts +0 -16
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { RegisterSingleton, ServiceProvider } from "@entity-access/entity-access/dist/di/di.js";
|
|
2
|
+
import { SessionUser } from "../core/SessionUser.js";
|
|
3
|
+
import DateTime from "@entity-access/entity-access/dist/types/DateTime.js";
|
|
4
|
+
import type { IAuthorizationCookie } from "./IAuthorizationCookie.js";
|
|
5
|
+
import type { SerializeOptions } from "cookie";
|
|
6
|
+
import KeyProvider from "./KeyProvider.js";
|
|
7
|
+
import { privateDecrypt, publicEncrypt } from "node:crypto";
|
|
8
|
+
|
|
9
|
+
const secure = (process.env["SOCIAL_MAIL_AUTH_COOKIE_SECURE"] ?? "true") === "true";
|
|
10
|
+
|
|
11
|
+
export interface ICookie {
|
|
12
|
+
name: string,
|
|
13
|
+
value: string,
|
|
14
|
+
options?: SerializeOptions
|
|
15
|
+
}
|
|
16
|
+
@RegisterSingleton
|
|
17
|
+
export default class AuthorizationService {
|
|
18
|
+
|
|
19
|
+
authCookieName = "ec-1";
|
|
20
|
+
keyProvider: any;
|
|
21
|
+
|
|
22
|
+
async authorizeRequest(user: SessionUser, { ip, cookies }: { ip: string, cookies: Record<string, string>}) {
|
|
23
|
+
const cookie = cookies[this.authCookieName];
|
|
24
|
+
if (!cookie) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
await this.loadUserSessionFromCookie(cookie, user);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async loadUserSessionFromCookie(cookie: string, user: SessionUser) {
|
|
31
|
+
const sessionID = await this.decode(cookie);
|
|
32
|
+
user.sessionID = sessionID;
|
|
33
|
+
// load session...
|
|
34
|
+
await this.loadSession(sessionID, user);
|
|
35
|
+
(user as any).isAuthorized = true;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async loadSession(sessionID, user: SessionUser): Promise<void> {
|
|
39
|
+
user.userID = sessionID;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async setAuthCookie(user: SessionUser, authCookie: IAuthorizationCookie): Promise<ICookie> {
|
|
43
|
+
|
|
44
|
+
const maxAge = ((authCookie?.expiry ? DateTime.from(authCookie.expiry) : null) ?? DateTime.now.addDays(30)).diff(DateTime.now).totalMilliseconds;
|
|
45
|
+
const name = this.authCookieName;
|
|
46
|
+
const value = await this.encode(authCookie?.sessionID ?? authCookie?.userID ?? "0");
|
|
47
|
+
const options = {
|
|
48
|
+
secure,
|
|
49
|
+
httpOnly: true,
|
|
50
|
+
maxAge
|
|
51
|
+
};
|
|
52
|
+
return { name, value, options };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async decode(cookie: string) {
|
|
56
|
+
this.keyProvider ??= ServiceProvider.resolve(this, KeyProvider, true) ?? new KeyProvider();
|
|
57
|
+
const keys = await this.keyProvider.getKeys();
|
|
58
|
+
const[id, value] = cookie.split(":")
|
|
59
|
+
for (const key of keys) {
|
|
60
|
+
if(key.id == id) {
|
|
61
|
+
return privateDecrypt(key.privateKey, value) as any as number;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
throw new Error("no suitable key found");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async encode(sessionID) {
|
|
68
|
+
this.keyProvider ??= ServiceProvider.resolve(this, KeyProvider, true) ?? new KeyProvider();
|
|
69
|
+
const [key] = await this.keyProvider.getKeys();
|
|
70
|
+
return key.id + ":" + publicEncrypt(key.publicKey, sessionID.toString()).toString("base64url");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
}
|
|
@@ -1,157 +1,89 @@
|
|
|
1
|
-
import Inject, { RegisterScoped, RegisterSingleton, ServiceProvider } from "@entity-access/entity-access/dist/di/di.js";
|
|
2
|
-
import TokenService, { IAuthCookie } from "./TokenService.js";
|
|
3
|
-
import TimedCache from "@entity-access/entity-access/dist/common/cache/TimedCache.js";
|
|
4
|
-
import { BaseDriver } from "@entity-access/entity-access/dist/drivers/base/BaseDriver.js";
|
|
5
|
-
import cluster from "cluster";
|
|
6
|
-
import { SessionUser } from "../core/SessionUser.js";
|
|
7
|
-
import UserSessionProvider from "./UserSessionProvider.js";
|
|
8
|
-
import { WrappedResponse } from "../core/Wrapped.js";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (cookie) {
|
|
91
|
-
const userInfo = await this.getVerifiedUser(cookie);
|
|
92
|
-
if (userInfo?.sessionID) {
|
|
93
|
-
(user as any).sessionID = userInfo.sessionID;
|
|
94
|
-
}
|
|
95
|
-
if (userInfo?.userID) {
|
|
96
|
-
user[tagForCache] = userInfo;
|
|
97
|
-
for (const key in userInfo) {
|
|
98
|
-
if (Object.prototype.hasOwnProperty.call(userInfo, key)) {
|
|
99
|
-
const element = userInfo[key];
|
|
100
|
-
user[key] = element;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
return user;
|
|
106
|
-
} catch (error) {
|
|
107
|
-
console.error(error);
|
|
108
|
-
return user;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
private getVerifiedUser(cookie: string): Promise<Partial<SessionUser>> {
|
|
113
|
-
|
|
114
|
-
return sessionCache.getOrCreateAsync(cookie, async (k) => {
|
|
115
|
-
|
|
116
|
-
const parsedCookie = JSON.parse(cookie) as IAuthCookie;
|
|
117
|
-
if (!parsedCookie.id) {
|
|
118
|
-
return {};
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (typeof parsedCookie.expiry === "string") {
|
|
122
|
-
parsedCookie.expiry = new Date(parsedCookie.expiry);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if(!await this.tokenService.verifyContent(parsedCookie, false)) {
|
|
126
|
-
console.warn(`Cookie Verification failed for ${parsedCookie.id}: ${parsedCookie.userID}`);
|
|
127
|
-
return {};
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (!parsedCookie.active) {
|
|
131
|
-
return {
|
|
132
|
-
sessionID: parsedCookie.id
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const r = await this.createUserInfo(cookie, parsedCookie);
|
|
137
|
-
return r;
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
private async createUserInfo(cookie: string, parsedCookie: IAuthCookie) {
|
|
142
|
-
const usp = ServiceProvider.resolve(this, UserSessionProvider, true) ?? new UserSessionProvider();
|
|
143
|
-
const r = await usp.getUserSession(parsedCookie);
|
|
144
|
-
if (r === null) {
|
|
145
|
-
console.warn(`Failed to get userSession for ${parsedCookie.id}: ${parsedCookie.userID}`);
|
|
146
|
-
return {};
|
|
147
|
-
}
|
|
148
|
-
if (r.expiry.getTime() < Date.now() || r.invalid) {
|
|
149
|
-
console.warn(`Session expired for ${parsedCookie.id}: ${parsedCookie.userID}`);
|
|
150
|
-
return {};
|
|
151
|
-
}
|
|
152
|
-
cacheFR.register(r, r.userID);
|
|
153
|
-
userCookies.set(r.userID, cookie);
|
|
154
|
-
return r;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
}
|
|
1
|
+
// import Inject, { RegisterScoped, RegisterSingleton, ServiceProvider } from "@entity-access/entity-access/dist/di/di.js";
|
|
2
|
+
// import TokenService, { IAuthCookie } from "./TokenService.js";
|
|
3
|
+
// import TimedCache from "@entity-access/entity-access/dist/common/cache/TimedCache.js";
|
|
4
|
+
// import { BaseDriver } from "@entity-access/entity-access/dist/drivers/base/BaseDriver.js";
|
|
5
|
+
// import cluster from "cluster";
|
|
6
|
+
// import { SessionUser } from "../core/SessionUser.js";
|
|
7
|
+
// import UserSessionProvider from "./UserSessionProvider.js";
|
|
8
|
+
// import { WrappedResponse } from "../core/Wrapped.js";
|
|
9
|
+
|
|
10
|
+
// let cookieName = null;
|
|
11
|
+
|
|
12
|
+
// @RegisterScoped
|
|
13
|
+
// export default class CookieService {
|
|
14
|
+
|
|
15
|
+
// @Inject
|
|
16
|
+
// private tokenService: TokenService;
|
|
17
|
+
|
|
18
|
+
// async createSessionUserFromCookie(cookie: string, ip: string) {
|
|
19
|
+
// const user = ServiceProvider.resolve(this, SessionUser);
|
|
20
|
+
// const ua = user as any;
|
|
21
|
+
// ua.isAuthorized = true;
|
|
22
|
+
// const value = null;
|
|
23
|
+
// const userID = { value, enumerable: true, writable: true};
|
|
24
|
+
// const sessionID = userID;
|
|
25
|
+
// const userName = userID;
|
|
26
|
+
// const expiry = userID;
|
|
27
|
+
// Object.defineProperties(ua, {
|
|
28
|
+
// authorize: {
|
|
29
|
+
// value: () => null
|
|
30
|
+
// },
|
|
31
|
+
// sessionID,
|
|
32
|
+
// userID,
|
|
33
|
+
// userName,
|
|
34
|
+
// expiry,
|
|
35
|
+
// roles: {
|
|
36
|
+
// value: [],
|
|
37
|
+
// enumerable: true,
|
|
38
|
+
// writable: true
|
|
39
|
+
// }
|
|
40
|
+
// });
|
|
41
|
+
// try {
|
|
42
|
+
// user.ipAddress = ip;
|
|
43
|
+
// if (cookie) {
|
|
44
|
+
// const userInfo = await this.getVerifiedUser(cookie);
|
|
45
|
+
// if (userInfo?.sessionID) {
|
|
46
|
+
// (user as any).sessionID = userInfo.sessionID;
|
|
47
|
+
// }
|
|
48
|
+
// if (userInfo?.userID) {
|
|
49
|
+
// for (const key in userInfo) {
|
|
50
|
+
// if (Object.prototype.hasOwnProperty.call(userInfo, key)) {
|
|
51
|
+
// const element = userInfo[key];
|
|
52
|
+
// user[key] = element;
|
|
53
|
+
// }
|
|
54
|
+
// }
|
|
55
|
+
// }
|
|
56
|
+
// }
|
|
57
|
+
// return user;
|
|
58
|
+
// } catch (error) {
|
|
59
|
+
// console.error(error);
|
|
60
|
+
// return user;
|
|
61
|
+
// }
|
|
62
|
+
// }
|
|
63
|
+
|
|
64
|
+
// private getVerifiedUser(cookie: string): Promise<Partial<SessionUser>> {
|
|
65
|
+
|
|
66
|
+
// return sessionCache.getOrCreateAsync(cookie, async (k) => {
|
|
67
|
+
// const parsedCookie = await this.tokenService.decryptContent(cookie);
|
|
68
|
+
// const r = await this.createUserInfo(cookie, parsedCookie);
|
|
69
|
+
// return r;
|
|
70
|
+
// });
|
|
71
|
+
// }
|
|
72
|
+
|
|
73
|
+
// private async createUserInfo(cookie: string, parsedCookie: IAuthCookie) {
|
|
74
|
+
// const usp = ServiceProvider.resolve(this, UserSessionProvider, true) ?? new UserSessionProvider();
|
|
75
|
+
// const r = await usp.getUserSession(parsedCookie);
|
|
76
|
+
// if (r === null) {
|
|
77
|
+
// console.warn(`Failed to get userSession for ${parsedCookie.id}: ${parsedCookie.userID}`);
|
|
78
|
+
// return {};
|
|
79
|
+
// }
|
|
80
|
+
// if (r.expiry.getTime() < Date.now() || r.invalid) {
|
|
81
|
+
// console.warn(`Session expired for ${parsedCookie.id}: ${parsedCookie.userID}`);
|
|
82
|
+
// return {};
|
|
83
|
+
// }
|
|
84
|
+
// cacheFR.register(r, r.userID);
|
|
85
|
+
// userCookies.set(r.userID, cookie);
|
|
86
|
+
// return r;
|
|
87
|
+
// }
|
|
88
|
+
|
|
89
|
+
// }
|
|
@@ -5,6 +5,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
5
5
|
import { join } from "node:path";
|
|
6
6
|
|
|
7
7
|
export interface IAuthKey {
|
|
8
|
+
id: number,
|
|
8
9
|
publicKey: string,
|
|
9
10
|
privateKey: string,
|
|
10
11
|
expires: DateTime
|
|
@@ -51,6 +52,7 @@ export default class KeyProvider {
|
|
|
51
52
|
},
|
|
52
53
|
(error, publicKey, privateKey) => {
|
|
53
54
|
resolve({
|
|
55
|
+
id: 1,
|
|
54
56
|
publicKey,
|
|
55
57
|
privateKey,
|
|
56
58
|
expires
|
|
@@ -1,23 +1,15 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
|
-
import
|
|
3
|
-
import { Http2SecureServer } from "http2";
|
|
4
|
-
import { Server as HttpServer } from "http";
|
|
5
|
-
import { Server as HttpsServer } from "https";
|
|
2
|
+
import { ServiceProvider, injectServiceKeysSymbol } from "@entity-access/entity-access/dist/di/di.js";
|
|
6
3
|
import { parse } from "cookie";
|
|
7
4
|
|
|
8
5
|
import { Server, Socket } from "socket.io";
|
|
9
|
-
import CookieService from "../services/CookieService.js";
|
|
10
|
-
import TokenService from "../services/TokenService.js";
|
|
11
6
|
import SocketNamespace, { SocketNamespaceClient } from "./SocketNamespace.js";
|
|
12
7
|
import { camelToChain } from "../core/camelToChain.js";
|
|
13
|
-
import
|
|
8
|
+
import AuthorizationService from "../services/AuthorizationService.js";
|
|
14
9
|
import { SessionUser } from "../core/SessionUser.js";
|
|
15
10
|
|
|
16
11
|
export default abstract class SocketService {
|
|
17
12
|
|
|
18
|
-
@Inject
|
|
19
|
-
private tokenService: TokenService;
|
|
20
|
-
|
|
21
13
|
protected server: Server;
|
|
22
14
|
|
|
23
15
|
constructor() {
|
|
@@ -70,11 +62,11 @@ export default abstract class SocketService {
|
|
|
70
62
|
socket.onAny(async (methodName, ... args: any[]) => {
|
|
71
63
|
const cookies = parse(socket.request.headers.cookie);
|
|
72
64
|
const scope = ServiceProvider.createScope(this);
|
|
73
|
-
const authService = ServiceProvider.resolve(this,
|
|
65
|
+
const authService = ServiceProvider.resolve(this, AuthorizationService);
|
|
74
66
|
try {
|
|
75
67
|
const user = scope.resolve(SessionUser);
|
|
76
68
|
const ip = socket.conn.remoteAddress;
|
|
77
|
-
await authService.
|
|
69
|
+
await authService.authorizeRequest(user, { ip, cookies });
|
|
78
70
|
scope.add(Socket, socket);
|
|
79
71
|
const clientClass = sns.clientClass ?? SocketNamespaceClient;
|
|
80
72
|
let c = scope.resolve(clientClass, true);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AuthenticationService.d.ts","sourceRoot":"","sources":["../../src/services/AuthenticationService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAIrD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAI/C,MAAM,WAAW,OAAO;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,gBAAgB,CAAA;CAC7B;AAED,MAAM,CAAC,OAAO,OAAO,qBAAqB;IAEhC,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAC;IAS5F,aAAa,CAAC,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC;CAgB7F"}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
};
|
|
7
|
-
import { RegisterSingleton, ServiceProvider } from "@entity-access/entity-access/dist/di/di.js";
|
|
8
|
-
import CookieService from "./CookieService.js";
|
|
9
|
-
import TokenService from "./TokenService.js";
|
|
10
|
-
import DateTime from "@entity-access/entity-access/dist/types/DateTime.js";
|
|
11
|
-
const secure = (process.env["SOCIAL_MAIL_AUTH_COOKIE_SECURE"] ?? "true") === "true";
|
|
12
|
-
let AuthenticationService = class AuthenticationService {
|
|
13
|
-
async authorize(user, { ip, cookies }) {
|
|
14
|
-
const scope = ServiceProvider.from(user);
|
|
15
|
-
const cookieService = scope.resolve(CookieService);
|
|
16
|
-
const tokenService = scope.resolve(TokenService);
|
|
17
|
-
const cookie = cookies[tokenService.authCookieName];
|
|
18
|
-
await cookieService.createSessionUserFromCookie(cookie, ip);
|
|
19
|
-
user.isAuthorized = true;
|
|
20
|
-
}
|
|
21
|
-
async setAuthCookie(user, authCookie) {
|
|
22
|
-
const scope = ServiceProvider.from(user);
|
|
23
|
-
const tokenService = scope.resolve(TokenService);
|
|
24
|
-
const cookie = await tokenService.getAuthToken(authCookie);
|
|
25
|
-
const maxAge = ((authCookie?.expiry ? DateTime.from(authCookie.expiry) : null) ?? DateTime.now.addDays(30)).diff(DateTime.now).totalMilliseconds;
|
|
26
|
-
const name = cookie.cookieName;
|
|
27
|
-
const value = cookie.cookie;
|
|
28
|
-
const options = {
|
|
29
|
-
secure,
|
|
30
|
-
httpOnly: true,
|
|
31
|
-
maxAge
|
|
32
|
-
};
|
|
33
|
-
return { name, value, options };
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
AuthenticationService = __decorate([
|
|
37
|
-
RegisterSingleton
|
|
38
|
-
], AuthenticationService);
|
|
39
|
-
export default AuthenticationService;
|
|
40
|
-
//# sourceMappingURL=AuthenticationService.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AuthenticationService.js","sourceRoot":"","sources":["../../src/services/AuthenticationService.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAC;AAEhG,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAC/C,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAC7C,OAAO,QAAQ,MAAM,qDAAqD,CAAC;AAI3E,MAAM,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,IAAI,MAAM,CAAC,KAAK,MAAM,CAAC;AAQrE,IAAM,qBAAqB,GAA3B,MAAM,qBAAqB;IAEtC,KAAK,CAAC,SAAS,CAAC,IAAiB,EAAE,EAAE,EAAE,EAAE,OAAO,EAAkD;QAC9F,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,aAAa,GAAG,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;QACnD,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;QACpD,MAAM,aAAa,CAAC,2BAA2B,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC3D,IAAY,CAAC,YAAY,GAAG,IAAI,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,IAAiB,EAAE,UAAgC;QAEnE,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QAC3D,MAAM,MAAM,GAAG,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAE,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAC;QAClJ,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC;QAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,MAAM,OAAO,GAAG;YACZ,MAAM;YACN,QAAQ,EAAE,IAAI;YACd,MAAM;SACT,CAAC;QACF,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IACpC,CAAC;CAEJ,CAAA;AA3BoB,qBAAqB;IADzC,iBAAiB;GACG,qBAAqB,CA2BzC;eA3BoB,qBAAqB"}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import DateTime from "@entity-access/entity-access/dist/types/DateTime.js";
|
|
2
|
-
export interface IAuthCookie {
|
|
3
|
-
id: number;
|
|
4
|
-
userID: number;
|
|
5
|
-
expiry: Date;
|
|
6
|
-
sign: string;
|
|
7
|
-
version: string;
|
|
8
|
-
active?: boolean;
|
|
9
|
-
}
|
|
10
|
-
export interface IAuthKey {
|
|
11
|
-
publicKey: string;
|
|
12
|
-
privateKey: string;
|
|
13
|
-
expires: DateTime;
|
|
14
|
-
}
|
|
15
|
-
export type ISignedContent<T> = T & {
|
|
16
|
-
sign: string;
|
|
17
|
-
};
|
|
18
|
-
export default class TokenService {
|
|
19
|
-
authCookieName: string;
|
|
20
|
-
shareCookieName: string;
|
|
21
|
-
private keyProvider;
|
|
22
|
-
getAuthToken(authCookie: Omit<IAuthCookie, "sign">): Promise<{
|
|
23
|
-
cookieName: string;
|
|
24
|
-
cookie: string;
|
|
25
|
-
}>;
|
|
26
|
-
signContent<T>(content: T): Promise<ISignedContent<T>>;
|
|
27
|
-
verifyContent<T>(content: ISignedContent<T>, fail?: boolean): Promise<boolean>;
|
|
28
|
-
verify(content: string | Buffer, signature: string, key: IAuthKey, fail?: boolean): boolean;
|
|
29
|
-
private sign;
|
|
30
|
-
}
|
|
31
|
-
//# sourceMappingURL=TokenService.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TokenService.d.ts","sourceRoot":"","sources":["../../src/services/TokenService.ts"],"names":[],"mappings":"AACA,OAAO,QAAQ,MAAM,qDAAqD,CAAC;AAM3E,MAAM,WAAW,WAAW;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,IAAI,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,QAAQ;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,QAAQ,CAAA;CACpB;AAED,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;CAChB,CAAC;AAGF,MAAM,CAAC,OAAO,OAAO,YAAY;IAEtB,cAAc,SAAW;IAEzB,eAAe,SAAY;IAElC,OAAO,CAAC,WAAW,CAAc;IAEpB,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,CAAC;IAKnG,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IAOtD,aAAa,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,IAAI,UAAO;IAc9D,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,UAAO;IAYrF,OAAO,CAAC,IAAI;CAOf"}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
};
|
|
7
|
-
import { RegisterSingleton, ServiceProvider } from "@entity-access/entity-access/dist/di/di.js";
|
|
8
|
-
import { createSign, createVerify } from "node:crypto";
|
|
9
|
-
import KeyProvider from "./KeyProvider.js";
|
|
10
|
-
let TokenService = class TokenService {
|
|
11
|
-
constructor() {
|
|
12
|
-
this.authCookieName = "ea-c1";
|
|
13
|
-
this.shareCookieName = "ea-ca1";
|
|
14
|
-
}
|
|
15
|
-
async getAuthToken(authCookie) {
|
|
16
|
-
const cookie = await this.signContent(authCookie);
|
|
17
|
-
return { cookieName: this.authCookieName, cookie: JSON.stringify(cookie) };
|
|
18
|
-
}
|
|
19
|
-
async signContent(content) {
|
|
20
|
-
this.keyProvider ??= ServiceProvider.resolve(this, KeyProvider, true) ?? new KeyProvider();
|
|
21
|
-
const [key] = await this.keyProvider.getKeys();
|
|
22
|
-
const sign = this.sign(JSON.stringify(content), key);
|
|
23
|
-
return { ...content, sign };
|
|
24
|
-
}
|
|
25
|
-
async verifyContent(content, fail = true) {
|
|
26
|
-
this.keyProvider ??= ServiceProvider.resolve(this, KeyProvider, true) ?? new KeyProvider();
|
|
27
|
-
const { sign, ...c } = content;
|
|
28
|
-
const keys = await this.keyProvider.getKeys();
|
|
29
|
-
for (const iterator of keys) {
|
|
30
|
-
if (this.verify(JSON.stringify(c), sign, iterator, false)) {
|
|
31
|
-
return true;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
if (fail) {
|
|
35
|
-
throw new Error("Signature verification failed");
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
verify(content, signature, key, fail = true) {
|
|
39
|
-
const verify = createVerify("SHA256");
|
|
40
|
-
verify.write(content);
|
|
41
|
-
verify.end();
|
|
42
|
-
if (verify.verify(key.publicKey, signature, "hex")) {
|
|
43
|
-
return true;
|
|
44
|
-
}
|
|
45
|
-
if (fail) {
|
|
46
|
-
throw new Error("Invalid signature");
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
sign(content, key) {
|
|
50
|
-
const sign = createSign("SHA256");
|
|
51
|
-
sign.write(content);
|
|
52
|
-
sign.end();
|
|
53
|
-
return sign.sign(key.privateKey, "hex");
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
TokenService = __decorate([
|
|
57
|
-
RegisterSingleton
|
|
58
|
-
], TokenService);
|
|
59
|
-
export default TokenService;
|
|
60
|
-
//# sourceMappingURL=TokenService.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TokenService.js","sourceRoot":"","sources":["../../src/services/TokenService.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { SessionUser } from "../core/SessionUser.js";
|
|
2
|
-
import { IAuthCookie } from "./TokenService.js";
|
|
3
|
-
export default class UserSessionProvider {
|
|
4
|
-
getUserSession({ userID, id: sessionID, expiry }: IAuthCookie): Promise<Partial<SessionUser>>;
|
|
5
|
-
}
|
|
6
|
-
//# sourceMappingURL=UserSessionProvider.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"UserSessionProvider.d.ts","sourceRoot":"","sources":["../../src/services/UserSessionProvider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,CAAC,OAAO,OAAO,mBAAmB;IAE9B,cAAc,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;CAQrG"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"UserSessionProvider.js","sourceRoot":"","sources":["../../src/services/UserSessionProvider.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,OAAO,OAAO,mBAAmB;IAEpC,KAAK,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAc;QAC9D,OAAO;YACH,SAAS;YACT,MAAM;YACN,MAAM;SACT,CAAA;IACL,CAAC;CAEJ"}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { RegisterSingleton, ServiceProvider } from "@entity-access/entity-access/dist/di/di.js";
|
|
2
|
-
import { SessionUser } from "../core/SessionUser.js";
|
|
3
|
-
import CookieService from "./CookieService.js";
|
|
4
|
-
import TokenService from "./TokenService.js";
|
|
5
|
-
import DateTime from "@entity-access/entity-access/dist/types/DateTime.js";
|
|
6
|
-
import type { IAuthorizationCookie } from "./IAuthorizationCookie.js";
|
|
7
|
-
import type { SerializeOptions } from "cookie";
|
|
8
|
-
|
|
9
|
-
const secure = (process.env["SOCIAL_MAIL_AUTH_COOKIE_SECURE"] ?? "true") === "true";
|
|
10
|
-
|
|
11
|
-
export interface ICookie {
|
|
12
|
-
name: string,
|
|
13
|
-
value: string,
|
|
14
|
-
options?: SerializeOptions
|
|
15
|
-
}
|
|
16
|
-
@RegisterSingleton
|
|
17
|
-
export default class AuthenticationService {
|
|
18
|
-
|
|
19
|
-
async authorize(user: SessionUser, { ip, cookies }: { ip: string, cookies: Record<string, string>}) {
|
|
20
|
-
const scope = ServiceProvider.from(user);
|
|
21
|
-
const cookieService = scope.resolve(CookieService);
|
|
22
|
-
const tokenService = scope.resolve(TokenService);
|
|
23
|
-
const cookie = cookies[tokenService.authCookieName];
|
|
24
|
-
await cookieService.createSessionUserFromCookie(cookie, ip);
|
|
25
|
-
(user as any).isAuthorized = true;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async setAuthCookie(user: SessionUser, authCookie: IAuthorizationCookie): Promise<ICookie> {
|
|
29
|
-
|
|
30
|
-
const scope = ServiceProvider.from(user);
|
|
31
|
-
const tokenService = scope.resolve(TokenService);
|
|
32
|
-
const cookie = await tokenService.getAuthToken(authCookie);
|
|
33
|
-
const maxAge = ((authCookie?.expiry ? DateTime.from(authCookie.expiry) : null) ?? DateTime.now.addDays(30)).diff(DateTime.now).totalMilliseconds;
|
|
34
|
-
const name = cookie.cookieName;
|
|
35
|
-
const value = cookie.cookie;
|
|
36
|
-
const options = {
|
|
37
|
-
secure,
|
|
38
|
-
httpOnly: true,
|
|
39
|
-
maxAge
|
|
40
|
-
};
|
|
41
|
-
return { name, value, options };
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
}
|