@microsoft/omnichannel-chat-sdk 2.0.2-main.6b3547d → 2.0.2-main.a1ba517

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.
@@ -57,6 +57,7 @@ declare class OmnichannelChatSDK {
57
57
  private coreServicesOrgUrl;
58
58
  private dynamicsLocationCode;
59
59
  private chatToken;
60
+ private chatTokenUnauthorizedRecovery;
60
61
  private liveChatConfig;
61
62
  private widgetSnippetBaseUrl;
62
63
  private liveChatVersion;
@@ -165,6 +166,30 @@ declare class OmnichannelChatSDK {
165
166
  getLiveChatConfig(optionalParams?: GetLiveChatConfigOptionalParams): Promise<ChatConfig>;
166
167
  getChatToken(cached?: boolean, optionalParams?: GetChatTokenOptionalParams): Promise<IChatToken>;
167
168
  setChatToken(chatToken: FetchChatTokenResponse): void;
169
+ /**
170
+ * Creates the ACS token refresher used to renew the chat token before it expires. Returns undefined, which keeps
171
+ * the existing behavior, unless renewal is enabled in the chat config, not disabled in the SDK config and
172
+ * supported by the installed OCSDK. The refresher never throws and falls back to the current token on failure.
173
+ */
174
+ private createChatTokenRefresher;
175
+ /**
176
+ * Gives the renewed chat token to the attachment client, which keeps the token it was initialized with and uses
177
+ * it for every upload and download. Runs in the background and never throws: on failure, attachments keep using
178
+ * the previous token as they did before renewal existed.
179
+ */
180
+ private refreshAttachmentClientToken;
181
+ /**
182
+ * Creates the recovery for chat requests that fail with 401 while the chat token has not
183
+ * expired. Returns null, which keeps the existing behavior, unless chat token renewal is enabled and recovery is
184
+ * not disabled in the SDK config.
185
+ */
186
+ private createChatTokenUnauthorizedRecovery;
187
+ /**
188
+ * Returns the token of the authenticated user to renew the chat token with, refreshed from the auth token
189
+ * provider when possible because the token used to start the chat may have expired. Returns undefined for
190
+ * unauthenticated chats.
191
+ */
192
+ private getAuthenticatedUserTokenForChatTokenRenewal;
168
193
  getCallingToken(): Promise<string>;
169
194
  private recordMessages;
170
195
  getMessages(): Promise<GetMessagesResponse>;
@@ -103,6 +103,8 @@ var location_1 = require("./utils/location");
103
103
  var internalUtils_1 = require("./utils/internalUtils");
104
104
  var loggerUtils_1 = require("./utils/loggerUtils");
105
105
  var parsers_1 = require("./utils/parsers");
106
+ var chatTokenUnauthorizedRecovery_1 = require("./utils/chatTokenUnauthorizedRecovery");
107
+ var chatTokenRenewal_1 = require("./utils/chatTokenRenewal");
106
108
  var platform_1 = require("./utils/platform");
107
109
  var retrieveCollectorUri_1 = require("./telemetry/retrieveCollectorUri");
108
110
  var startPolling_1 = require("./commands/startPolling");
@@ -125,6 +127,7 @@ var OmnichannelChatSDK = /** @class */ (function () {
125
127
  this.unqServicesOrgUrl = null;
126
128
  this.coreServicesOrgUrl = null;
127
129
  this.dynamicsLocationCode = null;
130
+ this.chatTokenUnauthorizedRecovery = null;
128
131
  this.widgetSnippetBaseUrl = '';
129
132
  this.dataMaskingRules = { rules: [] };
130
133
  this.authSettings = null;
@@ -1097,10 +1100,10 @@ var OmnichannelChatSDK = /** @class */ (function () {
1097
1100
  });
1098
1101
  }); };
1099
1102
  messagingClientPromise = function () { return __awaiter(_this, void 0, void 0, function () {
1100
- var chatAdapterConfig, error_8, telemetryData, _a, error_9, telemetryData, error_10, telemetryData, _b, error_11, telemetryData;
1101
- var _c, _d;
1102
- return __generator(this, function (_e) {
1103
- switch (_e.label) {
1103
+ var chatAdapterConfig, tokenRefresher, error_8, telemetryData, _a, error_9, telemetryData, error_10, telemetryData, _b, error_11, telemetryData;
1104
+ var _c, _d, _e;
1105
+ return __generator(this, function (_f) {
1106
+ switch (_f.label) {
1104
1107
  case 0:
1105
1108
  if (!(this.liveChatVersion === LiveChatVersion_1.default.V2)) return [3 /*break*/, 8];
1106
1109
  chatAdapterConfig = {
@@ -1110,18 +1113,22 @@ var OmnichannelChatSDK = /** @class */ (function () {
1110
1113
  environmentUrl: this.chatToken.acsEndpoint,
1111
1114
  pollingInterval: 30000
1112
1115
  };
1113
- _e.label = 1;
1116
+ _f.label = 1;
1114
1117
  case 1:
1115
- _e.trys.push([1, 3, , 4]);
1118
+ _f.trys.push([1, 3, , 4]);
1119
+ tokenRefresher = this.createChatTokenRefresher(chatAdapterConfig.token);
1120
+ this.chatTokenUnauthorizedRecovery = this.createChatTokenUnauthorizedRecovery(chatAdapterConfig.token, tokenRefresher);
1116
1121
  return [4 /*yield*/, ((_c = this.ACSClient) === null || _c === void 0 ? void 0 : _c.initialize({
1117
1122
  token: chatAdapterConfig.token,
1118
1123
  environmentUrl: chatAdapterConfig.environmentUrl,
1124
+ tokenRefresher: tokenRefresher,
1125
+ unauthorizedRecovery: (_d = this.chatTokenUnauthorizedRecovery) !== null && _d !== void 0 ? _d : undefined
1119
1126
  }))];
1120
1127
  case 2:
1121
- _e.sent();
1128
+ _f.sent();
1122
1129
  return [3 /*break*/, 4];
1123
1130
  case 3:
1124
- error_8 = _e.sent();
1131
+ error_8 = _f.sent();
1125
1132
  telemetryData = {
1126
1133
  RequestId: this.requestId,
1127
1134
  ChatId: this.chatToken.chatId,
@@ -1129,22 +1136,22 @@ var OmnichannelChatSDK = /** @class */ (function () {
1129
1136
  exceptionThrowers_1.default.throwMessagingClientInitializationFailure(error_8, this.scenarioMarker, TelemetryEvent_1.default.StartChat, telemetryData);
1130
1137
  return [3 /*break*/, 4];
1131
1138
  case 4:
1132
- _e.trys.push([4, 6, , 7]);
1139
+ _f.trys.push([4, 6, , 7]);
1133
1140
  _a = this;
1134
- return [4 /*yield*/, ((_d = this.ACSClient) === null || _d === void 0 ? void 0 : _d.joinConversation({
1141
+ return [4 /*yield*/, ((_e = this.ACSClient) === null || _e === void 0 ? void 0 : _e.joinConversation({
1135
1142
  id: chatAdapterConfig.id,
1136
1143
  threadId: chatAdapterConfig.threadId,
1137
1144
  pollingInterval: chatAdapterConfig.pollingInterval
1138
1145
  }))];
1139
1146
  case 5:
1140
- _a.conversation = (_e.sent());
1147
+ _a.conversation = (_f.sent());
1141
1148
  this.scenarioMarker.completeScenario(TelemetryEvent_1.default.StartChat, {
1142
1149
  RequestId: this.requestId,
1143
1150
  ChatId: this.chatToken.chatId
1144
1151
  });
1145
1152
  return [3 /*break*/, 7];
1146
1153
  case 6:
1147
- error_9 = _e.sent();
1154
+ error_9 = _f.sent();
1148
1155
  telemetryData = {
1149
1156
  RequestId: this.requestId,
1150
1157
  ChatId: this.chatToken.chatId,
@@ -1153,17 +1160,17 @@ var OmnichannelChatSDK = /** @class */ (function () {
1153
1160
  return [3 /*break*/, 7];
1154
1161
  case 7: return [3 /*break*/, 14];
1155
1162
  case 8:
1156
- _e.trys.push([8, 10, , 11]);
1163
+ _f.trys.push([8, 10, , 11]);
1157
1164
  return [4 /*yield*/, this.IC3Client.initialize({
1158
1165
  token: this.chatToken.token,
1159
1166
  regionGtms: this.chatToken.regionGTMS,
1160
1167
  visitor: true
1161
1168
  })];
1162
1169
  case 9:
1163
- _e.sent();
1170
+ _f.sent();
1164
1171
  return [3 /*break*/, 11];
1165
1172
  case 10:
1166
- error_10 = _e.sent();
1173
+ error_10 = _f.sent();
1167
1174
  telemetryData = {
1168
1175
  RequestId: this.requestId,
1169
1176
  ChatId: this.chatToken.chatId,
@@ -1171,18 +1178,18 @@ var OmnichannelChatSDK = /** @class */ (function () {
1171
1178
  exceptionThrowers_1.default.throwMessagingClientInitializationFailure(error_10, this.scenarioMarker, TelemetryEvent_1.default.StartChat, telemetryData);
1172
1179
  return [3 /*break*/, 11];
1173
1180
  case 11:
1174
- _e.trys.push([11, 13, , 14]);
1181
+ _f.trys.push([11, 13, , 14]);
1175
1182
  _b = this;
1176
1183
  return [4 /*yield*/, this.IC3Client.joinConversation(this.chatToken.chatId)];
1177
1184
  case 12:
1178
- _b.conversation = _e.sent();
1185
+ _b.conversation = _f.sent();
1179
1186
  this.scenarioMarker.completeScenario(TelemetryEvent_1.default.StartChat, {
1180
1187
  RequestId: this.requestId,
1181
1188
  ChatId: this.chatToken.chatId
1182
1189
  });
1183
1190
  return [3 /*break*/, 14];
1184
1191
  case 13:
1185
- error_11 = _e.sent();
1192
+ error_11 = _f.sent();
1186
1193
  telemetryData = {
1187
1194
  RequestId: this.requestId,
1188
1195
  ChatId: this.chatToken.chatId,
@@ -1425,6 +1432,7 @@ var OmnichannelChatSDK = /** @class */ (function () {
1425
1432
  this.conversation = null;
1426
1433
  this.requestId = (0, ocsdk_1.uuidv4)();
1427
1434
  this.chatToken = {};
1435
+ this.chatTokenUnauthorizedRecovery = null;
1428
1436
  this.reconnectId = null;
1429
1437
  if (this.IC3Client) {
1430
1438
  this.IC3Client.dispose();
@@ -1790,6 +1798,181 @@ var OmnichannelChatSDK = /** @class */ (function () {
1790
1798
  this.sessionId = this.OCClient.sessionId;
1791
1799
  }
1792
1800
  };
1801
+ /**
1802
+ * Creates the ACS token refresher used to renew the chat token before it expires. Returns undefined, which keeps
1803
+ * the existing behavior, unless renewal is enabled in the chat config, not disabled in the SDK config and
1804
+ * supported by the installed OCSDK. The refresher never throws and falls back to the current token on failure.
1805
+ */
1806
+ OmnichannelChatSDK.prototype.createChatTokenRefresher = function (initialToken) {
1807
+ var _this = this;
1808
+ var _a, _b, _c, _d, _e, _f;
1809
+ try {
1810
+ if (this.liveChatVersion !== LiveChatVersion_1.default.V2
1811
+ || ((_b = (_a = this.chatSDKConfig) === null || _a === void 0 ? void 0 : _a.chatTokenRenewal) === null || _b === void 0 ? void 0 : _b.disable) === true
1812
+ || (0, parsers_1.parseLowerCaseString)((_d = (_c = this.liveChatConfig) === null || _c === void 0 ? void 0 : _c.LcwFcbConfiguration) === null || _d === void 0 ? void 0 : _d.lcwChatTokenRenewalEnabled) !== "true"
1813
+ || typeof ((_e = this.OCClient) === null || _e === void 0 ? void 0 : _e.renewChatToken) !== "function"
1814
+ || !initialToken
1815
+ || !((_f = this.chatToken) === null || _f === void 0 ? void 0 : _f.chatId)
1816
+ || !this.requestId) {
1817
+ return undefined;
1818
+ }
1819
+ var chatId_1 = this.chatToken.chatId;
1820
+ var requestId_1 = this.requestId;
1821
+ // A reconnected chat is found by its reconnect id, not by the new request id
1822
+ var renewalId_1 = this.reconnectId || requestId_1;
1823
+ var telemetryData_1 = {
1824
+ RequestId: requestId_1,
1825
+ ChatId: chatId_1
1826
+ };
1827
+ return (0, chatTokenRenewal_1.createChatTokenRefresher)({
1828
+ initialToken: initialToken,
1829
+ chatId: chatId_1,
1830
+ isChatActive: function () { var _a; return !_this.isEndingChat && _this.requestId === requestId_1 && ((_a = _this.chatToken) === null || _a === void 0 ? void 0 : _a.chatId) === chatId_1; },
1831
+ renewChatToken: function () { return __awaiter(_this, void 0, void 0, function () {
1832
+ var renewChatTokenOptionalParams, authenticatedUserToken;
1833
+ return __generator(this, function (_a) {
1834
+ switch (_a.label) {
1835
+ case 0:
1836
+ renewChatTokenOptionalParams = {};
1837
+ return [4 /*yield*/, this.getAuthenticatedUserTokenForChatTokenRenewal()];
1838
+ case 1:
1839
+ authenticatedUserToken = _a.sent();
1840
+ if (authenticatedUserToken) {
1841
+ renewChatTokenOptionalParams.authenticatedUserToken = authenticatedUserToken;
1842
+ }
1843
+ return [2 /*return*/, this.OCClient.renewChatToken(renewalId_1, renewChatTokenOptionalParams)];
1844
+ }
1845
+ });
1846
+ }); },
1847
+ isNonRetriableStatus: function (statusCode) { return (_this.authenticatedUserToken ? chatTokenRenewal_1.authenticatedNonRetriableStatusCodes : chatTokenRenewal_1.defaultNonRetriableStatusCodes).includes(statusCode); },
1848
+ onRenewed: function (renewed) {
1849
+ var _a;
1850
+ _this.chatToken = __assign(__assign({}, _this.chatToken), { token: renewed.Token, expiresIn: renewed.ExpiresIn !== undefined && renewed.ExpiresIn !== null ? String(renewed.ExpiresIn) : _this.chatToken.expiresIn, voiceVideoCallToken: (_a = renewed.VoiceVideoCallToken) !== null && _a !== void 0 ? _a : _this.chatToken.voiceVideoCallToken });
1851
+ _this.refreshAttachmentClientToken(chatId_1);
1852
+ },
1853
+ onStart: function () { return _this.scenarioMarker.startScenario(TelemetryEvent_1.default.RenewChatToken, telemetryData_1); },
1854
+ onSuccess: function () { return _this.scenarioMarker.completeScenario(TelemetryEvent_1.default.RenewChatToken, telemetryData_1); },
1855
+ onFailure: function (reason, error) {
1856
+ var exceptionDetails = {
1857
+ response: reason,
1858
+ errorObject: error !== undefined ? "".concat(error) : undefined
1859
+ };
1860
+ _this.scenarioMarker.failScenario(TelemetryEvent_1.default.RenewChatToken, __assign(__assign({}, telemetryData_1), { ExceptionDetails: JSON.stringify(exceptionDetails) }));
1861
+ }
1862
+ });
1863
+ }
1864
+ catch (_g) {
1865
+ return undefined;
1866
+ }
1867
+ };
1868
+ /**
1869
+ * Gives the renewed chat token to the attachment client, which keeps the token it was initialized with and uses
1870
+ * it for every upload and download. Runs in the background and never throws: on failure, attachments keep using
1871
+ * the previous token as they did before renewal existed.
1872
+ */
1873
+ OmnichannelChatSDK.prototype.refreshAttachmentClientToken = function (chatId) {
1874
+ var _this = this;
1875
+ try {
1876
+ var amsClient_1 = this.AMSClient;
1877
+ var chatToken_1 = this.chatToken;
1878
+ if (!this.isAMSClientAllowed
1879
+ || this.AMSClientLoadCurrentState !== AMSClientLoadStates_1.AMSClientLoadStates.LOADED
1880
+ || !amsClient_1
1881
+ || typeof amsClient_1.initialize !== "function"
1882
+ || (chatToken_1 === null || chatToken_1 === void 0 ? void 0 : chatToken_1.chatId) !== chatId
1883
+ || !chatToken_1.token) {
1884
+ return;
1885
+ }
1886
+ var telemetryData_2 = {
1887
+ RequestId: this.requestId,
1888
+ ChatId: chatId
1889
+ };
1890
+ this.scenarioMarker.startScenario(TelemetryEvent_1.default.RefreshAttachmentClientToken, telemetryData_2);
1891
+ Promise.resolve()
1892
+ .then(function () { return amsClient_1.initialize({ chatToken: chatToken_1 }); })
1893
+ .then(function () {
1894
+ _this.scenarioMarker.completeScenario(TelemetryEvent_1.default.RefreshAttachmentClientToken, telemetryData_2);
1895
+ }, function (error) {
1896
+ _this.scenarioMarker.failScenario(TelemetryEvent_1.default.RefreshAttachmentClientToken, __assign(__assign({}, telemetryData_2), { ExceptionDetails: JSON.stringify({ errorObject: "".concat(error) }) }));
1897
+ })
1898
+ .catch(function () {
1899
+ // Telemetry failures must not surface
1900
+ });
1901
+ }
1902
+ catch (_a) {
1903
+ // Attachments keep using the previous token
1904
+ }
1905
+ };
1906
+ /**
1907
+ * Creates the recovery for chat requests that fail with 401 while the chat token has not
1908
+ * expired. Returns null, which keeps the existing behavior, unless chat token renewal is enabled and recovery is
1909
+ * not disabled in the SDK config.
1910
+ */
1911
+ OmnichannelChatSDK.prototype.createChatTokenUnauthorizedRecovery = function (initialToken, tokenRefresher) {
1912
+ var _this = this;
1913
+ var _a, _b, _c;
1914
+ try {
1915
+ if (!tokenRefresher
1916
+ || ((_b = (_a = this.chatSDKConfig) === null || _a === void 0 ? void 0 : _a.chatTokenRenewal) === null || _b === void 0 ? void 0 : _b.disableUnauthorizedRecovery) === true
1917
+ || !initialToken) {
1918
+ return null;
1919
+ }
1920
+ var telemetryData_3 = {
1921
+ RequestId: this.requestId,
1922
+ ChatId: (_c = this.chatToken) === null || _c === void 0 ? void 0 : _c.chatId
1923
+ };
1924
+ return (0, chatTokenUnauthorizedRecovery_1.createChatTokenUnauthorizedRecovery)({
1925
+ initialToken: initialToken,
1926
+ refreshToken: tokenRefresher,
1927
+ onStart: function () { return _this.scenarioMarker.startScenario(TelemetryEvent_1.default.ChatTokenUnauthorizedRecovery, telemetryData_3); },
1928
+ onSuccess: function (_source, usedExistingToken) {
1929
+ if (!usedExistingToken) {
1930
+ _this.scenarioMarker.completeScenario(TelemetryEvent_1.default.ChatTokenUnauthorizedRecovery, telemetryData_3);
1931
+ }
1932
+ },
1933
+ onFailure: function (source, reason) {
1934
+ _this.scenarioMarker.failScenario(TelemetryEvent_1.default.ChatTokenUnauthorizedRecovery, __assign(__assign({}, telemetryData_3), { ExceptionDetails: JSON.stringify({ response: reason, source: source }) }));
1935
+ }
1936
+ });
1937
+ }
1938
+ catch (_d) {
1939
+ return null;
1940
+ }
1941
+ };
1942
+ /**
1943
+ * Returns the token of the authenticated user to renew the chat token with, refreshed from the auth token
1944
+ * provider when possible because the token used to start the chat may have expired. Returns undefined for
1945
+ * unauthenticated chats.
1946
+ */
1947
+ OmnichannelChatSDK.prototype.getAuthenticatedUserTokenForChatTokenRenewal = function () {
1948
+ return __awaiter(this, void 0, void 0, function () {
1949
+ var token, _a;
1950
+ var _b;
1951
+ return __generator(this, function (_c) {
1952
+ switch (_c.label) {
1953
+ case 0:
1954
+ if (!this.authenticatedUserToken) {
1955
+ return [2 /*return*/, undefined];
1956
+ }
1957
+ if (!(typeof ((_b = this.chatSDKConfig) === null || _b === void 0 ? void 0 : _b.getAuthToken) === "function")) return [3 /*break*/, 4];
1958
+ _c.label = 1;
1959
+ case 1:
1960
+ _c.trys.push([1, 3, , 4]);
1961
+ return [4 /*yield*/, this.chatSDKConfig.getAuthToken()];
1962
+ case 2:
1963
+ token = _c.sent();
1964
+ if (typeof token === "string" && token.trim().length > 0) {
1965
+ return [2 /*return*/, token];
1966
+ }
1967
+ return [3 /*break*/, 4];
1968
+ case 3:
1969
+ _a = _c.sent();
1970
+ return [3 /*break*/, 4];
1971
+ case 4: return [2 /*return*/, this.authenticatedUserToken];
1972
+ }
1973
+ });
1974
+ });
1975
+ };
1793
1976
  OmnichannelChatSDK.prototype.getCallingToken = function () {
1794
1977
  return __awaiter(this, void 0, void 0, function () {
1795
1978
  return __generator(this, function (_a) {