propro-utils 1.6.3 → 1.6.5
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "propro-utils",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.5",
|
|
4
4
|
"description": "Auth middleware for propro-auth",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"jest-mock-axios": "^4.7.3",
|
|
47
47
|
"jsonwebtoken": "^9.0.2",
|
|
48
48
|
"multer": "^1.4.5-lts.1",
|
|
49
|
+
"neverthrow": "^8.2.0",
|
|
49
50
|
"nodemailer": "^6.9.7",
|
|
50
51
|
"nodemailer-mailgun-transport": "^2.1.5",
|
|
51
52
|
"querystring": "^0.2.1",
|
|
@@ -3,19 +3,19 @@
|
|
|
3
3
|
* This module provides functions for setting and clearing authentication cookies.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const { URL } = require(
|
|
6
|
+
const { URL } = require("url");
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Safely stringify an object, handling circular references
|
|
10
10
|
* @param {Object} obj - The object to stringify
|
|
11
11
|
* @return {string} A JSON string representation of the object
|
|
12
12
|
*/
|
|
13
|
-
const safeStringify = obj => {
|
|
13
|
+
const safeStringify = (obj) => {
|
|
14
14
|
const seen = new WeakSet();
|
|
15
15
|
return JSON.stringify(obj, (key, value) => {
|
|
16
|
-
if (typeof value ===
|
|
16
|
+
if (typeof value === "object" && value !== null) {
|
|
17
17
|
if (seen.has(value)) {
|
|
18
|
-
return
|
|
18
|
+
return "[Circular]";
|
|
19
19
|
}
|
|
20
20
|
seen.add(value);
|
|
21
21
|
}
|
|
@@ -28,7 +28,7 @@ const safeStringify = obj => {
|
|
|
28
28
|
* @param {Object} user - The user object to sanitize
|
|
29
29
|
* @return {Object} A sanitized version of the user object
|
|
30
30
|
*/
|
|
31
|
-
const sanitizeUser = user => {
|
|
31
|
+
const sanitizeUser = (user) => {
|
|
32
32
|
const sanitized = { ...user };
|
|
33
33
|
|
|
34
34
|
delete sanitized.password;
|
|
@@ -61,10 +61,10 @@ const sanitizeUser = user => {
|
|
|
61
61
|
* @param {Object} details - Cookie details
|
|
62
62
|
* @returns {Promise} Promise that resolves when cookie is set
|
|
63
63
|
*/
|
|
64
|
-
const setChromeExtensionCookie = details => {
|
|
64
|
+
const setChromeExtensionCookie = (details) => {
|
|
65
65
|
return new Promise((resolve, reject) => {
|
|
66
66
|
try {
|
|
67
|
-
chrome.cookies.set(details, cookie => {
|
|
67
|
+
chrome.cookies.set(details, (cookie) => {
|
|
68
68
|
if (chrome.runtime.lastError) {
|
|
69
69
|
reject(chrome.runtime.lastError);
|
|
70
70
|
} else {
|
|
@@ -83,13 +83,13 @@ const setChromeExtensionCookie = details => {
|
|
|
83
83
|
*/
|
|
84
84
|
const setAuthCookies = async (res, tokens, account, user, appUrl) => {
|
|
85
85
|
if (!tokens?.refresh?.token || !tokens?.access?.token) {
|
|
86
|
-
throw new Error(
|
|
86
|
+
throw new Error("Invalid tokens object");
|
|
87
87
|
}
|
|
88
88
|
if (!account) {
|
|
89
|
-
throw new Error(
|
|
89
|
+
throw new Error("Invalid account object");
|
|
90
90
|
}
|
|
91
91
|
if (!user) {
|
|
92
|
-
throw new Error(
|
|
92
|
+
throw new Error("Invalid user object");
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
const currentDateTime = new Date();
|
|
@@ -101,35 +101,49 @@ const setAuthCookies = async (res, tokens, account, user, appUrl) => {
|
|
|
101
101
|
// Domain configuration
|
|
102
102
|
let domain;
|
|
103
103
|
try {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
// Handle URLs that don't include the protocol
|
|
105
|
+
let processedAppUrl = appUrl;
|
|
106
|
+
if (
|
|
107
|
+
appUrl &&
|
|
108
|
+
!appUrl.startsWith("http://") &&
|
|
109
|
+
!appUrl.startsWith("https://")
|
|
110
|
+
) {
|
|
111
|
+
processedAppUrl = `https://${appUrl}`;
|
|
107
112
|
}
|
|
108
|
-
|
|
113
|
+
|
|
114
|
+
domain = processedAppUrl ? new URL(processedAppUrl).hostname : undefined;
|
|
115
|
+
if (domain?.includes("mapmap.app")) {
|
|
116
|
+
domain = ".mapmap.app";
|
|
117
|
+
}
|
|
118
|
+
if (domain?.includes("localhost")) {
|
|
109
119
|
domain = undefined;
|
|
110
120
|
}
|
|
111
|
-
if (domain?.includes(
|
|
112
|
-
domain =
|
|
121
|
+
if (domain?.includes("propro.so")) {
|
|
122
|
+
domain = "propro.so";
|
|
113
123
|
}
|
|
114
124
|
} catch (error) {
|
|
115
|
-
console.error(
|
|
125
|
+
console.error("Invalid appUrl:", { error, appUrl });
|
|
116
126
|
domain = undefined;
|
|
117
127
|
}
|
|
118
128
|
|
|
129
|
+
// Determine if we're in a local development environment
|
|
130
|
+
const isLocalhost =
|
|
131
|
+
!domain || domain === "localhost" || domain.includes("localhost");
|
|
132
|
+
|
|
119
133
|
const commonAttributes = {
|
|
120
|
-
secure:
|
|
121
|
-
sameSite:
|
|
134
|
+
secure: !isLocalhost, // Only require secure for non-localhost environments
|
|
135
|
+
sameSite: isLocalhost ? "Lax" : "None", // Use Lax for localhost, None for production
|
|
122
136
|
domain,
|
|
123
|
-
path:
|
|
137
|
+
path: "/",
|
|
124
138
|
};
|
|
125
139
|
|
|
126
140
|
const httpOnlyCookies = {
|
|
127
|
-
|
|
141
|
+
"x-refresh-token": {
|
|
128
142
|
value: tokens.refresh.token,
|
|
129
143
|
maxAge: refreshMaxAge,
|
|
130
144
|
httpOnly: true,
|
|
131
145
|
},
|
|
132
|
-
|
|
146
|
+
"x-access-token": {
|
|
133
147
|
value: tokens.access.token,
|
|
134
148
|
maxAge: accessMaxAge,
|
|
135
149
|
httpOnly: true,
|
|
@@ -150,7 +164,7 @@ const setAuthCookies = async (res, tokens, account, user, appUrl) => {
|
|
|
150
164
|
maxAge: refreshMaxAge,
|
|
151
165
|
},
|
|
152
166
|
has_account_token: {
|
|
153
|
-
value: JSON.stringify({ value:
|
|
167
|
+
value: JSON.stringify({ value: "true", expires: accessMaxAge }),
|
|
154
168
|
maxAge: accessMaxAge,
|
|
155
169
|
},
|
|
156
170
|
};
|
|
@@ -170,21 +184,21 @@ const setAuthCookies = async (res, tokens, account, user, appUrl) => {
|
|
|
170
184
|
...regularCookies,
|
|
171
185
|
}).map(([name, config]) => {
|
|
172
186
|
return setChromeExtensionCookie({
|
|
173
|
-
url: `https://${domain ||
|
|
187
|
+
url: `https://${domain || "propro.so"}`,
|
|
174
188
|
name,
|
|
175
189
|
value: config.value,
|
|
176
190
|
secure: true,
|
|
177
191
|
httpOnly: !!config.httpOnly,
|
|
178
|
-
sameSite:
|
|
179
|
-
path:
|
|
192
|
+
sameSite: "no_restriction",
|
|
193
|
+
path: "/",
|
|
180
194
|
expirationDate: Math.floor((Date.now() + config.maxAge) / 1000),
|
|
181
|
-
domain: domain?.startsWith(
|
|
195
|
+
domain: domain?.startsWith(".") ? domain : `.${domain || "propro.so"}`,
|
|
182
196
|
});
|
|
183
197
|
});
|
|
184
198
|
|
|
185
199
|
await Promise.allSettled(extensionCookiePromises);
|
|
186
200
|
|
|
187
|
-
console.log(
|
|
201
|
+
console.log("Auth cookies set successfully", {
|
|
188
202
|
domain,
|
|
189
203
|
sameSite: commonAttributes.sameSite,
|
|
190
204
|
cookieNames: [
|
|
@@ -193,11 +207,11 @@ const setAuthCookies = async (res, tokens, account, user, appUrl) => {
|
|
|
193
207
|
],
|
|
194
208
|
});
|
|
195
209
|
} catch (error) {
|
|
196
|
-
console.error(
|
|
210
|
+
console.error("Error setting cookies:", {
|
|
197
211
|
error: error.message,
|
|
198
212
|
stack: error.stack,
|
|
199
213
|
});
|
|
200
|
-
throw new Error(
|
|
214
|
+
throw new Error("Failed to set authentication cookies");
|
|
201
215
|
}
|
|
202
216
|
};
|
|
203
217
|
|
|
@@ -207,45 +221,59 @@ const setAuthCookies = async (res, tokens, account, user, appUrl) => {
|
|
|
207
221
|
const clearAuthCookies = async (res, appUrl) => {
|
|
208
222
|
let domain;
|
|
209
223
|
try {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
224
|
+
// Handle URLs that don't include the protocol
|
|
225
|
+
let processedAppUrl = appUrl;
|
|
226
|
+
if (
|
|
227
|
+
appUrl &&
|
|
228
|
+
!appUrl.startsWith("http://") &&
|
|
229
|
+
!appUrl.startsWith("https://")
|
|
230
|
+
) {
|
|
231
|
+
processedAppUrl = `https://${appUrl}`;
|
|
213
232
|
}
|
|
214
|
-
|
|
233
|
+
|
|
234
|
+
domain = processedAppUrl ? new URL(processedAppUrl).hostname : undefined;
|
|
235
|
+
if (domain?.includes("mapmap.app")) {
|
|
236
|
+
domain = ".mapmap.app";
|
|
237
|
+
}
|
|
238
|
+
if (domain?.includes("localhost")) {
|
|
215
239
|
domain = undefined;
|
|
216
240
|
}
|
|
217
241
|
} catch (error) {
|
|
218
|
-
console.error(
|
|
242
|
+
console.error("Invalid appUrl:", error);
|
|
219
243
|
domain = undefined;
|
|
220
244
|
}
|
|
221
245
|
|
|
246
|
+
// Determine if we're in a local development environment
|
|
247
|
+
const isLocalhost =
|
|
248
|
+
!domain || domain === "localhost" || domain.includes("localhost");
|
|
249
|
+
|
|
222
250
|
const commonAttributes = {
|
|
223
|
-
secure:
|
|
224
|
-
sameSite:
|
|
251
|
+
secure: !isLocalhost, // Only require secure for non-localhost environments
|
|
252
|
+
sameSite: isLocalhost ? "Lax" : "None", // Use Lax for localhost, None for production
|
|
225
253
|
domain,
|
|
226
|
-
path:
|
|
254
|
+
path: "/",
|
|
227
255
|
};
|
|
228
256
|
|
|
229
257
|
const cookieNames = [
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
258
|
+
"x-refresh-token",
|
|
259
|
+
"x-access-token",
|
|
260
|
+
"user",
|
|
261
|
+
"account",
|
|
262
|
+
"has_account_token",
|
|
235
263
|
];
|
|
236
264
|
|
|
237
265
|
// Clear web cookies
|
|
238
|
-
cookieNames.forEach(cookieName => {
|
|
266
|
+
cookieNames.forEach((cookieName) => {
|
|
239
267
|
res.clearCookie(cookieName, commonAttributes);
|
|
240
268
|
});
|
|
241
269
|
|
|
242
270
|
try {
|
|
243
271
|
const extensionClearPromises = cookieNames.map(
|
|
244
|
-
name =>
|
|
245
|
-
new Promise(resolve => {
|
|
272
|
+
(name) =>
|
|
273
|
+
new Promise((resolve) => {
|
|
246
274
|
chrome.cookies.remove(
|
|
247
275
|
{
|
|
248
|
-
url: `https://${domain ||
|
|
276
|
+
url: `https://${domain || "mapmap.app"}`,
|
|
249
277
|
name,
|
|
250
278
|
},
|
|
251
279
|
resolve
|
|
@@ -258,7 +286,7 @@ const clearAuthCookies = async (res, appUrl) => {
|
|
|
258
286
|
// Not in extension context, ignore
|
|
259
287
|
}
|
|
260
288
|
|
|
261
|
-
console.log(
|
|
289
|
+
console.log("Auth cookies cleared successfully", {
|
|
262
290
|
domain,
|
|
263
291
|
cookieNames,
|
|
264
292
|
sameSite: commonAttributes.sameSite,
|