@shopsbuilder/auth-sdk 1.1.0 → 1.2.1

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.
@@ -3,6 +3,12 @@ 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;
6
12
  refreshTokenStorage?: StorageRepository;
7
13
  accessTokenStorage?: StorageRepository;
8
14
  tokenGracePeriod?: number;
@@ -33,7 +39,7 @@ declare class SaleorAuthClient {
33
39
  * }, [])
34
40
  * ```
35
41
  */
36
- constructor({ saleorApiUrl, refreshTokenStorage, accessTokenStorage, onAuthRefresh, tokenGracePeriod, defaultRequestInit, }: SaleorAuthClientProps);
42
+ constructor({ saleorApiUrl, storageKeyPrefix, refreshTokenStorage, accessTokenStorage, onAuthRefresh, tokenGracePeriod, defaultRequestInit, }: SaleorAuthClientProps);
37
43
  cleanup: () => void;
38
44
  private runAuthorizedRequest;
39
45
  private handleRequestWithTokenRefresh;
@@ -3,6 +3,12 @@ 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;
6
12
  refreshTokenStorage?: StorageRepository;
7
13
  accessTokenStorage?: StorageRepository;
8
14
  tokenGracePeriod?: number;
@@ -33,7 +39,7 @@ declare class SaleorAuthClient {
33
39
  * }, [])
34
40
  * ```
35
41
  */
36
- constructor({ saleorApiUrl, refreshTokenStorage, accessTokenStorage, onAuthRefresh, tokenGracePeriod, defaultRequestInit, }: SaleorAuthClientProps);
42
+ constructor({ saleorApiUrl, storageKeyPrefix, refreshTokenStorage, accessTokenStorage, onAuthRefresh, tokenGracePeriod, defaultRequestInit, }: SaleorAuthClientProps);
37
43
  cleanup: () => void;
38
44
  private runAuthorizedRequest;
39
45
  private handleRequestWithTokenRefresh;
@@ -110,10 +110,6 @@ 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
- };
117
113
  var isExpiredToken = (token, tokenGracePeriod) => {
118
114
  return getTokenExpiry(token) - tokenGracePeriod <= Date.now();
119
115
  };
@@ -287,6 +283,7 @@ var SaleorAuthClient = class {
287
283
  */
288
284
  constructor({
289
285
  saleorApiUrl,
286
+ storageKeyPrefix,
290
287
  refreshTokenStorage,
291
288
  accessTokenStorage,
292
289
  onAuthRefresh,
@@ -299,46 +296,22 @@ var SaleorAuthClient = class {
299
296
  }
300
297
  this.onAuthRefresh = onAuthRefresh;
301
298
  this.saleorApiUrl = saleorApiUrl;
299
+ const keyPrefix = storageKeyPrefix ?? saleorApiUrl;
302
300
  const refreshTokenRepo = refreshTokenStorage ?? (typeof window !== "undefined" ? window.localStorage : void 0);
303
- this.refreshTokenStorage = refreshTokenRepo ? new SaleorRefreshTokenStorageHandler(refreshTokenRepo, saleorApiUrl) : null;
301
+ this.refreshTokenStorage = refreshTokenRepo ? new SaleorRefreshTokenStorageHandler(refreshTokenRepo, keyPrefix) : null;
304
302
  const accessTokenRepo = accessTokenStorage ?? getInMemoryAccessTokenStorage();
305
- this.accessTokenStorage = new SaleorAccessTokenStorageHandler(accessTokenRepo, saleorApiUrl);
303
+ this.accessTokenStorage = new SaleorAccessTokenStorageHandler(accessTokenRepo, keyPrefix);
306
304
  }
307
305
  cleanup = () => {
308
306
  this.refreshTokenStorage?.cleanup();
309
307
  };
310
- runAuthorizedRequest = (input, init, additionalParams) => {
308
+ runAuthorizedRequest = (input, init) => {
311
309
  const token = this.accessTokenStorage.getAccessToken();
312
310
  if (!token) {
313
311
  return fetch(input, init);
314
312
  }
315
313
  const headers = new Headers(init?.headers);
316
- const getURL = (input2) => {
317
- if (typeof input2 === "string") {
318
- return input2;
319
- } else if ("url" in input2) {
320
- return input2.url;
321
- } else {
322
- return input2.href;
323
- }
324
- };
325
- const iss = getTokenIss(token);
326
- const issuerAndDomainMatch = getURL(input) === iss;
327
- const shouldAddAuthorizationHeader = issuerAndDomainMatch || additionalParams?.allowPassingTokenToThirdPartyDomains;
328
- if (!issuerAndDomainMatch) {
329
- if (shouldAddAuthorizationHeader) {
330
- console.warn(
331
- "Token's `iss` and request URL do not match but `allowPassingTokenToThirdPartyDomains` was specified."
332
- );
333
- } else {
334
- console.warn(
335
- "Token's `iss` and request URL do not match. Not adding `Authorization` header to the request."
336
- );
337
- }
338
- }
339
- if (shouldAddAuthorizationHeader) {
340
- headers.set("Authorization", `Bearer ${token}`);
341
- }
314
+ headers.set("Authorization", `Bearer ${token}`);
342
315
  return fetch(input, { ...init, headers });
343
316
  };
344
317
  handleRequestWithTokenRefresh = async (input, requestInit, additionalParams) => {
@@ -351,15 +324,28 @@ var SaleorAuthClient = class {
351
324
  this.onAuthRefresh?.(true);
352
325
  if (this.tokenRefreshPromise) {
353
326
  const response = await this.tokenRefreshPromise;
354
- const res = await response.clone().json();
355
- const {
356
- errors: graphqlErrors,
357
- data: {
358
- tokenRefresh: { errors, token }
359
- }
360
- } = res;
327
+ const responseClone = response.clone();
328
+ let res;
329
+ try {
330
+ res = await responseClone.json();
331
+ } catch {
332
+ console.error("[auth-sdk] Token refresh response is not valid JSON, status:", response.status);
333
+ this.onAuthRefresh?.(false);
334
+ this.tokenRefreshPromise = null;
335
+ this.refreshTokenStorage?.clearAuthStorage();
336
+ return fetch(input, requestInit);
337
+ }
338
+ const graphqlErrors = res.errors;
339
+ const token = res.data?.tokenRefresh?.token;
340
+ const refreshErrors = res.data?.tokenRefresh?.errors;
361
341
  this.onAuthRefresh?.(false);
362
- if (errors?.length || graphqlErrors?.length || !token) {
342
+ if (refreshErrors?.length || graphqlErrors?.length || !token) {
343
+ console.warn("[auth-sdk] Token refresh failed:", JSON.stringify({
344
+ graphqlErrors: graphqlErrors?.length ?? 0,
345
+ refreshErrors: refreshErrors?.map((e) => e.message),
346
+ hasToken: Boolean(token),
347
+ httpStatus: response.status
348
+ }));
363
349
  this.tokenRefreshPromise = null;
364
350
  this.refreshTokenStorage?.clearAuthStorage();
365
351
  return fetch(input, requestInit);
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  SaleorAuthClient,
3
3
  createSaleorAuthClient
4
- } from "./chunk-BRRF6LN3.mjs";
4
+ } from "./chunk-OGC5TPQ2.mjs";
5
5
  import "./chunk-BZFBMGPG.mjs";
6
6
  import "./chunk-263DHBMK.mjs";
7
7
  import "./chunk-UDLCOX6B.mjs";
@@ -6,7 +6,6 @@ import {
6
6
  } from "./chunk-263DHBMK.mjs";
7
7
  import {
8
8
  getRequestData,
9
- getTokenIss,
10
9
  invariant,
11
10
  isExpiredToken
12
11
  } from "./chunk-UDLCOX6B.mjs";
@@ -47,6 +46,7 @@ var SaleorAuthClient = class {
47
46
  */
48
47
  constructor({
49
48
  saleorApiUrl,
49
+ storageKeyPrefix,
50
50
  refreshTokenStorage,
51
51
  accessTokenStorage,
52
52
  onAuthRefresh,
@@ -59,46 +59,22 @@ var SaleorAuthClient = class {
59
59
  }
60
60
  this.onAuthRefresh = onAuthRefresh;
61
61
  this.saleorApiUrl = saleorApiUrl;
62
+ const keyPrefix = storageKeyPrefix ?? saleorApiUrl;
62
63
  const refreshTokenRepo = refreshTokenStorage ?? (typeof window !== "undefined" ? window.localStorage : void 0);
63
- this.refreshTokenStorage = refreshTokenRepo ? new SaleorRefreshTokenStorageHandler(refreshTokenRepo, saleorApiUrl) : null;
64
+ this.refreshTokenStorage = refreshTokenRepo ? new SaleorRefreshTokenStorageHandler(refreshTokenRepo, keyPrefix) : null;
64
65
  const accessTokenRepo = accessTokenStorage ?? getInMemoryAccessTokenStorage();
65
- this.accessTokenStorage = new SaleorAccessTokenStorageHandler(accessTokenRepo, saleorApiUrl);
66
+ this.accessTokenStorage = new SaleorAccessTokenStorageHandler(accessTokenRepo, keyPrefix);
66
67
  }
67
68
  cleanup = () => {
68
69
  this.refreshTokenStorage?.cleanup();
69
70
  };
70
- runAuthorizedRequest = (input, init, additionalParams) => {
71
+ runAuthorizedRequest = (input, init) => {
71
72
  const token = this.accessTokenStorage.getAccessToken();
72
73
  if (!token) {
73
74
  return fetch(input, init);
74
75
  }
75
76
  const headers = new 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
- if (shouldAddAuthorizationHeader) {
100
- headers.set("Authorization", `Bearer ${token}`);
101
- }
77
+ headers.set("Authorization", `Bearer ${token}`);
102
78
  return fetch(input, { ...init, headers });
103
79
  };
104
80
  handleRequestWithTokenRefresh = async (input, requestInit, additionalParams) => {
@@ -111,15 +87,28 @@ var SaleorAuthClient = class {
111
87
  this.onAuthRefresh?.(true);
112
88
  if (this.tokenRefreshPromise) {
113
89
  const response = await this.tokenRefreshPromise;
114
- const res = await response.clone().json();
115
- const {
116
- errors: graphqlErrors,
117
- data: {
118
- tokenRefresh: { errors, token }
119
- }
120
- } = res;
90
+ const responseClone = response.clone();
91
+ let res;
92
+ try {
93
+ res = await responseClone.json();
94
+ } catch {
95
+ console.error("[auth-sdk] Token refresh response is not valid JSON, status:", response.status);
96
+ this.onAuthRefresh?.(false);
97
+ this.tokenRefreshPromise = null;
98
+ this.refreshTokenStorage?.clearAuthStorage();
99
+ return fetch(input, requestInit);
100
+ }
101
+ const graphqlErrors = res.errors;
102
+ const token = res.data?.tokenRefresh?.token;
103
+ const refreshErrors = res.data?.tokenRefresh?.errors;
121
104
  this.onAuthRefresh?.(false);
122
- if (errors?.length || graphqlErrors?.length || !token) {
105
+ if (refreshErrors?.length || graphqlErrors?.length || !token) {
106
+ console.warn("[auth-sdk] Token refresh failed:", JSON.stringify({
107
+ graphqlErrors: graphqlErrors?.length ?? 0,
108
+ refreshErrors: refreshErrors?.map((e) => e.message),
109
+ hasToken: Boolean(token),
110
+ httpStatus: response.status
111
+ }));
123
112
  this.tokenRefreshPromise = null;
124
113
  this.refreshTokenStorage?.clearAuthStorage();
125
114
  return fetch(input, requestInit);
package/dist/index.js CHANGED
@@ -113,10 +113,6 @@ 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
- };
120
116
  var isExpiredToken = (token, tokenGracePeriod) => {
121
117
  return getTokenExpiry(token) - tokenGracePeriod <= Date.now();
122
118
  };
@@ -290,6 +286,7 @@ var SaleorAuthClient = class {
290
286
  */
291
287
  constructor({
292
288
  saleorApiUrl,
289
+ storageKeyPrefix,
293
290
  refreshTokenStorage,
294
291
  accessTokenStorage,
295
292
  onAuthRefresh,
@@ -302,46 +299,22 @@ var SaleorAuthClient = class {
302
299
  }
303
300
  this.onAuthRefresh = onAuthRefresh;
304
301
  this.saleorApiUrl = saleorApiUrl;
302
+ const keyPrefix = storageKeyPrefix ?? saleorApiUrl;
305
303
  const refreshTokenRepo = refreshTokenStorage ?? (typeof window !== "undefined" ? window.localStorage : void 0);
306
- this.refreshTokenStorage = refreshTokenRepo ? new SaleorRefreshTokenStorageHandler(refreshTokenRepo, saleorApiUrl) : null;
304
+ this.refreshTokenStorage = refreshTokenRepo ? new SaleorRefreshTokenStorageHandler(refreshTokenRepo, keyPrefix) : null;
307
305
  const accessTokenRepo = accessTokenStorage ?? getInMemoryAccessTokenStorage();
308
- this.accessTokenStorage = new SaleorAccessTokenStorageHandler(accessTokenRepo, saleorApiUrl);
306
+ this.accessTokenStorage = new SaleorAccessTokenStorageHandler(accessTokenRepo, keyPrefix);
309
307
  }
310
308
  cleanup = () => {
311
309
  this.refreshTokenStorage?.cleanup();
312
310
  };
313
- runAuthorizedRequest = (input, init, additionalParams) => {
311
+ runAuthorizedRequest = (input, init) => {
314
312
  const token = this.accessTokenStorage.getAccessToken();
315
313
  if (!token) {
316
314
  return fetch(input, init);
317
315
  }
318
316
  const headers = new Headers(init?.headers);
319
- const getURL = (input2) => {
320
- if (typeof input2 === "string") {
321
- return input2;
322
- } else if ("url" in input2) {
323
- return input2.url;
324
- } else {
325
- return input2.href;
326
- }
327
- };
328
- const iss = getTokenIss(token);
329
- const issuerAndDomainMatch = getURL(input) === iss;
330
- const shouldAddAuthorizationHeader = issuerAndDomainMatch || additionalParams?.allowPassingTokenToThirdPartyDomains;
331
- if (!issuerAndDomainMatch) {
332
- if (shouldAddAuthorizationHeader) {
333
- console.warn(
334
- "Token's `iss` and request URL do not match but `allowPassingTokenToThirdPartyDomains` was specified."
335
- );
336
- } else {
337
- console.warn(
338
- "Token's `iss` and request URL do not match. Not adding `Authorization` header to the request."
339
- );
340
- }
341
- }
342
- if (shouldAddAuthorizationHeader) {
343
- headers.set("Authorization", `Bearer ${token}`);
344
- }
317
+ headers.set("Authorization", `Bearer ${token}`);
345
318
  return fetch(input, { ...init, headers });
346
319
  };
347
320
  handleRequestWithTokenRefresh = async (input, requestInit, additionalParams) => {
@@ -354,15 +327,28 @@ var SaleorAuthClient = class {
354
327
  this.onAuthRefresh?.(true);
355
328
  if (this.tokenRefreshPromise) {
356
329
  const response = await this.tokenRefreshPromise;
357
- const res = await response.clone().json();
358
- const {
359
- errors: graphqlErrors,
360
- data: {
361
- tokenRefresh: { errors, token }
362
- }
363
- } = res;
330
+ const responseClone = response.clone();
331
+ let res;
332
+ try {
333
+ res = await responseClone.json();
334
+ } catch {
335
+ console.error("[auth-sdk] Token refresh response is not valid JSON, status:", response.status);
336
+ this.onAuthRefresh?.(false);
337
+ this.tokenRefreshPromise = null;
338
+ this.refreshTokenStorage?.clearAuthStorage();
339
+ return fetch(input, requestInit);
340
+ }
341
+ const graphqlErrors = res.errors;
342
+ const token = res.data?.tokenRefresh?.token;
343
+ const refreshErrors = res.data?.tokenRefresh?.errors;
364
344
  this.onAuthRefresh?.(false);
365
- if (errors?.length || graphqlErrors?.length || !token) {
345
+ if (refreshErrors?.length || graphqlErrors?.length || !token) {
346
+ console.warn("[auth-sdk] Token refresh failed:", JSON.stringify({
347
+ graphqlErrors: graphqlErrors?.length ?? 0,
348
+ refreshErrors: refreshErrors?.map((e) => e.message),
349
+ hasToken: Boolean(token),
350
+ httpStatus: response.status
351
+ }));
366
352
  this.tokenRefreshPromise = null;
367
353
  this.refreshTokenStorage?.clearAuthStorage();
368
354
  return fetch(input, requestInit);
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  SaleorAuthClient,
3
3
  createSaleorAuthClient
4
- } from "./chunk-BRRF6LN3.mjs";
4
+ } from "./chunk-OGC5TPQ2.mjs";
5
5
  import "./chunk-BZFBMGPG.mjs";
6
6
  import "./chunk-263DHBMK.mjs";
7
7
  import {
@@ -2,7 +2,7 @@ import {
2
2
  SaleorAuthProvider
3
3
  } from "../chunk-74GMXOK4.mjs";
4
4
  import "../chunk-NAQNA6DI.mjs";
5
- import "../chunk-BRRF6LN3.mjs";
5
+ import "../chunk-OGC5TPQ2.mjs";
6
6
  import "../chunk-BZFBMGPG.mjs";
7
7
  import "../chunk-263DHBMK.mjs";
8
8
  import "../chunk-UDLCOX6B.mjs";
@@ -3,7 +3,7 @@ import {
3
3
  createSafeContext,
4
4
  useSaleorAuthContext
5
5
  } from "../chunk-NAQNA6DI.mjs";
6
- import "../chunk-BRRF6LN3.mjs";
6
+ import "../chunk-OGC5TPQ2.mjs";
7
7
  import "../chunk-BZFBMGPG.mjs";
8
8
  import "../chunk-263DHBMK.mjs";
9
9
  import "../chunk-UDLCOX6B.mjs";
@@ -12,7 +12,7 @@ import {
12
12
  import {
13
13
  useSaleorExternalAuth
14
14
  } from "../chunk-Q3UFWDCC.mjs";
15
- import "../chunk-BRRF6LN3.mjs";
15
+ import "../chunk-OGC5TPQ2.mjs";
16
16
  import "../chunk-BZFBMGPG.mjs";
17
17
  import "../chunk-263DHBMK.mjs";
18
18
  import "../chunk-T35JF4IS.mjs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shopsbuilder/auth-sdk",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "Auth SDK for Saleor",
5
5
  "sideEffects": false,
6
6
  "files": ["dist/", "README.md"],