@upbond/customauth
Version:
CustomAuth login with torus to get user private key
95 lines (83 loc) • 4.1 kB
text/typescript
import { getPublic, sign } from "@toruslabs/eccrypto";
import { get, post } from "@toruslabs/http-helpers";
import { decryptData, encryptData, keccak256 } from "@toruslabs/metadata-helpers";
import { LoginDetails } from "../handlers/interfaces";
import { REDIRECT_PARAMS_STORAGE_METHOD, REDIRECT_PARAMS_STORAGE_METHOD_TYPE } from "./enums";
import { are3PCSupported, storageAvailable } from "./helpers";
import log from "./loglevel";
class StorageHelper {
private currentStorageMethod: REDIRECT_PARAMS_STORAGE_METHOD_TYPE = REDIRECT_PARAMS_STORAGE_METHOD.LOCAL_STORAGE;
private isInitialized = false;
private storageServerUrl = "https://broadcast-server.tor.us";
constructor(serverUrl: string) {
this.storageServerUrl = serverUrl;
}
init() {
const support = are3PCSupported();
const localStorageAvailable = storageAvailable(REDIRECT_PARAMS_STORAGE_METHOD.LOCAL_STORAGE);
if (support && localStorageAvailable) {
// use local storage as default for storing stuff
this.currentStorageMethod = REDIRECT_PARAMS_STORAGE_METHOD.LOCAL_STORAGE;
} else {
// use server store as default for storing stuff
this.currentStorageMethod = REDIRECT_PARAMS_STORAGE_METHOD.SERVER;
}
this.isInitialized = true;
}
async storeLoginDetails(params: LoginDetails, scope: string): Promise<void> {
if (!this.isInitialized) throw new Error("StorageHelper is not initialized");
if (this.currentStorageMethod === REDIRECT_PARAMS_STORAGE_METHOD.SERVER) {
const privKey = keccak256(Buffer.from(scope, "utf8"));
const privKeyHex = privKey.toString("hex");
const publicKeyHex = getPublic(privKey).toString("hex");
const encData = await encryptData(privKeyHex, params);
const signature = (await sign(privKey, keccak256(Buffer.from(encData, "utf8")))).toString("hex");
await post(`${this.storageServerUrl}/store/set`, { key: publicKeyHex, data: encData, signature });
} else {
window.localStorage.setItem(`torus_login_${scope}`, JSON.stringify(params));
}
}
async retrieveLoginDetails(scope: string): Promise<LoginDetails> {
if (!this.isInitialized) throw new Error("StorageHelper is not initialized");
if (this.currentStorageMethod === REDIRECT_PARAMS_STORAGE_METHOD.SERVER) {
const privKey = keccak256(Buffer.from(scope, "utf8"));
const privKeyHex = privKey.toString("hex");
const publicKeyHex = getPublic(privKey).toString("hex");
try {
const encData: { message: string; success: boolean } = await get(`${this.storageServerUrl}/store/get?key=${publicKeyHex}`);
if (encData.message) {
const loginDetails = await decryptData<LoginDetails>(privKeyHex, encData.message);
return loginDetails;
}
} catch (error) {
if ((error as Response).status === 404) {
log.warn(error, "Session likely expired");
} else {
throw error;
}
}
}
const loginDetails = window.localStorage.getItem(`torus_login_${scope}`);
return JSON.parse(loginDetails || "{}") as LoginDetails;
}
clearLoginDetailsStorage(scope: string): void {
if (!this.isInitialized) throw new Error("StorageHelper is not initialized");
if (this.currentStorageMethod === REDIRECT_PARAMS_STORAGE_METHOD.LOCAL_STORAGE) {
window.localStorage.removeItem(`torus_login_${scope}`);
}
// No need to clear server details cause they auto expire and scope is never re-used for different login attempts
}
clearOrphanedLoginDetails(): void {
if (!this.isInitialized) throw new Error("StorageHelper is not initialized");
if (this.currentStorageMethod === REDIRECT_PARAMS_STORAGE_METHOD.LOCAL_STORAGE) {
const allStorageKeys = Object.keys(window.localStorage);
allStorageKeys.forEach((key) => {
if (key.startsWith("torus_login_")) {
window.localStorage.removeItem(key);
}
});
}
// No need to clear server details cause they auto expire and scope is never re-used for different login attempts
}
}
export default StorageHelper;