dce-reactkit 3.12.1-beta-cross-server.2 → 3.12.1-beta-cross-server.3
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/cjs/index.js +8028 -190
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/helpers/dataSigner.d.ts +13 -11
- package/dist/cjs/types/helpers/visitEndpointOnAnotherServer/index.d.ts +0 -6
- package/dist/cjs/types/types/ReactKitErrorCode.d.ts +13 -11
- package/dist/esm/index.js +8027 -189
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/helpers/dataSigner.d.ts +13 -11
- package/dist/esm/types/helpers/visitEndpointOnAnotherServer/index.d.ts +0 -6
- package/dist/esm/types/types/ReactKitErrorCode.d.ts +13 -11
- package/dist/index.d.ts +13 -17
- package/genEncodedSecret.ts +67 -11
- package/package.json +3 -2
- package/rollup.config.js +2 -0
- package/src/helpers/dataSigner.ts +221 -113
- package/src/helpers/genRouteHandler.ts +27 -24
- package/src/helpers/visitEndpointOnAnotherServer/index.ts +84 -26
- package/src/types/ReactKitErrorCode.tsx +13 -11
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
// Import crypto
|
|
2
|
-
import { createHash } from 'crypto';
|
|
3
|
-
|
|
4
|
-
// Import jwt
|
|
5
|
-
import jwt from 'jwt-simple';
|
|
6
|
-
|
|
7
1
|
// Import shared helpers
|
|
2
|
+
// eslint-disable-next-line import/no-cycle
|
|
8
3
|
import { internalGetCrossServerCredentialCollection } from '../server/initServer';
|
|
9
4
|
|
|
10
5
|
// Import shared types
|
|
@@ -16,57 +11,163 @@ import CrossServerCredential from '../types/CrossServerCredential';
|
|
|
16
11
|
import MINUTE_IN_MS from '../constants/MINUTE_IN_MS';
|
|
17
12
|
|
|
18
13
|
/*------------------------------------------------------------------------*/
|
|
19
|
-
/*
|
|
14
|
+
/* --------------------------- Dynamic Imports -------------------------- */
|
|
20
15
|
/*------------------------------------------------------------------------*/
|
|
21
16
|
|
|
22
17
|
/**
|
|
23
|
-
*
|
|
18
|
+
* Get a copy of the oauth lib
|
|
24
19
|
* @author Gabe Abrams
|
|
25
|
-
* @
|
|
26
|
-
* @return the secret
|
|
20
|
+
* @return the oauth lib
|
|
27
21
|
*/
|
|
28
|
-
const
|
|
29
|
-
// Get the
|
|
30
|
-
|
|
31
|
-
|
|
22
|
+
const getOauthLib = async () => {
|
|
23
|
+
// Get the oauth signing library (included with caccl)
|
|
24
|
+
// Ignore because this is assumed to be included with caccl
|
|
25
|
+
try {
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
28
|
+
const oauth = await import('oauth-signature');
|
|
29
|
+
return oauth;
|
|
30
|
+
} catch (err) {
|
|
32
31
|
throw new ErrorWithCode(
|
|
33
|
-
'
|
|
34
|
-
ReactKitErrorCode.
|
|
32
|
+
'Could not sign a cross-server request because we could not load the oauth library. Please make sure this app has caccl as one of its dependencies.',
|
|
33
|
+
ReactKitErrorCode.NoOauthLib,
|
|
35
34
|
);
|
|
36
35
|
}
|
|
36
|
+
};
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Get a copy of the crypto lib
|
|
40
|
+
* @author Gabe Abrams
|
|
41
|
+
* @return the crypto lib
|
|
42
|
+
*/
|
|
43
|
+
const getCryptoLib = async () => {
|
|
44
|
+
// Get the crypto library (included on the server)
|
|
45
|
+
// Ignore because this is assumed to be included with typescript
|
|
46
|
+
// @ts-ignore
|
|
47
|
+
try {
|
|
48
|
+
const crypto = await import('crypto');
|
|
49
|
+
return crypto;
|
|
50
|
+
} catch (err) {
|
|
51
|
+
throw new ErrorWithCode(
|
|
52
|
+
'Could not sign a cross-server request because we could not load the crypto library. Please make sure this operation is running on the server.',
|
|
53
|
+
ReactKitErrorCode.NoCryptoLib,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
40
56
|
};
|
|
41
57
|
|
|
42
58
|
/*------------------------------------------------------------------------*/
|
|
43
|
-
/* -------------------------------
|
|
59
|
+
/* ------------------------------- Helpers ------------------------------ */
|
|
44
60
|
/*------------------------------------------------------------------------*/
|
|
45
61
|
|
|
46
62
|
/**
|
|
47
|
-
*
|
|
63
|
+
* Generate an oauth signature
|
|
48
64
|
* @author Gabe Abrams
|
|
49
65
|
* @param opts object containing all arguments
|
|
50
|
-
* @param opts.
|
|
51
|
-
* @param opts.
|
|
52
|
-
* @
|
|
66
|
+
* @param opts.method the http method
|
|
67
|
+
* @param opts.path the http request path
|
|
68
|
+
* @param opts.params the data in the body to sign
|
|
69
|
+
* @param opts.secret the secret to sign with
|
|
70
|
+
* @return the signature
|
|
53
71
|
*/
|
|
54
|
-
const genSignature = (
|
|
72
|
+
const genSignature = async (
|
|
55
73
|
opts: {
|
|
56
|
-
|
|
74
|
+
method?: string,
|
|
75
|
+
path?: string,
|
|
76
|
+
params?: { [key: string]: any },
|
|
57
77
|
secret: string,
|
|
58
78
|
},
|
|
59
|
-
): string => {
|
|
60
|
-
//
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
79
|
+
): Promise<string> => {
|
|
80
|
+
// Destructure opts
|
|
81
|
+
const {
|
|
82
|
+
method,
|
|
83
|
+
path,
|
|
84
|
+
params,
|
|
85
|
+
secret,
|
|
86
|
+
} = opts;
|
|
87
|
+
|
|
88
|
+
// Get the oauth library
|
|
89
|
+
const oauth = await getOauthLib();
|
|
90
|
+
|
|
91
|
+
// Order the params alphabetically by key
|
|
92
|
+
const keys = Object.keys(params ?? {});
|
|
93
|
+
keys.sort();
|
|
94
|
+
const orderedParams: {
|
|
95
|
+
[key: string]: any,
|
|
96
|
+
} = {};
|
|
97
|
+
keys.forEach((key) => {
|
|
98
|
+
// Skip oauth_signature
|
|
99
|
+
if (key === 'oauth_signature') {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Add the param
|
|
104
|
+
orderedParams[key] = (params ?? {})[key];
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Generate the signature
|
|
108
|
+
return decodeURIComponent(oauth.generate(
|
|
109
|
+
method ?? 'GET',
|
|
110
|
+
path ?? 'no-path',
|
|
111
|
+
orderedParams,
|
|
112
|
+
secret,
|
|
113
|
+
));
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Decrypt an encrypted string using a secret
|
|
118
|
+
* @author Gabe Abrams
|
|
119
|
+
* @param str the encrypted string
|
|
120
|
+
* @return the decrypted string
|
|
121
|
+
*/
|
|
122
|
+
const decrypt = async (
|
|
123
|
+
encryptedPack: string,
|
|
124
|
+
): Promise<string> => {
|
|
125
|
+
// Decryption process based on:
|
|
126
|
+
// https://medium.com/@tony.infisical/guide-to-nodes-crypto-module-for-encryption-decryption-65c077176980
|
|
127
|
+
|
|
128
|
+
// Get the encryption secret
|
|
129
|
+
const { REACTKIT_CRED_ENCODING_SALT } = process.env;
|
|
130
|
+
if (!REACTKIT_CRED_ENCODING_SALT) {
|
|
131
|
+
throw new ErrorWithCode(
|
|
132
|
+
'Could not decrypt a string because the encryption salt was not set.',
|
|
133
|
+
ReactKitErrorCode.CrossServerNoCredentialEncodingSalt,
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Get the crypto library
|
|
138
|
+
const crypto = await getCryptoLib();
|
|
139
|
+
|
|
140
|
+
// Separate encrypted pack
|
|
141
|
+
const {
|
|
142
|
+
ciphertext,
|
|
143
|
+
iv,
|
|
144
|
+
tag,
|
|
145
|
+
} = JSON.parse(decodeURIComponent(encryptedPack));
|
|
146
|
+
|
|
147
|
+
// Parse the encrypted data
|
|
148
|
+
const decipher = crypto.createDecipheriv(
|
|
149
|
+
'aes-256-gcm',
|
|
150
|
+
Buffer.from(REACTKIT_CRED_ENCODING_SALT, 'base64'),
|
|
151
|
+
Buffer.from(iv, 'base64'),
|
|
65
152
|
);
|
|
153
|
+
|
|
154
|
+
// Set the authentication tag
|
|
155
|
+
decipher.setAuthTag(Buffer.from(tag, 'base64'));
|
|
156
|
+
|
|
157
|
+
// Decrypt the string
|
|
158
|
+
let str = decipher.update(ciphertext, 'base64', 'utf8');
|
|
159
|
+
str += decipher.final('utf8');
|
|
160
|
+
|
|
161
|
+
// Return the decrypted string
|
|
162
|
+
return str;
|
|
66
163
|
};
|
|
67
164
|
|
|
165
|
+
/*------------------------------------------------------------------------*/
|
|
166
|
+
/* ------------------------------- Signing ------------------------------ */
|
|
167
|
+
/*------------------------------------------------------------------------*/
|
|
168
|
+
|
|
68
169
|
/**
|
|
69
|
-
* Sign
|
|
170
|
+
* Sign a request and get the new request params
|
|
70
171
|
* @author Gabe Abrams
|
|
71
172
|
* @param opts object containing all arguments
|
|
72
173
|
* @param opts.method the method to sign
|
|
@@ -74,9 +175,9 @@ const genSignature = (
|
|
|
74
175
|
* @param opts.params the data in the body to sign
|
|
75
176
|
* @param opts.key the reactkit key to sign with
|
|
76
177
|
* @param opts.secret the reactkit secret to sign with
|
|
77
|
-
* @return the
|
|
178
|
+
* @return augmented params for the request, including a signature, timestamp, and key
|
|
78
179
|
*/
|
|
79
|
-
export const
|
|
180
|
+
export const signRequest = async (
|
|
80
181
|
opts: {
|
|
81
182
|
method: string,
|
|
82
183
|
path: string,
|
|
@@ -84,111 +185,108 @@ export const createSignedPack = (
|
|
|
84
185
|
key: string,
|
|
85
186
|
secret: string,
|
|
86
187
|
},
|
|
87
|
-
): string => {
|
|
88
|
-
//
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
key: opts.key,
|
|
97
|
-
timestamp,
|
|
98
|
-
});
|
|
188
|
+
): Promise<{ [key: string]: any }> => {
|
|
189
|
+
// Destructure opts
|
|
190
|
+
const method = opts.method.toUpperCase();
|
|
191
|
+
const {
|
|
192
|
+
path,
|
|
193
|
+
params,
|
|
194
|
+
key,
|
|
195
|
+
secret,
|
|
196
|
+
} = opts;
|
|
99
197
|
|
|
100
|
-
//
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
198
|
+
// Augment the params
|
|
199
|
+
const augmentedParams: {
|
|
200
|
+
[key: string]: any,
|
|
201
|
+
} = {
|
|
202
|
+
...params,
|
|
203
|
+
oauth_consumer_key: key,
|
|
204
|
+
oauth_nonce: Math.random().toString(36),
|
|
205
|
+
oauth_timestamp: Date.now(),
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
// Generate a signature
|
|
209
|
+
const signature = await genSignature({
|
|
210
|
+
method,
|
|
211
|
+
path,
|
|
212
|
+
params,
|
|
213
|
+
secret,
|
|
104
214
|
});
|
|
105
215
|
|
|
106
|
-
//
|
|
107
|
-
|
|
108
|
-
pack,
|
|
109
|
-
signature,
|
|
110
|
-
}));
|
|
216
|
+
// Add signature to the augmented params
|
|
217
|
+
augmentedParams.oauth_signature = signature;
|
|
111
218
|
|
|
112
|
-
// Return the
|
|
113
|
-
return
|
|
219
|
+
// Return the augmented params
|
|
220
|
+
return augmentedParams;
|
|
114
221
|
};
|
|
115
222
|
|
|
116
223
|
/**
|
|
117
|
-
*
|
|
224
|
+
* Validate a signed request. Throws an error if invalid
|
|
118
225
|
* @author Gabe Abrams
|
|
119
226
|
* @param opts object containing all arguments
|
|
120
227
|
* @param opts.method the method of the data validate
|
|
121
228
|
* @param opts.path the http request path to validate
|
|
122
229
|
* @param opts.scope the name of the scope to validate
|
|
123
|
-
* @param opts.
|
|
230
|
+
* @param opts.params the request data to validate
|
|
124
231
|
* @returns parsed and validated params
|
|
125
232
|
*/
|
|
126
|
-
export const
|
|
233
|
+
export const validateSignedRequest = async (
|
|
127
234
|
opts: {
|
|
128
235
|
method: string,
|
|
129
236
|
path: string,
|
|
130
237
|
scope: string,
|
|
131
|
-
|
|
238
|
+
params: { [key: string]: any },
|
|
132
239
|
},
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
let pack: string;
|
|
136
|
-
let signature: string;
|
|
137
|
-
let method: string;
|
|
138
|
-
let path: string;
|
|
139
|
-
let key: string;
|
|
140
|
-
let timestamp: number;
|
|
141
|
-
let params: { [k: string]: any };
|
|
142
|
-
try {
|
|
143
|
-
({
|
|
144
|
-
pack,
|
|
145
|
-
signature,
|
|
146
|
-
} = JSON.parse(decodeURIComponent(opts.signedPack)));
|
|
147
|
-
|
|
148
|
-
// Unpack
|
|
149
|
-
({
|
|
150
|
-
method,
|
|
151
|
-
path,
|
|
152
|
-
params,
|
|
153
|
-
key,
|
|
154
|
-
timestamp,
|
|
155
|
-
} = JSON.parse(pack));
|
|
156
|
-
} catch (err) {
|
|
157
|
-
throw new ErrorWithCode(
|
|
158
|
-
'Could not validate a cross-server request because the request could not be parsed.',
|
|
159
|
-
ReactKitErrorCode.PackUnparseable,
|
|
160
|
-
);
|
|
161
|
-
}
|
|
240
|
+
) => {
|
|
241
|
+
/* ---------- Collect Info ---------- */
|
|
162
242
|
|
|
163
|
-
//
|
|
164
|
-
if (
|
|
243
|
+
// Get the signature
|
|
244
|
+
if (!opts.params.oauth_signature) {
|
|
165
245
|
throw new ErrorWithCode(
|
|
166
|
-
'Could not validate a cross-server request
|
|
167
|
-
ReactKitErrorCode.
|
|
246
|
+
'Could not validate a cross-server request there was no oauth signature.',
|
|
247
|
+
ReactKitErrorCode.CrossServerMissingSignedRequestInfo,
|
|
168
248
|
);
|
|
169
249
|
}
|
|
170
|
-
|
|
250
|
+
const signature = opts.params.oauth_signature;
|
|
251
|
+
|
|
252
|
+
// Get the timestamp
|
|
253
|
+
if (
|
|
254
|
+
// No timestamp
|
|
255
|
+
!opts.params.oauth_timestamp
|
|
256
|
+
// Invalid timestamp
|
|
257
|
+
|| Number.isNaN(Number.parseInt(opts.params.oauth_timestamp, 10))
|
|
258
|
+
) {
|
|
171
259
|
throw new ErrorWithCode(
|
|
172
|
-
'Could not validate a cross-server request
|
|
173
|
-
ReactKitErrorCode.
|
|
260
|
+
'Could not validate a cross-server request there was no valid oauth timestamp.',
|
|
261
|
+
ReactKitErrorCode.CrossServerMissingSignedRequestInfo,
|
|
174
262
|
);
|
|
175
263
|
}
|
|
264
|
+
const timestamp = Number.parseInt(opts.params.oauth_timestamp, 10);
|
|
176
265
|
|
|
177
|
-
//
|
|
178
|
-
|
|
179
|
-
if (elapsedMs < MINUTE_IN_MS) {
|
|
266
|
+
// Get the key
|
|
267
|
+
if (!opts.params.oauth_consumer_key) {
|
|
180
268
|
throw new ErrorWithCode(
|
|
181
|
-
'Could not validate a cross-server request
|
|
182
|
-
ReactKitErrorCode.
|
|
269
|
+
'Could not validate a cross-server request there was no oauth consumer key.',
|
|
270
|
+
ReactKitErrorCode.CrossServerMissingSignedRequestInfo,
|
|
183
271
|
);
|
|
184
272
|
}
|
|
273
|
+
const key = opts.params.oauth_consumer_key;
|
|
274
|
+
|
|
275
|
+
// Get the rest of the info
|
|
276
|
+
const {
|
|
277
|
+
method,
|
|
278
|
+
path,
|
|
279
|
+
params,
|
|
280
|
+
} = opts;
|
|
281
|
+
|
|
282
|
+
/* ------- Look Up Credential ------- */
|
|
185
283
|
|
|
186
284
|
// Get the cross-server credential collection
|
|
187
285
|
const crossServerCredentialCollection = internalGetCrossServerCredentialCollection();
|
|
188
286
|
if (!crossServerCredentialCollection) {
|
|
189
287
|
throw new ErrorWithCode(
|
|
190
288
|
'Could not validate a cross-server request because the cross-server credential collection was not ready in time.',
|
|
191
|
-
ReactKitErrorCode.
|
|
289
|
+
ReactKitErrorCode.SignedRequestInvalidCollection,
|
|
192
290
|
);
|
|
193
291
|
}
|
|
194
292
|
|
|
@@ -197,7 +295,7 @@ export const parseSignedPack = async (
|
|
|
197
295
|
if (!crossServerCredential) {
|
|
198
296
|
throw new ErrorWithCode(
|
|
199
297
|
'Could not validate a cross-server request because the credential was not found.',
|
|
200
|
-
ReactKitErrorCode.
|
|
298
|
+
ReactKitErrorCode.SignedRequestInvalidCredential,
|
|
201
299
|
);
|
|
202
300
|
}
|
|
203
301
|
|
|
@@ -206,27 +304,37 @@ export const parseSignedPack = async (
|
|
|
206
304
|
if (!allowedScopes.includes(opts.scope)) {
|
|
207
305
|
throw new ErrorWithCode(
|
|
208
306
|
'Could not validate a cross-server request because the scope was not included.',
|
|
209
|
-
ReactKitErrorCode.
|
|
307
|
+
ReactKitErrorCode.SignedRequestInvalidScope,
|
|
210
308
|
);
|
|
211
309
|
}
|
|
212
310
|
|
|
213
311
|
// Decode the secret
|
|
214
|
-
const secret =
|
|
312
|
+
const secret = await decrypt(crossServerCredential.encodedeSecret);
|
|
313
|
+
|
|
314
|
+
/* -------- Verify Signature -------- */
|
|
215
315
|
|
|
216
|
-
// Generate signature
|
|
217
|
-
const expectedSignature = genSignature({
|
|
218
|
-
|
|
316
|
+
// Generate a new signature to compare
|
|
317
|
+
const expectedSignature = await genSignature({
|
|
318
|
+
method,
|
|
319
|
+
path,
|
|
320
|
+
params,
|
|
219
321
|
secret,
|
|
220
322
|
});
|
|
221
323
|
|
|
222
|
-
// Make sure the
|
|
324
|
+
// Make sure the signatures match
|
|
223
325
|
if (signature !== expectedSignature) {
|
|
224
326
|
throw new ErrorWithCode(
|
|
225
327
|
'Could not validate a cross-server request because the signature did not match.',
|
|
226
|
-
ReactKitErrorCode.
|
|
328
|
+
ReactKitErrorCode.SignedRequestInvalidSignature,
|
|
227
329
|
);
|
|
228
330
|
}
|
|
229
331
|
|
|
230
|
-
//
|
|
231
|
-
|
|
332
|
+
// Make sure the timestamp was recent enough
|
|
333
|
+
const elapsedMs = Math.abs(Date.now() - timestamp);
|
|
334
|
+
if (elapsedMs < MINUTE_IN_MS) {
|
|
335
|
+
throw new ErrorWithCode(
|
|
336
|
+
'Could not validate a cross-server request because the request was too old.',
|
|
337
|
+
ReactKitErrorCode.SignedRequestInvalidTimestamp,
|
|
338
|
+
);
|
|
339
|
+
}
|
|
232
340
|
};
|
|
@@ -17,7 +17,7 @@ import genErrorPage from '../html/genErrorPage';
|
|
|
17
17
|
import genInfoPage from '../html/genInfoPage';
|
|
18
18
|
import parseUserAgent from './parseUserAgent';
|
|
19
19
|
import getTimeInfoInET from './getTimeInfoInET';
|
|
20
|
-
import {
|
|
20
|
+
import { validateSignedRequest } from './dataSigner';
|
|
21
21
|
|
|
22
22
|
// Import shared types
|
|
23
23
|
import LogFunction from '../types/LogFunction';
|
|
@@ -30,7 +30,6 @@ import LogSourceSpecificInfo from '../types/Log/LogSourceSpecificInfo';
|
|
|
30
30
|
import LogBuiltInMetadata from '../types/LogBuiltInMetadata';
|
|
31
31
|
import LogAction from '../types/LogAction';
|
|
32
32
|
import LogLevel from '../types/LogLevel';
|
|
33
|
-
import ErrorWithCode from '../errors/ErrorWithCode';
|
|
34
33
|
|
|
35
34
|
/**
|
|
36
35
|
* Generate an express API route handler
|
|
@@ -137,7 +136,7 @@ const genRouteHandler = (
|
|
|
137
136
|
);
|
|
138
137
|
|
|
139
138
|
// Get body from everywhere it can come from
|
|
140
|
-
|
|
139
|
+
const requestBody: {
|
|
141
140
|
[k: string]: any,
|
|
142
141
|
} = {
|
|
143
142
|
...req.body,
|
|
@@ -150,27 +149,31 @@ const genRouteHandler = (
|
|
|
150
149
|
/*----------------------------------------*/
|
|
151
150
|
|
|
152
151
|
if (crossServerScope) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
152
|
+
try {
|
|
153
|
+
// Validate the request body
|
|
154
|
+
await validateSignedRequest({
|
|
155
|
+
method: req.method ?? 'GET',
|
|
156
|
+
path: req.path,
|
|
157
|
+
scope: crossServerScope,
|
|
158
|
+
params: requestBody,
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Valid! Remove oauth values
|
|
162
|
+
Object.keys(requestBody).forEach((key) => {
|
|
163
|
+
if (key.startsWith('oauth_')) {
|
|
164
|
+
delete requestBody[key];
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
} catch (err) {
|
|
168
|
+
return handleError(
|
|
169
|
+
res,
|
|
170
|
+
{
|
|
171
|
+
message: `The authenticity of a cross-server request could not be validated because an error occurred: ${(err as any).message ?? 'unknown error'}`,
|
|
172
|
+
code: ((err as any).code ?? ReactKitErrorCode.UnknownCrossServerError),
|
|
173
|
+
status: 401,
|
|
174
|
+
},
|
|
161
175
|
);
|
|
162
176
|
}
|
|
163
|
-
|
|
164
|
-
// Validate the request
|
|
165
|
-
const crossServerParams = await parseSignedPack({
|
|
166
|
-
method: req.method ?? 'GET',
|
|
167
|
-
path: req.path,
|
|
168
|
-
scope: crossServerScope,
|
|
169
|
-
signedPack,
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
// Replace body with params from the pack
|
|
173
|
-
requestBody = crossServerParams ?? {};
|
|
174
177
|
}
|
|
175
178
|
|
|
176
179
|
/*----------------------------------------*/
|
|
@@ -586,14 +589,14 @@ const genRouteHandler = (
|
|
|
586
589
|
// Main log info
|
|
587
590
|
const mainLogInfo: LogMainInfo = {
|
|
588
591
|
id: `${launchInfo ? launchInfo.userId : 'unknown'}-${Date.now()}-${Math.floor(Math.random() * 100000)}-${Math.floor(Math.random() * 100000)}`,
|
|
589
|
-
userFirstName: (launchInfo ? launchInfo.userFirstName: 'unknown'),
|
|
592
|
+
userFirstName: (launchInfo ? launchInfo.userFirstName : 'unknown'),
|
|
590
593
|
userLastName: (launchInfo ? launchInfo.userLastName : 'unknown'),
|
|
591
594
|
userEmail: (launchInfo ? launchInfo.userEmail : 'unknown'),
|
|
592
595
|
userId: (launchInfo ? launchInfo.userId : 'unknown'),
|
|
593
596
|
isLearner: (launchInfo && !!launchInfo.isLearner),
|
|
594
597
|
isAdmin: (launchInfo && !!launchInfo.isAdmin),
|
|
595
598
|
isTTM: (launchInfo && !!launchInfo.isTTM),
|
|
596
|
-
courseId: (launchInfo ? launchInfo.courseId : 'unknown'
|
|
599
|
+
courseId: (launchInfo ? launchInfo.courseId : 'unknown'),
|
|
597
600
|
courseName: (launchInfo ? launchInfo.contextLabel : 'unknown'),
|
|
598
601
|
browser,
|
|
599
602
|
device,
|