UNPKG

supertokens-website

Version:

frontend sdk for website to be used for auth solution.

847 lines (846 loc) 44.3 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function (t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function () { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return ( (g = { next: verb(0), throw: verb(1), return: verb(2) }), typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g ); function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if ( ((f = 1), y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) ) return t; if (((y = 0), t)) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if ( !((t = _.trys), (t = t.length > 0 && t[t.length - 1])) && (op[0] === 6 || op[0] === 2) ) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.responseErrorInterceptor = exports.responseInterceptor = exports.interceptorFunctionRequestFulfilled = void 0; var axiosError_1 = require("./axiosError"); var fetch_1 = require("./fetch"); var processState_1 = require("./processState"); var windowHandler_1 = require("./utils/windowHandler"); var logger_1 = require("./logger"); function incrementSessionRefreshAttemptCount(config) { if (config.__supertokensSessionRefreshAttempts === undefined) { config.__supertokensSessionRefreshAttempts = 0; } config.__supertokensSessionRefreshAttempts++; } function hasExceededMaxSessionRefreshAttempts(config) { if (config.__supertokensSessionRefreshAttempts === undefined) { config.__supertokensSessionRefreshAttempts = 0; } return config.__supertokensSessionRefreshAttempts >= fetch_1.default.config.maxRetryAttemptsForSessionRefresh; } function getUrlFromConfig(config) { var url = config.url === undefined ? "" : config.url; var baseURL = config.baseURL; if (baseURL !== undefined) { if (url.charAt(0) === "/" && baseURL.charAt(baseURL.length - 1) === "/") { url = baseURL + url.substr(1); } else if (url.charAt(0) !== "/" && baseURL.charAt(baseURL.length - 1) !== "/") { url = baseURL + "/" + url; } else { url = baseURL + url; } } return url; } function interceptorFunctionRequestFulfilled(config) { return __awaiter(this, void 0, void 0, function () { var url, doNotDoInterception, preRequestLSS, configWithAntiCsrf, antiCsrfToken, transferMethod; return __generator(this, function (_a) { switch (_a.label) { case 0: (0, logger_1.logDebugMessage)("interceptorFunctionRequestFulfilled: started axios interception"); url = getUrlFromConfig(config); doNotDoInterception = false; try { doNotDoInterception = typeof url === "string" && !fetch_1.default.recipeImpl.shouldDoInterceptionBasedOnUrl( url, fetch_1.default.config.apiDomain, fetch_1.default.config.sessionTokenBackendDomain ); } catch (err) { if (err.message === "Please provide a valid domain name") { (0, logger_1.logDebugMessage)( "interceptorFunctionRequestFulfilled: Trying shouldDoInterceptionBasedOnUrl with location.origin" ); // .origin gives the port as well.. doNotDoInterception = !fetch_1.default.recipeImpl.shouldDoInterceptionBasedOnUrl( windowHandler_1.default.getReferenceOrThrow().windowHandler.location.getOrigin(), fetch_1.default.config.apiDomain, fetch_1.default.config.sessionTokenBackendDomain ); } else { throw err; } } (0, logger_1.logDebugMessage)("interceptorFunctionRequestFulfilled: Value of doNotDoInterception: " + doNotDoInterception); if (doNotDoInterception) { (0, logger_1.logDebugMessage)( "interceptorFunctionRequestFulfilled: Returning config unchanged" ); // this check means that if you are using axios via inteceptor, then we only do the refresh steps if you are calling your APIs. return [2 /*return*/, config]; } (0, logger_1.logDebugMessage)("interceptorFunctionRequestFulfilled: Modifying config"); processState_1.ProcessState.getInstance().addState( processState_1.PROCESS_STATE.CALLING_INTERCEPTION_REQUEST ); return [4 /*yield*/, (0, fetch_1.getLocalSessionState)(true)]; case 1: preRequestLSS = _a.sent(); configWithAntiCsrf = config; if (!(preRequestLSS.status === "EXISTS")) return [3 /*break*/, 3]; return [4 /*yield*/, fetch_1.AntiCsrfToken.getToken(preRequestLSS.lastAccessTokenUpdate)]; case 2: antiCsrfToken = _a.sent(); if (antiCsrfToken !== undefined) { (0, logger_1.logDebugMessage)( "interceptorFunctionRequestFulfilled: Adding anti-csrf token to request" ); configWithAntiCsrf = __assign(__assign({}, configWithAntiCsrf), { headers: configWithAntiCsrf === undefined ? { "anti-csrf": antiCsrfToken } : __assign(__assign({}, configWithAntiCsrf.headers), { "anti-csrf": antiCsrfToken }) }); } _a.label = 3; case 3: if (fetch_1.default.config.autoAddCredentials && configWithAntiCsrf.withCredentials === undefined) { (0, logger_1.logDebugMessage)( "interceptorFunctionRequestFulfilled: Adding credentials include" ); configWithAntiCsrf = __assign(__assign({}, configWithAntiCsrf), { withCredentials: true }); } // adding rid for anti-csrf protection: Anti-csrf via custom header (0, logger_1.logDebugMessage)("interceptorFunctionRequestFulfilled: Adding rid header: anti-csrf (it may be overriden by the user's provided rid)"); configWithAntiCsrf = __assign(__assign({}, configWithAntiCsrf), { headers: configWithAntiCsrf === undefined ? { rid: "anti-csrf" } : __assign({ rid: "anti-csrf" }, configWithAntiCsrf.headers) }); transferMethod = fetch_1.default.config.tokenTransferMethod; (0, logger_1.logDebugMessage)("interceptorFunctionRequestFulfilled: Adding st-auth-mode header: " + transferMethod); configWithAntiCsrf.headers["st-auth-mode"] = transferMethod; return [4 /*yield*/, removeAuthHeaderIfMatchesLocalToken(configWithAntiCsrf)]; case 4: configWithAntiCsrf = _a.sent(); return [4 /*yield*/, setAuthorizationHeaderIfRequired(configWithAntiCsrf)]; case 5: _a.sent(); (0, logger_1.logDebugMessage)("interceptorFunctionRequestFulfilled: returning modified config"); return [2 /*return*/, configWithAntiCsrf]; } }); }); } exports.interceptorFunctionRequestFulfilled = interceptorFunctionRequestFulfilled; function responseInterceptor(axiosInstance) { var _this = this; return function (response) { return __awaiter(_this, void 0, void 0, function () { var doNotDoInterception, url, preRequestLSS, config; return __generator(this, function (_a) { switch (_a.label) { case 0: doNotDoInterception = false; if (!fetch_1.default.initCalled) { throw new Error("init function not called"); } (0, logger_1.logDebugMessage)("responseInterceptor: started"); (0, logger_1.logDebugMessage)("responseInterceptor: already intercepted: " + response.headers["x-supertokens-xhr-intercepted"]); url = getUrlFromConfig(response.config); try { doNotDoInterception = (typeof url === "string" && !fetch_1.default.recipeImpl.shouldDoInterceptionBasedOnUrl( url, fetch_1.default.config.apiDomain, fetch_1.default.config.sessionTokenBackendDomain )) || !!response.headers["x-supertokens-xhr-intercepted"]; } catch (err) { if (err.message === "Please provide a valid domain name") { (0, logger_1.logDebugMessage)( "responseInterceptor: Trying shouldDoInterceptionBasedOnUrl with location.origin" ); // .origin gives the port as well.. doNotDoInterception = !fetch_1.default.recipeImpl.shouldDoInterceptionBasedOnUrl( windowHandler_1.default .getReferenceOrThrow() .windowHandler.location.getOrigin(), fetch_1.default.config.apiDomain, fetch_1.default.config.sessionTokenBackendDomain ) || !!response.headers["x-supertokens-xhr-intercepted"]; } else { throw err; } } (0, logger_1.logDebugMessage)("responseInterceptor: Value of doNotDoInterception: " + doNotDoInterception); if (doNotDoInterception) { (0, logger_1.logDebugMessage)("responseInterceptor: Returning without interception"); // this check means that if you are using axios via inteceptor, then we only do the refresh steps if you are calling your APIs. return [2 /*return*/, response]; } (0, logger_1.logDebugMessage)("responseInterceptor: Interception started"); processState_1.ProcessState.getInstance().addState( processState_1.PROCESS_STATE.CALLING_INTERCEPTION_RESPONSE ); return [4 /*yield*/, (0, fetch_1.getLocalSessionState)(false)]; case 1: preRequestLSS = _a.sent(); return [4 /*yield*/, saveTokensFromHeaders(response)]; case 2: _a.sent(); (0, fetch_1.fireSessionUpdateEventsIfNecessary)(preRequestLSS.status === "EXISTS", response.status, response.headers["front-token"]); if (!(response.status === fetch_1.default.config.sessionExpiredStatusCode)) return [3 /*break*/, 3]; (0, logger_1.logDebugMessage)("responseInterceptor: Status code is: " + response.status); config = response.config; return [ 2 /*return*/, AuthHttpRequest.doRequest( function (config) { // we create an instance since we don't want to intercept this. // const instance = axios.create(); // return instance(config); return axiosInstance(config); }, config, url, response, undefined, true ) ]; case 3: if (!(response.status === fetch_1.default.config.invalidClaimStatusCode)) return [3 /*break*/, 5]; // only fire event if body is defined. return [4 /*yield*/, (0, fetch_1.onInvalidClaimResponse)(response)]; case 4: // only fire event if body is defined. _a.sent(); _a.label = 5; case 5: return [2 /*return*/, response]; } }); }); }; } exports.responseInterceptor = responseInterceptor; function responseErrorInterceptor(axiosInstance) { var _this = this; return function (error) { return __awaiter(_this, void 0, void 0, function () { var config; return __generator(this, function (_a) { switch (_a.label) { case 0: (0, logger_1.logDebugMessage)("responseErrorInterceptor: called"); (0, logger_1.logDebugMessage)("responseErrorInterceptor: already intercepted: " + (error.response && error.response.headers["x-supertokens-xhr-intercepted"])); if (error.response === undefined || error.response.headers["x-supertokens-xhr-intercepted"]) { throw error; } if ( !( error.response !== undefined && error.response.status === fetch_1.default.config.sessionExpiredStatusCode ) ) return [3 /*break*/, 1]; (0, logger_1.logDebugMessage)("responseErrorInterceptor: Status code is: " + error.response.status); config = error.config; return [ 2 /*return*/, AuthHttpRequest.doRequest( function (config) { // we create an instance since we don't want to intercept this. // const instance = axios.create(); // return instance(config); return axiosInstance(config); }, config, getUrlFromConfig(config), undefined, error, true ) ]; case 1: if ( !( error.response !== undefined && error.response.status === fetch_1.default.config.invalidClaimStatusCode ) ) return [3 /*break*/, 3]; return [4 /*yield*/, (0, fetch_1.onInvalidClaimResponse)(error.response)]; case 2: _a.sent(); _a.label = 3; case 3: throw error; } }); }); }; } exports.responseErrorInterceptor = responseErrorInterceptor; /** * @class AuthHttpRequest * @description wrapper for common http methods. */ var AuthHttpRequest = /** @class */ (function () { function AuthHttpRequest() {} var _a; _a = AuthHttpRequest; /** * @description sends the actual http request and returns a response if successful/ * If not successful due to session expiry reasons, it * attempts to call the refresh token API and if that is successful, calls this API again. * @throws Error */ AuthHttpRequest.doRequest = function (httpCall, config, url, prevResponse, prevError, viaInterceptor) { if (viaInterceptor === void 0) { viaInterceptor = false; } return __awaiter(void 0, void 0, void 0, function () { var doNotDoInterception, returnObj, preRequestLSS, configWithAntiCsrf, antiCsrfToken, transferMethod, localPrevError, localPrevResponse, response, _b, err_1, response, errorMessage, refreshResult, _c; return __generator(_a, function (_d) { switch (_d.label) { case 0: if (!fetch_1.default.initCalled) { throw Error("init function not called"); } (0, logger_1.logDebugMessage)("doRequest: called"); doNotDoInterception = false; try { doNotDoInterception = typeof url === "string" && !fetch_1.default.recipeImpl.shouldDoInterceptionBasedOnUrl( url, fetch_1.default.config.apiDomain, fetch_1.default.config.sessionTokenBackendDomain ) && viaInterceptor; } catch (err) { if (err.message === "Please provide a valid domain name") { (0, logger_1.logDebugMessage)( "doRequest: Trying shouldDoInterceptionBasedOnUrl with location.origin" ); // .origin gives the port as well.. doNotDoInterception = !fetch_1.default.recipeImpl.shouldDoInterceptionBasedOnUrl( windowHandler_1.default .getReferenceOrThrow() .windowHandler.location.getOrigin(), fetch_1.default.config.apiDomain, fetch_1.default.config.sessionTokenBackendDomain ) && viaInterceptor; } else { throw err; } } (0, logger_1.logDebugMessage)("doRequest: Value of doNotDoInterception: " + doNotDoInterception); if (!doNotDoInterception) return [3 /*break*/, 2]; (0, logger_1.logDebugMessage)("doRequest: Returning without interception"); if (prevError !== undefined) { throw prevError; } else if (prevResponse !== undefined) { return [2 /*return*/, prevResponse]; } return [4 /*yield*/, httpCall(config)]; case 1: return [2 /*return*/, _d.sent()]; case 2: (0, logger_1.logDebugMessage)("doRequest: Interception started"); return [4 /*yield*/, removeAuthHeaderIfMatchesLocalToken(config)]; case 3: config = _d.sent(); returnObj = undefined; _d.label = 4; case 4: if (!true) return [3 /*break*/, 28]; return [4 /*yield*/, (0, fetch_1.getLocalSessionState)(true)]; case 5: preRequestLSS = _d.sent(); configWithAntiCsrf = config; if (!(preRequestLSS.status === "EXISTS")) return [3 /*break*/, 7]; return [4 /*yield*/, fetch_1.AntiCsrfToken.getToken(preRequestLSS.lastAccessTokenUpdate)]; case 6: antiCsrfToken = _d.sent(); if (antiCsrfToken !== undefined) { (0, logger_1.logDebugMessage)("doRequest: Adding anti-csrf token to request"); configWithAntiCsrf = __assign(__assign({}, configWithAntiCsrf), { headers: configWithAntiCsrf === undefined ? { "anti-csrf": antiCsrfToken } : __assign(__assign({}, configWithAntiCsrf.headers), { "anti-csrf": antiCsrfToken }) }); } _d.label = 7; case 7: if ( fetch_1.default.config.autoAddCredentials && configWithAntiCsrf.withCredentials === undefined ) { (0, logger_1.logDebugMessage)("doRequest: Adding credentials include"); configWithAntiCsrf = __assign(__assign({}, configWithAntiCsrf), { withCredentials: true }); } // adding rid for anti-csrf protection: Anti-csrf via custom header (0, logger_1.logDebugMessage)("doRequest: Adding rid header: anti-csrf (May get overriden by user's rid)"); configWithAntiCsrf = __assign(__assign({}, configWithAntiCsrf), { headers: configWithAntiCsrf === undefined ? { rid: "anti-csrf" } : __assign({ rid: "anti-csrf" }, configWithAntiCsrf.headers) }); transferMethod = fetch_1.default.config.tokenTransferMethod; (0, logger_1.logDebugMessage)("doRequest: Adding st-auth-mode header: " + transferMethod); configWithAntiCsrf.headers["st-auth-mode"] = transferMethod; return [4 /*yield*/, setAuthorizationHeaderIfRequired(configWithAntiCsrf)]; case 8: _d.sent(); _d.label = 9; case 9: _d.trys.push([9, 14, , 27]); localPrevError = prevError; localPrevResponse = prevResponse; prevError = undefined; prevResponse = undefined; if (localPrevError !== undefined) { (0, logger_1.logDebugMessage)( "doRequest: Not making call because localPrevError is not undefined" ); throw localPrevError; } if (localPrevResponse !== undefined) { (0, logger_1.logDebugMessage)( "doRequest: Not making call because localPrevResponse is not undefined" ); } else { (0, logger_1.logDebugMessage)("doRequest: Making user's http call"); } if (!(localPrevResponse === undefined)) return [3 /*break*/, 11]; return [4 /*yield*/, httpCall(configWithAntiCsrf)]; case 10: _b = _d.sent(); return [3 /*break*/, 12]; case 11: _b = localPrevResponse; _d.label = 12; case 12: response = _b; // NOTE: No need to check for unauthorized response status here for session refresh, // as we only reach this point on a successful response. Axios handles error responses // by throwing an error, which is handled in the catch block. (0, logger_1.logDebugMessage)("doRequest: User's http call ended"); return [4 /*yield*/, saveTokensFromHeaders(response)]; case 13: _d.sent(); (0, fetch_1.fireSessionUpdateEventsIfNecessary)(preRequestLSS.status === "EXISTS", response.status, response.headers["front-token"]); return [2 /*return*/, response]; case 14: err_1 = _d.sent(); response = err_1.response; if (!(response !== undefined)) return [3 /*break*/, 25]; return [4 /*yield*/, saveTokensFromHeaders(response)]; case 15: _d.sent(); (0, fetch_1.fireSessionUpdateEventsIfNecessary)(preRequestLSS.status === "EXISTS", response.status, response.headers["front-token"]); if (!(response.status === fetch_1.default.config.sessionExpiredStatusCode)) return [3 /*break*/, 21]; (0, logger_1.logDebugMessage)("doRequest: Status code is: " + response.status); /** * An API may return a 401 error response even with a valid session, causing a session refresh loop in the interceptor. * To prevent this infinite loop, we break out of the loop after retrying the original request a specified number of times. * The maximum number of retry attempts is defined by maxRetryAttemptsForSessionRefresh config variable. */ if (hasExceededMaxSessionRefreshAttempts(config)) { (0, logger_1.logDebugMessage)( "doRequest: Maximum session refresh attempts reached. sessionRefreshAttempts: " .concat( config.__supertokensSessionRefreshAttempts, ", maxRetryAttemptsForSessionRefresh: " ) .concat(fetch_1.default.config.maxRetryAttemptsForSessionRefresh) ); errorMessage = "Received a 401 response from " .concat( url, ". Attempted to refresh the session and retry the request with the updated session tokens " ) .concat( fetch_1.default.config.maxRetryAttemptsForSessionRefresh, " times, but each attempt resulted in a 401 error. The maximum session refresh limit has been reached. Please investigate your API. To increase the session refresh attempts, update maxRetryAttemptsForSessionRefresh in the config." ); console.error(errorMessage); throw new Error(errorMessage); } return [4 /*yield*/, (0, fetch_1.onUnauthorisedResponse)(preRequestLSS)]; case 16: refreshResult = _d.sent(); incrementSessionRefreshAttemptCount(config); (0, logger_1.logDebugMessage)("doRequest: sessionRefreshAttempts: " + config.__supertokensSessionRefreshAttempts); if (!(refreshResult.result !== "RETRY")) return [3 /*break*/, 20]; (0, logger_1.logDebugMessage)("doRequest: Not retrying original request"); if (!(refreshResult.error !== undefined)) return [3 /*break*/, 18]; return [4 /*yield*/, (0, axiosError_1.createAxiosErrorFromFetchResp)(refreshResult.error)]; case 17: _c = _d.sent(); return [3 /*break*/, 19]; case 18: _c = err_1; _d.label = 19; case 19: // Returning refreshResult.error as an Axios Error if we attempted a refresh // Returning the original error if we did not attempt refreshing returnObj = _c; return [3 /*break*/, 28]; case 20: (0, logger_1.logDebugMessage)("doRequest: Retrying original request"); return [3 /*break*/, 24]; case 21: if (!(response.status === fetch_1.default.config.invalidClaimStatusCode)) return [3 /*break*/, 23]; return [4 /*yield*/, (0, fetch_1.onInvalidClaimResponse)(response)]; case 22: _d.sent(); _d.label = 23; case 23: throw err_1; case 24: return [3 /*break*/, 26]; case 25: throw err_1; case 26: return [3 /*break*/, 27]; case 27: return [3 /*break*/, 4]; case 28: // if it comes here, means we called break. which happens only if we have logged out. // which means it's a 401, so we throw throw returnObj; } }); }); }; return AuthHttpRequest; })(); exports.default = AuthHttpRequest; function setAuthorizationHeaderIfRequired(requestConfig) { return __awaiter(this, void 0, void 0, function () { var accessToken, refreshToken; return __generator(this, function (_b) { switch (_b.label) { case 0: if (requestConfig.headers === undefined) { // This is makes TS happy requestConfig.headers = {}; } (0, logger_1.logDebugMessage)("setAuthorizationHeaderIfRequired: adding existing tokens as header"); return [4 /*yield*/, (0, fetch_1.getTokenForHeaderAuth)("access")]; case 1: accessToken = _b.sent(); return [4 /*yield*/, (0, fetch_1.getTokenForHeaderAuth)("refresh")]; case 2: refreshToken = _b.sent(); // We don't add the refresh token because that's only required by the refresh call which is done with fetch // Still, we only add the Authorization header if both are present, because we are planning to add an option to expose the // access token to the frontend while using cookie based auth - so that users can get the access token to use if (accessToken !== undefined && refreshToken !== undefined) { if ( requestConfig.headers["Authorization"] !== undefined || requestConfig.headers["authorization"] !== undefined ) { (0, logger_1.logDebugMessage)( "setAuthorizationHeaderIfRequired: Authorization header defined by the user, not adding" ); } else { (0, logger_1.logDebugMessage)( "setAuthorizationHeaderIfRequired: added authorization header" ); requestConfig.headers = __assign(__assign({}, requestConfig.headers), { Authorization: "Bearer ".concat(accessToken) }); requestConfig.__supertokensAddedAuthHeader = true; } } else { (0, logger_1.logDebugMessage)( "setAuthorizationHeaderIfRequired: token for header based auth not found" ); } return [2 /*return*/]; } }); }); } function saveTokensFromHeaders(response) { return __awaiter(this, void 0, void 0, function () { var refreshToken, accessToken, frontToken, responseHeaders_1, antiCsrfToken, tok; return __generator(this, function (_b) { switch (_b.label) { case 0: (0, logger_1.logDebugMessage)("saveTokensFromHeaders: Saving updated tokens from the response"); refreshToken = response.headers["st-refresh-token"]; if (!(refreshToken !== undefined)) return [3 /*break*/, 2]; (0, logger_1.logDebugMessage)("saveTokensFromHeaders: saving new refresh token"); return [4 /*yield*/, (0, fetch_1.setToken)("refresh", refreshToken)]; case 1: _b.sent(); _b.label = 2; case 2: accessToken = response.headers["st-access-token"]; if (!(accessToken !== undefined)) return [3 /*break*/, 4]; (0, logger_1.logDebugMessage)("saveTokensFromHeaders: saving new access token"); return [4 /*yield*/, (0, fetch_1.setToken)("access", accessToken)]; case 3: _b.sent(); _b.label = 4; case 4: frontToken = response.headers["front-token"]; if (!(frontToken !== undefined)) return [3 /*break*/, 6]; (0, logger_1.logDebugMessage)("doRequest: Setting sFrontToken: " + frontToken); return [4 /*yield*/, fetch_1.FrontToken.setItem(frontToken)]; case 5: _b.sent(); responseHeaders_1 = new Headers(); Object.entries(response.headers).forEach(function (_b) { var key = _b[0], value = _b[1]; Array.isArray(value) ? value.forEach(function (item) { return responseHeaders_1.append(key, item); }) : responseHeaders_1.append(key, value); }); (0, fetch_1.updateClockSkewUsingFrontToken)({ frontToken: frontToken, responseHeaders: responseHeaders_1 }); _b.label = 6; case 6: antiCsrfToken = response.headers["anti-csrf"]; if (!(antiCsrfToken !== undefined)) return [3 /*break*/, 9]; return [4 /*yield*/, (0, fetch_1.getLocalSessionState)(false)]; case 7: tok = _b.sent(); if (!(tok.status === "EXISTS")) return [3 /*break*/, 9]; (0, logger_1.logDebugMessage)("doRequest: Setting anti-csrf token"); return [4 /*yield*/, fetch_1.AntiCsrfToken.setItem(tok.lastAccessTokenUpdate, antiCsrfToken)]; case 8: _b.sent(); _b.label = 9; case 9: return [2 /*return*/]; } }); }); } function removeAuthHeaderIfMatchesLocalToken(config) { return __awaiter(this, void 0, void 0, function () { var accessToken, refreshToken, authHeader, res; return __generator(this, function (_b) { switch (_b.label) { case 0: return [4 /*yield*/, (0, fetch_1.getTokenForHeaderAuth)("access")]; case 1: accessToken = _b.sent(); return [4 /*yield*/, (0, fetch_1.getTokenForHeaderAuth)("refresh")]; case 2: refreshToken = _b.sent(); authHeader = config.headers.Authorization || config.headers.authorization; if (accessToken !== undefined && refreshToken !== undefined) { if (authHeader === "Bearer ".concat(accessToken) || "__supertokensAddedAuthHeader" in config) { // We are ignoring the Authorization header set by the user in this case, because it would cause issues // If we do not ignore this, then this header would be used even if the request is being retried after a refresh, even though it contains an outdated access token. // This causes an infinite refresh loop. (0, logger_1.logDebugMessage)( "removeAuthHeaderIfMatchesLocalToken: Removing Authorization from user provided headers because it contains our access token" ); res = __assign(__assign({}, config), { headers: __assign({}, config.headers) }); delete res.headers.authorization; delete res.headers.Authorization; return [2 /*return*/, res]; } } return [2 /*return*/, config]; } }); }); }