@shopsbuilder/auth-sdk 1.2.7 → 1.2.9
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/SaleorAccessTokenStorageHandler.d.mts +1 -0
- package/dist/SaleorAccessTokenStorageHandler.d.ts +1 -0
- package/dist/SaleorAccessTokenStorageHandler.js +7 -0
- package/dist/SaleorAccessTokenStorageHandler.mjs +1 -1
- package/dist/SaleorAuthClient.d.mts +1 -7
- package/dist/SaleorAuthClient.d.ts +1 -7
- package/dist/SaleorAuthClient.js +54 -64
- package/dist/SaleorAuthClient.mjs +2 -2
- package/dist/{chunk-BZFBMGPG.mjs → chunk-B326YIV6.mjs} +7 -0
- package/dist/{chunk-UHR2J6FG.mjs → chunk-GFXR244N.mjs} +45 -65
- package/dist/index.js +54 -64
- package/dist/index.mjs +2 -2
- package/dist/react/SaleorAuthProvider.mjs +2 -2
- package/dist/react/context.mjs +2 -2
- package/dist/react/index.mjs +2 -2
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@ declare const getAccessTokenKey: (prefix?: string) => string;
|
|
|
4
4
|
declare class SaleorAccessTokenStorageHandler {
|
|
5
5
|
private storage;
|
|
6
6
|
private prefix?;
|
|
7
|
+
private cachedToken;
|
|
7
8
|
constructor(storage: StorageRepository, prefix?: string | undefined);
|
|
8
9
|
getAccessToken: () => string | null;
|
|
9
10
|
setAccessToken: (token: string) => void;
|
|
@@ -4,6 +4,7 @@ declare const getAccessTokenKey: (prefix?: string) => string;
|
|
|
4
4
|
declare class SaleorAccessTokenStorageHandler {
|
|
5
5
|
private storage;
|
|
6
6
|
private prefix?;
|
|
7
|
+
private cachedToken;
|
|
7
8
|
constructor(storage: StorageRepository, prefix?: string | undefined);
|
|
8
9
|
getAccessToken: () => string | null;
|
|
9
10
|
setAccessToken: (token: string) => void;
|
|
@@ -30,15 +30,22 @@ var SaleorAccessTokenStorageHandler = class {
|
|
|
30
30
|
this.storage = storage;
|
|
31
31
|
this.prefix = prefix;
|
|
32
32
|
}
|
|
33
|
+
// In-memory cache so the token is available even when the storage
|
|
34
|
+
// backend is read-only (e.g. Next.js cookies during render).
|
|
35
|
+
cachedToken = null;
|
|
33
36
|
getAccessToken = () => {
|
|
37
|
+
if (this.cachedToken)
|
|
38
|
+
return this.cachedToken;
|
|
34
39
|
const key = getAccessTokenKey(this.prefix);
|
|
35
40
|
return this.storage.getItem(key);
|
|
36
41
|
};
|
|
37
42
|
setAccessToken = (token) => {
|
|
43
|
+
this.cachedToken = token;
|
|
38
44
|
const key = getAccessTokenKey(this.prefix);
|
|
39
45
|
return this.storage.setItem(key, token);
|
|
40
46
|
};
|
|
41
47
|
clearAuthStorage = () => {
|
|
48
|
+
this.cachedToken = null;
|
|
42
49
|
const key = getAccessTokenKey(this.prefix);
|
|
43
50
|
return this.storage.removeItem(key);
|
|
44
51
|
};
|
|
@@ -3,12 +3,6 @@ import { StorageRepository, FetchWithAdditionalParams, PasswordResetVariables, P
|
|
|
3
3
|
interface SaleorAuthClientProps {
|
|
4
4
|
onAuthRefresh?: (isAuthenticating: boolean) => void;
|
|
5
5
|
saleorApiUrl: string;
|
|
6
|
-
/**
|
|
7
|
-
* Prefix used for storage keys. Defaults to saleorApiUrl.
|
|
8
|
-
* Set this to the public API URL when the server uses an internal URL
|
|
9
|
-
* for saleorApiUrl, so that cookie keys match between client and server.
|
|
10
|
-
*/
|
|
11
|
-
storageKeyPrefix?: string;
|
|
12
6
|
refreshTokenStorage?: StorageRepository;
|
|
13
7
|
accessTokenStorage?: StorageRepository;
|
|
14
8
|
tokenGracePeriod?: number;
|
|
@@ -39,7 +33,7 @@ declare class SaleorAuthClient {
|
|
|
39
33
|
* }, [])
|
|
40
34
|
* ```
|
|
41
35
|
*/
|
|
42
|
-
constructor({ saleorApiUrl,
|
|
36
|
+
constructor({ saleorApiUrl, refreshTokenStorage, accessTokenStorage, onAuthRefresh, tokenGracePeriod, defaultRequestInit, }: SaleorAuthClientProps);
|
|
43
37
|
cleanup: () => void;
|
|
44
38
|
private runAuthorizedRequest;
|
|
45
39
|
private handleRequestWithTokenRefresh;
|
|
@@ -3,12 +3,6 @@ import { StorageRepository, FetchWithAdditionalParams, PasswordResetVariables, P
|
|
|
3
3
|
interface SaleorAuthClientProps {
|
|
4
4
|
onAuthRefresh?: (isAuthenticating: boolean) => void;
|
|
5
5
|
saleorApiUrl: string;
|
|
6
|
-
/**
|
|
7
|
-
* Prefix used for storage keys. Defaults to saleorApiUrl.
|
|
8
|
-
* Set this to the public API URL when the server uses an internal URL
|
|
9
|
-
* for saleorApiUrl, so that cookie keys match between client and server.
|
|
10
|
-
*/
|
|
11
|
-
storageKeyPrefix?: string;
|
|
12
6
|
refreshTokenStorage?: StorageRepository;
|
|
13
7
|
accessTokenStorage?: StorageRepository;
|
|
14
8
|
tokenGracePeriod?: number;
|
|
@@ -39,7 +33,7 @@ declare class SaleorAuthClient {
|
|
|
39
33
|
* }, [])
|
|
40
34
|
* ```
|
|
41
35
|
*/
|
|
42
|
-
constructor({ saleorApiUrl,
|
|
36
|
+
constructor({ saleorApiUrl, refreshTokenStorage, accessTokenStorage, onAuthRefresh, tokenGracePeriod, defaultRequestInit, }: SaleorAuthClientProps);
|
|
43
37
|
cleanup: () => void;
|
|
44
38
|
private runAuthorizedRequest;
|
|
45
39
|
private handleRequestWithTokenRefresh;
|
package/dist/SaleorAuthClient.js
CHANGED
|
@@ -110,6 +110,10 @@ var getTokenExpiry = (token) => {
|
|
|
110
110
|
const parsedTokenData = decodeToken(token);
|
|
111
111
|
return parsedTokenData.exp * MILLI_MULTIPLYER || 0;
|
|
112
112
|
};
|
|
113
|
+
var getTokenIss = (token) => {
|
|
114
|
+
const parsedTokenData = decodeToken(token);
|
|
115
|
+
return parsedTokenData.iss;
|
|
116
|
+
};
|
|
113
117
|
var isExpiredToken = (token, tokenGracePeriod) => {
|
|
114
118
|
return getTokenExpiry(token) - tokenGracePeriod <= Date.now();
|
|
115
119
|
};
|
|
@@ -239,15 +243,22 @@ var SaleorAccessTokenStorageHandler = class {
|
|
|
239
243
|
this.storage = storage;
|
|
240
244
|
this.prefix = prefix;
|
|
241
245
|
}
|
|
246
|
+
// In-memory cache so the token is available even when the storage
|
|
247
|
+
// backend is read-only (e.g. Next.js cookies during render).
|
|
248
|
+
cachedToken = null;
|
|
242
249
|
getAccessToken = () => {
|
|
250
|
+
if (this.cachedToken)
|
|
251
|
+
return this.cachedToken;
|
|
243
252
|
const key = getAccessTokenKey(this.prefix);
|
|
244
253
|
return this.storage.getItem(key);
|
|
245
254
|
};
|
|
246
255
|
setAccessToken = (token) => {
|
|
256
|
+
this.cachedToken = token;
|
|
247
257
|
const key = getAccessTokenKey(this.prefix);
|
|
248
258
|
return this.storage.setItem(key, token);
|
|
249
259
|
};
|
|
250
260
|
clearAuthStorage = () => {
|
|
261
|
+
this.cachedToken = null;
|
|
251
262
|
const key = getAccessTokenKey(this.prefix);
|
|
252
263
|
return this.storage.removeItem(key);
|
|
253
264
|
};
|
|
@@ -283,7 +294,6 @@ var SaleorAuthClient = class {
|
|
|
283
294
|
*/
|
|
284
295
|
constructor({
|
|
285
296
|
saleorApiUrl,
|
|
286
|
-
storageKeyPrefix,
|
|
287
297
|
refreshTokenStorage,
|
|
288
298
|
accessTokenStorage,
|
|
289
299
|
onAuthRefresh,
|
|
@@ -296,23 +306,47 @@ var SaleorAuthClient = class {
|
|
|
296
306
|
}
|
|
297
307
|
this.onAuthRefresh = onAuthRefresh;
|
|
298
308
|
this.saleorApiUrl = saleorApiUrl;
|
|
299
|
-
const keyPrefix = storageKeyPrefix ?? saleorApiUrl;
|
|
300
309
|
const refreshTokenRepo = refreshTokenStorage ?? (typeof window !== "undefined" ? window.localStorage : void 0);
|
|
301
|
-
this.refreshTokenStorage = refreshTokenRepo ? new SaleorRefreshTokenStorageHandler(refreshTokenRepo,
|
|
310
|
+
this.refreshTokenStorage = refreshTokenRepo ? new SaleorRefreshTokenStorageHandler(refreshTokenRepo, saleorApiUrl) : null;
|
|
302
311
|
const accessTokenRepo = accessTokenStorage ?? getInMemoryAccessTokenStorage();
|
|
303
|
-
this.accessTokenStorage = new SaleorAccessTokenStorageHandler(accessTokenRepo,
|
|
312
|
+
this.accessTokenStorage = new SaleorAccessTokenStorageHandler(accessTokenRepo, saleorApiUrl);
|
|
304
313
|
}
|
|
305
314
|
cleanup = () => {
|
|
306
315
|
this.refreshTokenStorage?.cleanup();
|
|
307
316
|
};
|
|
308
|
-
runAuthorizedRequest = (input, init) => {
|
|
317
|
+
runAuthorizedRequest = (input, init, additionalParams) => {
|
|
309
318
|
const token = this.accessTokenStorage.getAccessToken();
|
|
310
319
|
if (!token) {
|
|
311
320
|
return fetch(input, init);
|
|
312
321
|
}
|
|
313
|
-
const headers =
|
|
314
|
-
|
|
315
|
-
|
|
322
|
+
const headers = init?.headers || {};
|
|
323
|
+
const getURL = (input2) => {
|
|
324
|
+
if (typeof input2 === "string") {
|
|
325
|
+
return input2;
|
|
326
|
+
} else if ("url" in input2) {
|
|
327
|
+
return input2.url;
|
|
328
|
+
} else {
|
|
329
|
+
return input2.href;
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
const iss = getTokenIss(token);
|
|
333
|
+
const issuerAndDomainMatch = getURL(input) === iss;
|
|
334
|
+
const shouldAddAuthorizationHeader = issuerAndDomainMatch || additionalParams?.allowPassingTokenToThirdPartyDomains;
|
|
335
|
+
if (!issuerAndDomainMatch) {
|
|
336
|
+
if (shouldAddAuthorizationHeader) {
|
|
337
|
+
console.warn(
|
|
338
|
+
"Token's `iss` and request URL do not match but `allowPassingTokenToThirdPartyDomains` was specified."
|
|
339
|
+
);
|
|
340
|
+
} else {
|
|
341
|
+
console.warn(
|
|
342
|
+
"Token's `iss` and request URL do not match. Not adding `Authorization` header to the request."
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return fetch(input, {
|
|
347
|
+
...init,
|
|
348
|
+
headers: shouldAddAuthorizationHeader ? { ...headers, Authorization: `Bearer ${token}` } : headers
|
|
349
|
+
});
|
|
316
350
|
};
|
|
317
351
|
handleRequestWithTokenRefresh = async (input, requestInit, additionalParams) => {
|
|
318
352
|
const refreshToken = this.refreshTokenStorage?.getRefreshToken();
|
|
@@ -324,37 +358,15 @@ var SaleorAuthClient = class {
|
|
|
324
358
|
this.onAuthRefresh?.(true);
|
|
325
359
|
if (this.tokenRefreshPromise) {
|
|
326
360
|
const response = await this.tokenRefreshPromise;
|
|
327
|
-
const
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
body: rawText.slice(0, 500)
|
|
335
|
-
}));
|
|
336
|
-
let res;
|
|
337
|
-
try {
|
|
338
|
-
res = await responseClone.json();
|
|
339
|
-
} catch {
|
|
340
|
-
console.error("[auth-sdk] Token refresh response is not valid JSON, status:", response.status);
|
|
341
|
-
this.onAuthRefresh?.(false);
|
|
342
|
-
this.tokenRefreshPromise = null;
|
|
343
|
-
this.refreshTokenStorage?.clearAuthStorage();
|
|
344
|
-
return fetch(input, requestInit);
|
|
345
|
-
}
|
|
346
|
-
const graphqlErrors = res.errors;
|
|
347
|
-
const token = res.data?.tokenRefresh?.token;
|
|
348
|
-
const refreshErrors = res.data?.tokenRefresh?.errors;
|
|
361
|
+
const res = await response.clone().json();
|
|
362
|
+
const {
|
|
363
|
+
errors: graphqlErrors,
|
|
364
|
+
data: {
|
|
365
|
+
tokenRefresh: { errors, token }
|
|
366
|
+
}
|
|
367
|
+
} = res;
|
|
349
368
|
this.onAuthRefresh?.(false);
|
|
350
|
-
if (
|
|
351
|
-
console.warn("[auth-sdk] Token refresh failed:", JSON.stringify({
|
|
352
|
-
graphqlErrors: graphqlErrors ?? [],
|
|
353
|
-
refreshErrors: refreshErrors ?? [],
|
|
354
|
-
hasToken: Boolean(token),
|
|
355
|
-
httpStatus: response.status,
|
|
356
|
-
rawData: res.data ?? null
|
|
357
|
-
}));
|
|
369
|
+
if (errors?.length || graphqlErrors?.length || !token) {
|
|
358
370
|
this.tokenRefreshPromise = null;
|
|
359
371
|
this.refreshTokenStorage?.clearAuthStorage();
|
|
360
372
|
return fetch(input, requestInit);
|
|
@@ -364,32 +376,10 @@ var SaleorAuthClient = class {
|
|
|
364
376
|
this.tokenRefreshPromise = null;
|
|
365
377
|
return this.runAuthorizedRequest(input, requestInit, additionalParams);
|
|
366
378
|
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
const origHeaders = new Headers(requestInit.headers);
|
|
372
|
-
for (const [key, value] of origHeaders.entries()) {
|
|
373
|
-
if (key !== "host" && key !== "content-type") {
|
|
374
|
-
refreshHeaders[key] = value;
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
const refreshBody = JSON.stringify({
|
|
379
|
-
query: TOKEN_REFRESH.toString(),
|
|
380
|
-
variables: { refreshToken }
|
|
381
|
-
});
|
|
382
|
-
console.log("[auth-sdk] Token refresh request:", JSON.stringify({
|
|
383
|
-
url: this.saleorApiUrl,
|
|
384
|
-
headers: refreshHeaders,
|
|
385
|
-
bodyLength: refreshBody.length,
|
|
386
|
-
bodyPreview: refreshBody.slice(0, 200)
|
|
387
|
-
}));
|
|
388
|
-
this.tokenRefreshPromise = fetch(this.saleorApiUrl, {
|
|
389
|
-
method: "POST",
|
|
390
|
-
headers: refreshHeaders,
|
|
391
|
-
body: refreshBody
|
|
392
|
-
});
|
|
379
|
+
this.tokenRefreshPromise = fetch(
|
|
380
|
+
this.saleorApiUrl,
|
|
381
|
+
getRequestData(TOKEN_REFRESH, { refreshToken }, { ...this.defaultRequestInit, ...requestInit })
|
|
382
|
+
);
|
|
393
383
|
return this.fetchWithAuth(input, requestInit, additionalParams);
|
|
394
384
|
};
|
|
395
385
|
handleSignIn = async (response) => {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SaleorAuthClient,
|
|
3
3
|
createSaleorAuthClient
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-GFXR244N.mjs";
|
|
5
|
+
import "./chunk-B326YIV6.mjs";
|
|
6
6
|
import "./chunk-263DHBMK.mjs";
|
|
7
7
|
import "./chunk-UDLCOX6B.mjs";
|
|
8
8
|
import "./chunk-7JTFMRQS.mjs";
|
|
@@ -5,15 +5,22 @@ var SaleorAccessTokenStorageHandler = class {
|
|
|
5
5
|
this.storage = storage;
|
|
6
6
|
this.prefix = prefix;
|
|
7
7
|
}
|
|
8
|
+
// In-memory cache so the token is available even when the storage
|
|
9
|
+
// backend is read-only (e.g. Next.js cookies during render).
|
|
10
|
+
cachedToken = null;
|
|
8
11
|
getAccessToken = () => {
|
|
12
|
+
if (this.cachedToken)
|
|
13
|
+
return this.cachedToken;
|
|
9
14
|
const key = getAccessTokenKey(this.prefix);
|
|
10
15
|
return this.storage.getItem(key);
|
|
11
16
|
};
|
|
12
17
|
setAccessToken = (token) => {
|
|
18
|
+
this.cachedToken = token;
|
|
13
19
|
const key = getAccessTokenKey(this.prefix);
|
|
14
20
|
return this.storage.setItem(key, token);
|
|
15
21
|
};
|
|
16
22
|
clearAuthStorage = () => {
|
|
23
|
+
this.cachedToken = null;
|
|
17
24
|
const key = getAccessTokenKey(this.prefix);
|
|
18
25
|
return this.storage.removeItem(key);
|
|
19
26
|
};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SaleorAccessTokenStorageHandler
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-B326YIV6.mjs";
|
|
4
4
|
import {
|
|
5
5
|
SaleorRefreshTokenStorageHandler
|
|
6
6
|
} from "./chunk-263DHBMK.mjs";
|
|
7
7
|
import {
|
|
8
8
|
getRequestData,
|
|
9
|
+
getTokenIss,
|
|
9
10
|
invariant,
|
|
10
11
|
isExpiredToken
|
|
11
12
|
} from "./chunk-UDLCOX6B.mjs";
|
|
@@ -46,7 +47,6 @@ var SaleorAuthClient = class {
|
|
|
46
47
|
*/
|
|
47
48
|
constructor({
|
|
48
49
|
saleorApiUrl,
|
|
49
|
-
storageKeyPrefix,
|
|
50
50
|
refreshTokenStorage,
|
|
51
51
|
accessTokenStorage,
|
|
52
52
|
onAuthRefresh,
|
|
@@ -59,23 +59,47 @@ var SaleorAuthClient = class {
|
|
|
59
59
|
}
|
|
60
60
|
this.onAuthRefresh = onAuthRefresh;
|
|
61
61
|
this.saleorApiUrl = saleorApiUrl;
|
|
62
|
-
const keyPrefix = storageKeyPrefix ?? saleorApiUrl;
|
|
63
62
|
const refreshTokenRepo = refreshTokenStorage ?? (typeof window !== "undefined" ? window.localStorage : void 0);
|
|
64
|
-
this.refreshTokenStorage = refreshTokenRepo ? new SaleorRefreshTokenStorageHandler(refreshTokenRepo,
|
|
63
|
+
this.refreshTokenStorage = refreshTokenRepo ? new SaleorRefreshTokenStorageHandler(refreshTokenRepo, saleorApiUrl) : null;
|
|
65
64
|
const accessTokenRepo = accessTokenStorage ?? getInMemoryAccessTokenStorage();
|
|
66
|
-
this.accessTokenStorage = new SaleorAccessTokenStorageHandler(accessTokenRepo,
|
|
65
|
+
this.accessTokenStorage = new SaleorAccessTokenStorageHandler(accessTokenRepo, saleorApiUrl);
|
|
67
66
|
}
|
|
68
67
|
cleanup = () => {
|
|
69
68
|
this.refreshTokenStorage?.cleanup();
|
|
70
69
|
};
|
|
71
|
-
runAuthorizedRequest = (input, init) => {
|
|
70
|
+
runAuthorizedRequest = (input, init, additionalParams) => {
|
|
72
71
|
const token = this.accessTokenStorage.getAccessToken();
|
|
73
72
|
if (!token) {
|
|
74
73
|
return fetch(input, init);
|
|
75
74
|
}
|
|
76
|
-
const headers =
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
const headers = init?.headers || {};
|
|
76
|
+
const getURL = (input2) => {
|
|
77
|
+
if (typeof input2 === "string") {
|
|
78
|
+
return input2;
|
|
79
|
+
} else if ("url" in input2) {
|
|
80
|
+
return input2.url;
|
|
81
|
+
} else {
|
|
82
|
+
return input2.href;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
const iss = getTokenIss(token);
|
|
86
|
+
const issuerAndDomainMatch = getURL(input) === iss;
|
|
87
|
+
const shouldAddAuthorizationHeader = issuerAndDomainMatch || additionalParams?.allowPassingTokenToThirdPartyDomains;
|
|
88
|
+
if (!issuerAndDomainMatch) {
|
|
89
|
+
if (shouldAddAuthorizationHeader) {
|
|
90
|
+
console.warn(
|
|
91
|
+
"Token's `iss` and request URL do not match but `allowPassingTokenToThirdPartyDomains` was specified."
|
|
92
|
+
);
|
|
93
|
+
} else {
|
|
94
|
+
console.warn(
|
|
95
|
+
"Token's `iss` and request URL do not match. Not adding `Authorization` header to the request."
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return fetch(input, {
|
|
100
|
+
...init,
|
|
101
|
+
headers: shouldAddAuthorizationHeader ? { ...headers, Authorization: `Bearer ${token}` } : headers
|
|
102
|
+
});
|
|
79
103
|
};
|
|
80
104
|
handleRequestWithTokenRefresh = async (input, requestInit, additionalParams) => {
|
|
81
105
|
const refreshToken = this.refreshTokenStorage?.getRefreshToken();
|
|
@@ -87,37 +111,15 @@ var SaleorAuthClient = class {
|
|
|
87
111
|
this.onAuthRefresh?.(true);
|
|
88
112
|
if (this.tokenRefreshPromise) {
|
|
89
113
|
const response = await this.tokenRefreshPromise;
|
|
90
|
-
const
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
body: rawText.slice(0, 500)
|
|
98
|
-
}));
|
|
99
|
-
let res;
|
|
100
|
-
try {
|
|
101
|
-
res = await responseClone.json();
|
|
102
|
-
} catch {
|
|
103
|
-
console.error("[auth-sdk] Token refresh response is not valid JSON, status:", response.status);
|
|
104
|
-
this.onAuthRefresh?.(false);
|
|
105
|
-
this.tokenRefreshPromise = null;
|
|
106
|
-
this.refreshTokenStorage?.clearAuthStorage();
|
|
107
|
-
return fetch(input, requestInit);
|
|
108
|
-
}
|
|
109
|
-
const graphqlErrors = res.errors;
|
|
110
|
-
const token = res.data?.tokenRefresh?.token;
|
|
111
|
-
const refreshErrors = res.data?.tokenRefresh?.errors;
|
|
114
|
+
const res = await response.clone().json();
|
|
115
|
+
const {
|
|
116
|
+
errors: graphqlErrors,
|
|
117
|
+
data: {
|
|
118
|
+
tokenRefresh: { errors, token }
|
|
119
|
+
}
|
|
120
|
+
} = res;
|
|
112
121
|
this.onAuthRefresh?.(false);
|
|
113
|
-
if (
|
|
114
|
-
console.warn("[auth-sdk] Token refresh failed:", JSON.stringify({
|
|
115
|
-
graphqlErrors: graphqlErrors ?? [],
|
|
116
|
-
refreshErrors: refreshErrors ?? [],
|
|
117
|
-
hasToken: Boolean(token),
|
|
118
|
-
httpStatus: response.status,
|
|
119
|
-
rawData: res.data ?? null
|
|
120
|
-
}));
|
|
122
|
+
if (errors?.length || graphqlErrors?.length || !token) {
|
|
121
123
|
this.tokenRefreshPromise = null;
|
|
122
124
|
this.refreshTokenStorage?.clearAuthStorage();
|
|
123
125
|
return fetch(input, requestInit);
|
|
@@ -127,32 +129,10 @@ var SaleorAuthClient = class {
|
|
|
127
129
|
this.tokenRefreshPromise = null;
|
|
128
130
|
return this.runAuthorizedRequest(input, requestInit, additionalParams);
|
|
129
131
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const origHeaders = new Headers(requestInit.headers);
|
|
135
|
-
for (const [key, value] of origHeaders.entries()) {
|
|
136
|
-
if (key !== "host" && key !== "content-type") {
|
|
137
|
-
refreshHeaders[key] = value;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
const refreshBody = JSON.stringify({
|
|
142
|
-
query: TOKEN_REFRESH.toString(),
|
|
143
|
-
variables: { refreshToken }
|
|
144
|
-
});
|
|
145
|
-
console.log("[auth-sdk] Token refresh request:", JSON.stringify({
|
|
146
|
-
url: this.saleorApiUrl,
|
|
147
|
-
headers: refreshHeaders,
|
|
148
|
-
bodyLength: refreshBody.length,
|
|
149
|
-
bodyPreview: refreshBody.slice(0, 200)
|
|
150
|
-
}));
|
|
151
|
-
this.tokenRefreshPromise = fetch(this.saleorApiUrl, {
|
|
152
|
-
method: "POST",
|
|
153
|
-
headers: refreshHeaders,
|
|
154
|
-
body: refreshBody
|
|
155
|
-
});
|
|
132
|
+
this.tokenRefreshPromise = fetch(
|
|
133
|
+
this.saleorApiUrl,
|
|
134
|
+
getRequestData(TOKEN_REFRESH, { refreshToken }, { ...this.defaultRequestInit, ...requestInit })
|
|
135
|
+
);
|
|
156
136
|
return this.fetchWithAuth(input, requestInit, additionalParams);
|
|
157
137
|
};
|
|
158
138
|
handleSignIn = async (response) => {
|
package/dist/index.js
CHANGED
|
@@ -113,6 +113,10 @@ var getTokenExpiry = (token) => {
|
|
|
113
113
|
const parsedTokenData = decodeToken(token);
|
|
114
114
|
return parsedTokenData.exp * MILLI_MULTIPLYER || 0;
|
|
115
115
|
};
|
|
116
|
+
var getTokenIss = (token) => {
|
|
117
|
+
const parsedTokenData = decodeToken(token);
|
|
118
|
+
return parsedTokenData.iss;
|
|
119
|
+
};
|
|
116
120
|
var isExpiredToken = (token, tokenGracePeriod) => {
|
|
117
121
|
return getTokenExpiry(token) - tokenGracePeriod <= Date.now();
|
|
118
122
|
};
|
|
@@ -242,15 +246,22 @@ var SaleorAccessTokenStorageHandler = class {
|
|
|
242
246
|
this.storage = storage;
|
|
243
247
|
this.prefix = prefix;
|
|
244
248
|
}
|
|
249
|
+
// In-memory cache so the token is available even when the storage
|
|
250
|
+
// backend is read-only (e.g. Next.js cookies during render).
|
|
251
|
+
cachedToken = null;
|
|
245
252
|
getAccessToken = () => {
|
|
253
|
+
if (this.cachedToken)
|
|
254
|
+
return this.cachedToken;
|
|
246
255
|
const key = getAccessTokenKey(this.prefix);
|
|
247
256
|
return this.storage.getItem(key);
|
|
248
257
|
};
|
|
249
258
|
setAccessToken = (token) => {
|
|
259
|
+
this.cachedToken = token;
|
|
250
260
|
const key = getAccessTokenKey(this.prefix);
|
|
251
261
|
return this.storage.setItem(key, token);
|
|
252
262
|
};
|
|
253
263
|
clearAuthStorage = () => {
|
|
264
|
+
this.cachedToken = null;
|
|
254
265
|
const key = getAccessTokenKey(this.prefix);
|
|
255
266
|
return this.storage.removeItem(key);
|
|
256
267
|
};
|
|
@@ -286,7 +297,6 @@ var SaleorAuthClient = class {
|
|
|
286
297
|
*/
|
|
287
298
|
constructor({
|
|
288
299
|
saleorApiUrl,
|
|
289
|
-
storageKeyPrefix,
|
|
290
300
|
refreshTokenStorage,
|
|
291
301
|
accessTokenStorage,
|
|
292
302
|
onAuthRefresh,
|
|
@@ -299,23 +309,47 @@ var SaleorAuthClient = class {
|
|
|
299
309
|
}
|
|
300
310
|
this.onAuthRefresh = onAuthRefresh;
|
|
301
311
|
this.saleorApiUrl = saleorApiUrl;
|
|
302
|
-
const keyPrefix = storageKeyPrefix ?? saleorApiUrl;
|
|
303
312
|
const refreshTokenRepo = refreshTokenStorage ?? (typeof window !== "undefined" ? window.localStorage : void 0);
|
|
304
|
-
this.refreshTokenStorage = refreshTokenRepo ? new SaleorRefreshTokenStorageHandler(refreshTokenRepo,
|
|
313
|
+
this.refreshTokenStorage = refreshTokenRepo ? new SaleorRefreshTokenStorageHandler(refreshTokenRepo, saleorApiUrl) : null;
|
|
305
314
|
const accessTokenRepo = accessTokenStorage ?? getInMemoryAccessTokenStorage();
|
|
306
|
-
this.accessTokenStorage = new SaleorAccessTokenStorageHandler(accessTokenRepo,
|
|
315
|
+
this.accessTokenStorage = new SaleorAccessTokenStorageHandler(accessTokenRepo, saleorApiUrl);
|
|
307
316
|
}
|
|
308
317
|
cleanup = () => {
|
|
309
318
|
this.refreshTokenStorage?.cleanup();
|
|
310
319
|
};
|
|
311
|
-
runAuthorizedRequest = (input, init) => {
|
|
320
|
+
runAuthorizedRequest = (input, init, additionalParams) => {
|
|
312
321
|
const token = this.accessTokenStorage.getAccessToken();
|
|
313
322
|
if (!token) {
|
|
314
323
|
return fetch(input, init);
|
|
315
324
|
}
|
|
316
|
-
const headers =
|
|
317
|
-
|
|
318
|
-
|
|
325
|
+
const headers = init?.headers || {};
|
|
326
|
+
const getURL = (input2) => {
|
|
327
|
+
if (typeof input2 === "string") {
|
|
328
|
+
return input2;
|
|
329
|
+
} else if ("url" in input2) {
|
|
330
|
+
return input2.url;
|
|
331
|
+
} else {
|
|
332
|
+
return input2.href;
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
const iss = getTokenIss(token);
|
|
336
|
+
const issuerAndDomainMatch = getURL(input) === iss;
|
|
337
|
+
const shouldAddAuthorizationHeader = issuerAndDomainMatch || additionalParams?.allowPassingTokenToThirdPartyDomains;
|
|
338
|
+
if (!issuerAndDomainMatch) {
|
|
339
|
+
if (shouldAddAuthorizationHeader) {
|
|
340
|
+
console.warn(
|
|
341
|
+
"Token's `iss` and request URL do not match but `allowPassingTokenToThirdPartyDomains` was specified."
|
|
342
|
+
);
|
|
343
|
+
} else {
|
|
344
|
+
console.warn(
|
|
345
|
+
"Token's `iss` and request URL do not match. Not adding `Authorization` header to the request."
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
return fetch(input, {
|
|
350
|
+
...init,
|
|
351
|
+
headers: shouldAddAuthorizationHeader ? { ...headers, Authorization: `Bearer ${token}` } : headers
|
|
352
|
+
});
|
|
319
353
|
};
|
|
320
354
|
handleRequestWithTokenRefresh = async (input, requestInit, additionalParams) => {
|
|
321
355
|
const refreshToken = this.refreshTokenStorage?.getRefreshToken();
|
|
@@ -327,37 +361,15 @@ var SaleorAuthClient = class {
|
|
|
327
361
|
this.onAuthRefresh?.(true);
|
|
328
362
|
if (this.tokenRefreshPromise) {
|
|
329
363
|
const response = await this.tokenRefreshPromise;
|
|
330
|
-
const
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
body: rawText.slice(0, 500)
|
|
338
|
-
}));
|
|
339
|
-
let res;
|
|
340
|
-
try {
|
|
341
|
-
res = await responseClone.json();
|
|
342
|
-
} catch {
|
|
343
|
-
console.error("[auth-sdk] Token refresh response is not valid JSON, status:", response.status);
|
|
344
|
-
this.onAuthRefresh?.(false);
|
|
345
|
-
this.tokenRefreshPromise = null;
|
|
346
|
-
this.refreshTokenStorage?.clearAuthStorage();
|
|
347
|
-
return fetch(input, requestInit);
|
|
348
|
-
}
|
|
349
|
-
const graphqlErrors = res.errors;
|
|
350
|
-
const token = res.data?.tokenRefresh?.token;
|
|
351
|
-
const refreshErrors = res.data?.tokenRefresh?.errors;
|
|
364
|
+
const res = await response.clone().json();
|
|
365
|
+
const {
|
|
366
|
+
errors: graphqlErrors,
|
|
367
|
+
data: {
|
|
368
|
+
tokenRefresh: { errors, token }
|
|
369
|
+
}
|
|
370
|
+
} = res;
|
|
352
371
|
this.onAuthRefresh?.(false);
|
|
353
|
-
if (
|
|
354
|
-
console.warn("[auth-sdk] Token refresh failed:", JSON.stringify({
|
|
355
|
-
graphqlErrors: graphqlErrors ?? [],
|
|
356
|
-
refreshErrors: refreshErrors ?? [],
|
|
357
|
-
hasToken: Boolean(token),
|
|
358
|
-
httpStatus: response.status,
|
|
359
|
-
rawData: res.data ?? null
|
|
360
|
-
}));
|
|
372
|
+
if (errors?.length || graphqlErrors?.length || !token) {
|
|
361
373
|
this.tokenRefreshPromise = null;
|
|
362
374
|
this.refreshTokenStorage?.clearAuthStorage();
|
|
363
375
|
return fetch(input, requestInit);
|
|
@@ -367,32 +379,10 @@ var SaleorAuthClient = class {
|
|
|
367
379
|
this.tokenRefreshPromise = null;
|
|
368
380
|
return this.runAuthorizedRequest(input, requestInit, additionalParams);
|
|
369
381
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
const origHeaders = new Headers(requestInit.headers);
|
|
375
|
-
for (const [key, value] of origHeaders.entries()) {
|
|
376
|
-
if (key !== "host" && key !== "content-type") {
|
|
377
|
-
refreshHeaders[key] = value;
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
const refreshBody = JSON.stringify({
|
|
382
|
-
query: TOKEN_REFRESH.toString(),
|
|
383
|
-
variables: { refreshToken }
|
|
384
|
-
});
|
|
385
|
-
console.log("[auth-sdk] Token refresh request:", JSON.stringify({
|
|
386
|
-
url: this.saleorApiUrl,
|
|
387
|
-
headers: refreshHeaders,
|
|
388
|
-
bodyLength: refreshBody.length,
|
|
389
|
-
bodyPreview: refreshBody.slice(0, 200)
|
|
390
|
-
}));
|
|
391
|
-
this.tokenRefreshPromise = fetch(this.saleorApiUrl, {
|
|
392
|
-
method: "POST",
|
|
393
|
-
headers: refreshHeaders,
|
|
394
|
-
body: refreshBody
|
|
395
|
-
});
|
|
382
|
+
this.tokenRefreshPromise = fetch(
|
|
383
|
+
this.saleorApiUrl,
|
|
384
|
+
getRequestData(TOKEN_REFRESH, { refreshToken }, { ...this.defaultRequestInit, ...requestInit })
|
|
385
|
+
);
|
|
396
386
|
return this.fetchWithAuth(input, requestInit, additionalParams);
|
|
397
387
|
};
|
|
398
388
|
handleSignIn = async (response) => {
|
package/dist/index.mjs
CHANGED
|
@@ -2,8 +2,8 @@ import {
|
|
|
2
2
|
SaleorAuthProvider
|
|
3
3
|
} from "../chunk-74GMXOK4.mjs";
|
|
4
4
|
import "../chunk-NAQNA6DI.mjs";
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-
|
|
5
|
+
import "../chunk-GFXR244N.mjs";
|
|
6
|
+
import "../chunk-B326YIV6.mjs";
|
|
7
7
|
import "../chunk-263DHBMK.mjs";
|
|
8
8
|
import "../chunk-UDLCOX6B.mjs";
|
|
9
9
|
import "../chunk-7JTFMRQS.mjs";
|
package/dist/react/context.mjs
CHANGED
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
createSafeContext,
|
|
4
4
|
useSaleorAuthContext
|
|
5
5
|
} from "../chunk-NAQNA6DI.mjs";
|
|
6
|
-
import "../chunk-
|
|
7
|
-
import "../chunk-
|
|
6
|
+
import "../chunk-GFXR244N.mjs";
|
|
7
|
+
import "../chunk-B326YIV6.mjs";
|
|
8
8
|
import "../chunk-263DHBMK.mjs";
|
|
9
9
|
import "../chunk-UDLCOX6B.mjs";
|
|
10
10
|
import "../chunk-7JTFMRQS.mjs";
|
package/dist/react/index.mjs
CHANGED
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
import {
|
|
13
13
|
useSaleorExternalAuth
|
|
14
14
|
} from "../chunk-Q3UFWDCC.mjs";
|
|
15
|
-
import "../chunk-
|
|
16
|
-
import "../chunk-
|
|
15
|
+
import "../chunk-GFXR244N.mjs";
|
|
16
|
+
import "../chunk-B326YIV6.mjs";
|
|
17
17
|
import "../chunk-263DHBMK.mjs";
|
|
18
18
|
import "../chunk-T35JF4IS.mjs";
|
|
19
19
|
import "../chunk-KLIEZ4V4.mjs";
|