@scayle/storefront-core 7.65.6 → 7.65.8

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @scayle/storefront-core
2
2
 
3
+ ## 7.65.8
4
+
5
+ ### Patch Changes
6
+
7
+ - Fixed an issue with handling the deprecated MD5 hash support, e.g. used for generating a user-specific basket hash, resulting in a potential application crash
8
+
9
+ ## 7.65.7
10
+
11
+ ### Patch Changes
12
+
13
+ - Delete `refreshToken` if it fails to refresh the access token
14
+
3
15
  ## 7.65.6
4
16
 
5
17
  ### Patch Changes
@@ -34,18 +34,29 @@ class CustomerAPIClient {
34
34
  if ((response.status === _httpStatus.HttpStatusCode.UNAUTHORIZED && response.headers.get("WWW-Authenticate")?.includes("invalid_token") || response.status === _httpStatus.HttpStatusCode.FORBIDDEN) && this.context.accessToken && this.context.refreshToken) {
35
35
  if (retry) {
36
36
  const client = (0, _oauth.getOAuthClient)(this.context);
37
- const tokens = await client.refreshToken({
38
- grant_type: "refresh_token",
39
- refresh_token: this.context.refreshToken
40
- });
41
- this.context.updateTokens({
42
- accessToken: tokens?.access_token,
43
- refreshToken: tokens?.refresh_token
44
- });
37
+ try {
38
+ const tokens = await client.refreshToken({
39
+ grant_type: "refresh_token",
40
+ refresh_token: this.context.refreshToken
41
+ });
42
+ this.context.updateTokens({
43
+ accessToken: tokens?.access_token,
44
+ refreshToken: tokens?.refresh_token
45
+ });
46
+ } catch (e) {
47
+ if (e instanceof _fetch.FetchError && e.response.status === _httpStatus.HttpStatusCode.UNAUTHORIZED) {
48
+ this.context.log.debug("Failed to refresh Checkout Token due to invalid refresh token. Deleting session");
49
+ await this.context.destroySession();
50
+ } else {
51
+ this.context.log.debug("Failed to refresh Checkout Token for unknown reason.");
52
+ }
53
+ throw new _fetch.FetchError(response);
54
+ }
45
55
  return await this.sendRequest(request, false);
56
+ } else {
57
+ this.context.log.debug("Invalid Checkout Token. Deleting session");
58
+ await this.context.destroySession();
46
59
  }
47
- this.context.log.debug("Invalid Checkout Token. Deleting session");
48
- await this.context.destroySession();
49
60
  }
50
61
  throw new _fetch.FetchError(response);
51
62
  }
@@ -37,7 +37,7 @@ interface PasswordUpdate {
37
37
  export declare class CustomerAPIClient {
38
38
  baseURL: string;
39
39
  context: RpcContext;
40
- private additionalHeaders;
40
+ additionalHeaders: HeadersInit | undefined;
41
41
  constructor(context: RpcContext);
42
42
  get headers(): HeadersInit;
43
43
  sendRequest<BodyType>(request: () => Promise<Response>, retry?: boolean): Promise<BodyType>;
@@ -28,18 +28,33 @@ export class CustomerAPIClient {
28
28
  ) || response.status === HttpStatusCode.FORBIDDEN) && this.context.accessToken && this.context.refreshToken) {
29
29
  if (retry) {
30
30
  const client = getOAuthClient(this.context);
31
- const tokens = await client.refreshToken({
32
- grant_type: "refresh_token",
33
- refresh_token: this.context.refreshToken
34
- });
35
- this.context.updateTokens({
36
- accessToken: tokens?.access_token,
37
- refreshToken: tokens?.refresh_token
38
- });
31
+ try {
32
+ const tokens = await client.refreshToken({
33
+ grant_type: "refresh_token",
34
+ refresh_token: this.context.refreshToken
35
+ });
36
+ this.context.updateTokens({
37
+ accessToken: tokens?.access_token,
38
+ refreshToken: tokens?.refresh_token
39
+ });
40
+ } catch (e) {
41
+ if (e instanceof FetchError && e.response.status === HttpStatusCode.UNAUTHORIZED) {
42
+ this.context.log.debug(
43
+ "Failed to refresh Checkout Token due to invalid refresh token. Deleting session"
44
+ );
45
+ await this.context.destroySession();
46
+ } else {
47
+ this.context.log.debug(
48
+ "Failed to refresh Checkout Token for unknown reason."
49
+ );
50
+ }
51
+ throw new FetchError(response);
52
+ }
39
53
  return await this.sendRequest(request, false);
54
+ } else {
55
+ this.context.log.debug("Invalid Checkout Token. Deleting session");
56
+ await this.context.destroySession();
40
57
  }
41
- this.context.log.debug("Invalid Checkout Token. Deleting session");
42
- await this.context.destroySession();
43
58
  }
44
59
  throw new FetchError(response);
45
60
  }
@@ -37,7 +37,7 @@ const getCheckoutToken = exports.getCheckoutToken = async function getCheckoutTo
37
37
  carrier,
38
38
  basketId: context.basketKey,
39
39
  campaignKey: context.campaignKey
40
- }).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"7.65.6"}`).setProtectedHeader({
40
+ }).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"7.65.8"}`).setProtectedHeader({
41
41
  alg: "HS256",
42
42
  typ: "JWT"
43
43
  }).sign(secret);
@@ -35,7 +35,7 @@ export const getCheckoutToken = async function getCheckoutToken2(jwtPayload = {}
35
35
  carrier,
36
36
  basketId: context.basketKey,
37
37
  campaignKey: context.campaignKey
38
- }).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"7.65.6"}`).setProtectedHeader({ alg: "HS256", typ: "JWT" }).sign(secret);
38
+ }).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"7.65.8"}`).setProtectedHeader({ alg: "HS256", typ: "JWT" }).sign(secret);
39
39
  return {
40
40
  accessToken: refreshedAccessToken,
41
41
  checkoutJwt
@@ -143,6 +143,12 @@ const refreshAccessToken = async context => {
143
143
  };
144
144
  } catch (error) {
145
145
  const res = convertErrorForRpcCall(error, [_constants.HttpStatusCode.BAD_REQUEST, _constants.HttpStatusCode.UNAUTHORIZED]);
146
+ if (res && res.status === _constants.HttpStatusCode.UNAUTHORIZED) {
147
+ context.log.debug("Failed to refresh Checkout Token due to invalid refresh token. Deleting session");
148
+ await context.destroySession();
149
+ } else {
150
+ context.log.debug("Failed to refresh Checkout Token for unknown reason.");
151
+ }
146
152
  if (res) {
147
153
  return res;
148
154
  }
@@ -190,6 +190,16 @@ export const refreshAccessToken = async (context) => {
190
190
  HttpStatusCode.BAD_REQUEST,
191
191
  HttpStatusCode.UNAUTHORIZED
192
192
  ]);
193
+ if (res && res.status === HttpStatusCode.UNAUTHORIZED) {
194
+ context.log.debug(
195
+ "Failed to refresh Checkout Token due to invalid refresh token. Deleting session"
196
+ );
197
+ await context.destroySession();
198
+ } else {
199
+ context.log.debug(
200
+ "Failed to refresh Checkout Token for unknown reason."
201
+ );
202
+ }
193
203
  if (res) {
194
204
  return res;
195
205
  }
@@ -9,6 +9,7 @@ var _customer = require("../../api/customer.cjs");
9
9
  var _oauth = require("../../api/oauth.cjs");
10
10
  var _constants = require("../../constants/index.cjs");
11
11
  var _errors = require("../../errors/index.cjs");
12
+ var _fetch = require("../../utils/fetch.cjs");
12
13
  const getUser = exports.getUser = function getUser2(context) {
13
14
  const {
14
15
  user,
@@ -84,18 +85,31 @@ const getAccessToken = exports.getAccessToken = async function getAccessToken2({
84
85
  return new _errors.ErrorResponse(_constants.HttpStatusCode.UNAUTHORIZED, _constants.HttpStatusMessage.UNAUTHORIZED, "No refresh token present");
85
86
  }
86
87
  const client = (0, _oauth.getOAuthClient)(context);
87
- const tokens = await client.refreshToken({
88
- grant_type: "refresh_token",
89
- refresh_token: context.refreshToken
90
- });
91
- context.updateTokens({
92
- accessToken: tokens.access_token,
93
- refreshToken: tokens.refresh_token
94
- });
95
- const user = await fetchUser({
96
- accessToken: tokens.access_token
97
- }, context);
98
- context.updateUser(user);
88
+ try {
89
+ const tokens = await client.refreshToken({
90
+ grant_type: "refresh_token",
91
+ refresh_token: context.refreshToken
92
+ });
93
+ context.updateTokens({
94
+ accessToken: tokens.access_token,
95
+ refreshToken: tokens.refresh_token
96
+ });
97
+ try {
98
+ const user = await fetchUser({
99
+ accessToken: tokens.access_token
100
+ }, context);
101
+ context.updateUser(user);
102
+ } catch {
103
+ context.log.debug("Failed to update user");
104
+ }
105
+ } catch (e) {
106
+ if (e instanceof _fetch.FetchError && e.response.status === _constants.HttpStatusCode.UNAUTHORIZED) {
107
+ context.log.debug("Failed to refresh Checkout Token due to invalid refresh token. Deleting session");
108
+ await context.destroySession();
109
+ } else {
110
+ context.log.debug("Failed to refresh Checkout Token for unknown reason.");
111
+ }
112
+ }
99
113
  }
100
114
  return context.accessToken;
101
115
  };
@@ -3,6 +3,7 @@ import { CustomerAPIClient } from "../../api/customer.mjs";
3
3
  import { getOAuthClient } from "../../api/oauth.mjs";
4
4
  import { HttpStatusCode, HttpStatusMessage } from "../../constants/index.mjs";
5
5
  import { ErrorResponse } from "../../errors/index.mjs";
6
+ import { FetchError } from "../../utils/fetch.mjs";
6
7
  const getUser = function getUser2(context) {
7
8
  const { user, accessToken, shopId } = context;
8
9
  if (user) {
@@ -74,19 +75,36 @@ const getAccessToken = async function getAccessToken2({ forceTokenRefresh = fals
74
75
  );
75
76
  }
76
77
  const client = getOAuthClient(context);
77
- const tokens = await client.refreshToken({
78
- grant_type: "refresh_token",
79
- refresh_token: context.refreshToken
80
- });
81
- context.updateTokens({
82
- accessToken: tokens.access_token,
83
- refreshToken: tokens.refresh_token
84
- });
85
- const user = await fetchUser(
86
- { accessToken: tokens.access_token },
87
- context
88
- );
89
- context.updateUser(user);
78
+ try {
79
+ const tokens = await client.refreshToken({
80
+ grant_type: "refresh_token",
81
+ refresh_token: context.refreshToken
82
+ });
83
+ context.updateTokens({
84
+ accessToken: tokens.access_token,
85
+ refreshToken: tokens.refresh_token
86
+ });
87
+ try {
88
+ const user = await fetchUser(
89
+ { accessToken: tokens.access_token },
90
+ context
91
+ );
92
+ context.updateUser(user);
93
+ } catch {
94
+ context.log.debug("Failed to update user");
95
+ }
96
+ } catch (e) {
97
+ if (e instanceof FetchError && e.response.status === HttpStatusCode.UNAUTHORIZED) {
98
+ context.log.debug(
99
+ "Failed to refresh Checkout Token due to invalid refresh token. Deleting session"
100
+ );
101
+ await context.destroySession();
102
+ } else {
103
+ context.log.debug(
104
+ "Failed to refresh Checkout Token for unknown reason."
105
+ );
106
+ }
107
+ }
90
108
  }
91
109
  return context.accessToken;
92
110
  };
@@ -5,12 +5,15 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.verifyOrderSuccessToken = exports.sha256 = exports.md5 = exports.hmac = exports.encodeBase64 = exports.decodeBase64 = exports.buildSignature = exports.buildHashPayload = void 0;
7
7
  var _uncrypto = require("uncrypto");
8
+ function stringToBoolean(value, defaultValue = false) {
9
+ return value ? value.toLowerCase() === "true" : defaultValue;
10
+ }
8
11
  const md5 = async value => {
9
- if (!process.env.SFC_OMIT_MD5) {
10
- const md5EncryptImport = await Promise.resolve().then(() => require("crypto-js/md5"));
11
- const hexImport = await Promise.resolve().then(() => require("crypto-js/enc-hex"));
12
- const md5Encrypt = md5EncryptImport.default && typeof md5EncryptImport.default === "function" ? md5EncryptImport.default : md5EncryptImport;
13
- const hex = hexImport.default && typeof hexImport.default === "function" ? hexImport.default : hexImport;
12
+ if (!stringToBoolean(process.env.SFC_OMIT_MD5)) {
13
+ const md5EncryptImport = await Promise.resolve().then(() => require("crypto-js/md5.js"));
14
+ const hexImport = await Promise.resolve().then(() => require("crypto-js/enc-hex.js"));
15
+ const md5Encrypt = md5EncryptImport.default && (typeof md5EncryptImport.default === "function" || typeof md5EncryptImport.default === "object") ? md5EncryptImport.default : md5EncryptImport;
16
+ const hex = hexImport.default && (typeof hexImport.default === "function" || typeof hexImport.default === "object") ? hexImport.default : hexImport;
14
17
  return hex.stringify(md5Encrypt(value));
15
18
  } else {
16
19
  throw Error("SFC was built without support for MD5");
@@ -1,10 +1,13 @@
1
1
  import { subtle } from "uncrypto";
2
+ function stringToBoolean(value, defaultValue = false) {
3
+ return value ? value.toLowerCase() === "true" : defaultValue;
4
+ }
2
5
  export const md5 = async (value) => {
3
- if (!process.env.SFC_OMIT_MD5) {
4
- const md5EncryptImport = await import("crypto-js/md5");
5
- const hexImport = await import("crypto-js/enc-hex");
6
- const md5Encrypt = md5EncryptImport.default && typeof md5EncryptImport.default === "function" ? md5EncryptImport.default : md5EncryptImport;
7
- const hex = hexImport.default && typeof hexImport.default === "function" ? hexImport.default : hexImport;
6
+ if (!stringToBoolean(process.env.SFC_OMIT_MD5)) {
7
+ const md5EncryptImport = await import("crypto-js/md5.js");
8
+ const hexImport = await import("crypto-js/enc-hex.js");
9
+ const md5Encrypt = md5EncryptImport.default && (typeof md5EncryptImport.default === "function" || typeof md5EncryptImport.default === "object") ? md5EncryptImport.default : md5EncryptImport;
10
+ const hex = hexImport.default && (typeof hexImport.default === "function" || typeof hexImport.default === "object") ? hexImport.default : hexImport;
8
11
  return hex.stringify(md5Encrypt(value));
9
12
  } else {
10
13
  throw Error("SFC was built without support for MD5");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scayle/storefront-core",
3
- "version": "7.65.6",
3
+ "version": "7.65.8",
4
4
  "description": "Collection of essential utilities to work with the Storefront API",
5
5
  "author": "SCAYLE Commerce Engine",
6
6
  "license": "MIT",