// general implementation to call entities using our OAuth login framework class Network { constructor(clientId, secret, tenant) { this.clientId = clientId; this.secret = secret; this.tenant = tenant; this.baseUrl = window.location.protocol + "//" + window.location.host + "/"; this.TTL = 1000 * 60 * 5; } _store(token) { window.sessionStorage[this.clientId + "-access_token"] = token.access_token; window.sessionStorage[this.clientId + "-refresh_token"] = token.refresh_token; window.sessionStorage[this.clientId + "-expires"] = Date.now() + token.expires_in * 1000; }; _token() { return { "access_token": window.sessionStorage[this.clientId + "-access_token"], "refresh_token": window.sessionStorage[this.clientId + "-refresh_token"], "expires": window.sessionStorage[this.clientId + "-expires"] }; }; _clear() { window.sessionStorage.removeItem(this.clientId + "-access_token"); window.sessionStorage.removeItem(this.clientId + "-refresh_token"); window.sessionStorage.removeItem(this.clientId + "-expires"); }; isLoggedIn() { return this._token().access_token != null; }; loginUrl() { const redirect_url = window.location.href.split('?')[0]; return this.baseUrl + `oauth?redirect_url=${redirect_url}&response_type=token&client_id=${this.clientId}&state=ras&tenant=${this.tenant}`; }; logOut() { this._clear(); } _authorizationCode(code) { const redirect_url = window.location.href.split('?')[0]; const data = { "code": code, "redirect_url": redirect_url, "grant_type": "authorization_code", "client_id": this.clientId, "client_secret": this.secret, "tenant": this.tenant }; const request = new Request(this.baseUrl + "oauth/token", { method: "POST", body: new URLSearchParams(data), headers: { "Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json" }, cache: 'no-cache', }); return fetch(request) .then((response) => { if (response.ok) { return response.json(); } else { throw Error(response.statusText); } }) .then((token) => { this._store(token); return token; }); }; _refresh() { console.log("Refresh"); const data = { "grant_type": "refresh_token", "refresh_token": this._token().refresh_token, "client_id": this.clientId, "client_secret": this.secret, "tenant": this.tenant }; const request = new Request(this.baseUrl + "oauth/token", { method: "POST", body: new URLSearchParams(data), headers: { "Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json" }, cache: 'no-cache', }); return fetch(request) .then((response) => { if (response.ok) { return response.json(); } else { throw Error(response.statusText); } }) .then((token) => { this._store(token); return token; }); }; request(method, entity, query, data) { const ttl = this._token().expires - Date.now() if (ttl <= this.TTL) { return this._refresh() .then(() => { return this.request(method, entity, query, data); }); } console.log(`Request entity ${entity}, ttl: ${ttl / 1000 / 60}m`); const request = new Request(this.baseUrl + entity + query, { method: method, body: JSON.stringify(data), headers: { "Content-Type": "application/json", "Authorization": `Bearer ${this._token().access_token}`, "X-Navajo-Tenant": this.tenant }, cache: 'no-cache', }); return fetch(request) .then((response) => { if (response.ok) { if (entity.endsWith(".bin")) { return response.text() } else { return response.json() } } if (response.status == 401) { return this._refresh() .then(() => { return this.request(method, entity, data) }); } if (response.status == 420) { return response.json() .then((validationError) => { throw new Error(Object.values(validationError.Violations).join("\n")); }); } throw new Error("Something went wrong, please try again later"); }); }; // Handle OAuth callback checkAuthorizationCode(loginSuccessUrl) { const params = new URLSearchParams(window.location.search); // If code is available in the query we should exchange it with for an access token. if (params.has("code")) { const code = params.get('code'); this._authorizationCode(code) .then(() => { window.location = loginSuccessUrl; }); } } }