supertokens-react-native
Version:
React Native SDK for SuperTokens
164 lines (163 loc) • 7.46 kB
JavaScript
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());
});
};
import AsyncStorage from "@react-native-async-storage/async-storage";
import { decode as atob } from "base-64";
import { getLocalSessionState, saveLastAccessTokenUpdate, setToken } from "./utils";
import { logDebugMessage } from "./logger";
import AntiCSRF from "./antiCsrf";
const FRONT_TOKEN_KEY = "supertokens-rn-front-token-key";
const FRONT_TOKEN_NAME = "sFrontToken";
class FrontToken {
constructor() {}
static getFrontTokenFromStorage() {
return __awaiter(this, void 0, void 0, function*() {
logDebugMessage("getFrontTokenFromStorage: called");
let frontTokenFromStorage = yield AsyncStorage.getItem(FRONT_TOKEN_KEY);
if (frontTokenFromStorage !== null) {
let value = "; " + frontTokenFromStorage;
if (value.includes("; " + FRONT_TOKEN_NAME + "=")) {
// This means that the storage had a cookie string instead of a simple key value (legacy sessions)
let parts = value.split("; " + FRONT_TOKEN_NAME + "=");
let last = parts.pop();
if (last !== undefined) {
let splitForExpiry = frontTokenFromStorage.split(";");
let expiry = Date.parse(splitForExpiry[1].split("=")[1]);
let currentTime = Date.now();
if (expiry < currentTime) {
yield FrontToken.removeToken();
return null;
}
let temp = last.split(";").shift();
if (temp !== undefined) {
// We update storage to set just the value and return it
yield FrontToken.setFrontToken(temp);
return temp;
}
// This means that the storage had a cookie string but it was malformed somehow
return null;
}
}
return frontTokenFromStorage;
}
return null;
});
}
static getFrontToken() {
return __awaiter(this, void 0, void 0, function*() {
logDebugMessage("getFrontToken: called");
if ((yield getLocalSessionState()).status !== "EXISTS") {
logDebugMessage("getFrontToken: Returning because sIRTFrontend != EXISTS");
return null;
}
let token = yield this.getFrontTokenFromStorage();
logDebugMessage("getFrontToken: returning: " + token);
return token;
});
}
static getTokenInfo() {
return __awaiter(this, void 0, void 0, function*() {
logDebugMessage("FrontToken.getTokenInfo: called");
let frontToken = yield this.getFrontToken();
if (frontToken === null) {
if ((yield getLocalSessionState()).status === "EXISTS") {
// this means that the id refresh token has been set, so we must
// wait for this to be set or removed
yield new Promise(resolve => {
FrontToken.waiters.push(resolve);
});
return FrontToken.getTokenInfo();
} else {
return undefined;
}
}
const parsedToken = JSON.parse(decodeURIComponent(escape(atob(frontToken))));
logDebugMessage("FrontToken.getTokenInfo: returning ate: " + parsedToken.ate);
logDebugMessage("FrontToken.getTokenInfo: returning uid: " + parsedToken.uid);
logDebugMessage("FrontToken.getTokenInfo: returning up: " + parsedToken.up);
return parsedToken;
});
}
static setFrontToken(frontToken) {
return __awaiter(this, void 0, void 0, function*() {
logDebugMessage("setFrontToken: called");
function setFrontTokenToStorage(frontToken) {
return __awaiter(this, void 0, void 0, function*() {
if (frontToken === undefined) {
yield AsyncStorage.removeItem(FRONT_TOKEN_KEY);
} else {
yield AsyncStorage.setItem(FRONT_TOKEN_KEY, frontToken);
}
});
}
yield setFrontTokenToStorage(frontToken);
});
}
static removeToken() {
return __awaiter(this, void 0, void 0, function*() {
logDebugMessage("FrontToken.removeToken: called");
yield this.setFrontToken(undefined);
yield setToken("access", "");
yield setToken("refresh", "");
yield AntiCSRF.removeToken();
FrontToken.waiters.forEach(f => f(undefined));
FrontToken.waiters = [];
});
}
static setItem(frontToken) {
return __awaiter(this, void 0, void 0, function*() {
// We update the refresh attempt info here as well, since this means that we've updated the session in some way
// This could be both by a refresh call or if the access token was updated in a custom endpoint
// By saving every time the access token has been updated, we cause an early retry if
// another request has failed with a 401 with the previous access token and the token still exists.
// Check the start and end of onUnauthorisedResponse
// As a side-effect we reload the anti-csrf token to check if it was changed by another tab.
yield saveLastAccessTokenUpdate();
if (frontToken === "remove") {
return FrontToken.removeToken();
}
logDebugMessage("FrontToken.setItem: called");
yield this.setFrontToken(frontToken);
FrontToken.waiters.forEach(f => f(undefined));
FrontToken.waiters = [];
});
}
static doesTokenExists() {
return __awaiter(this, void 0, void 0, function*() {
const frontToken = yield this.getFrontTokenFromStorage();
return frontToken !== null;
});
}
}
// these are waiters for when the idRefreshToken has been set, but this token has
// not yet been set. Once this token is set or removed, the waiters are resolved.
FrontToken.waiters = [];
export default FrontToken;