mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-22 14:39:34 +01:00
fix: migrate token refreshing to use mutex
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import http from "../utils/http";
|
import http from "../utils/http";
|
||||||
import constants from "../utils/constants";
|
import constants from "../utils/constants";
|
||||||
import { EV, EVENTS } from "../common";
|
import { EV, EVENTS } from "../common";
|
||||||
|
import { withTimeout, Mutex } from "async-mutex";
|
||||||
|
|
||||||
const ENDPOINTS = {
|
const ENDPOINTS = {
|
||||||
token: "/connect/token",
|
token: "/connect/token",
|
||||||
@@ -9,7 +10,6 @@ const ENDPOINTS = {
|
|||||||
logout: "/account/logout",
|
logout: "/account/logout",
|
||||||
};
|
};
|
||||||
|
|
||||||
var isRefreshingToken = false;
|
|
||||||
class TokenManager {
|
class TokenManager {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -17,13 +17,14 @@ class TokenManager {
|
|||||||
*/
|
*/
|
||||||
constructor(storage) {
|
constructor(storage) {
|
||||||
this._storage = storage;
|
this._storage = storage;
|
||||||
|
this._refreshTokenMutex = withTimeout(new Mutex(), 10 * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getToken(renew = true, forceRenew = false) {
|
async getToken(renew = true, forceRenew = false) {
|
||||||
let token = await this._storage.read("token");
|
let token = await this._storage.read("token");
|
||||||
if (!token) return;
|
if (!token) return;
|
||||||
if (forceRenew || (renew && this._isTokenExpired(token))) {
|
if (forceRenew || (renew && this._isTokenExpired(token))) {
|
||||||
await this._refreshToken(token);
|
await this._refreshToken();
|
||||||
return await this.getToken();
|
return await this.getToken();
|
||||||
}
|
}
|
||||||
return token;
|
return token;
|
||||||
@@ -49,29 +50,15 @@ class TokenManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async _refreshToken(token) {
|
async _refreshToken() {
|
||||||
const { refresh_token, scope } = token;
|
await this._refreshTokenMutex.runExclusive(async () => {
|
||||||
if (!refresh_token || !scope) return;
|
const token = await this.getToken(false, false);
|
||||||
|
if (!this._isTokenExpired(token)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isRefreshingToken) {
|
const { refresh_token, scope } = token;
|
||||||
return new Promise((resolve, reject) => {
|
if (!refresh_token || !scope) return;
|
||||||
EV.subscribe(EVENTS.tokenRefreshed, onTokenRefreshed, true);
|
|
||||||
|
|
||||||
function onTokenRefreshed({ success, error }) {
|
|
||||||
clearTimeout(timeout);
|
|
||||||
if (success) return resolve();
|
|
||||||
else return reject(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const timeout = setTimeout(() => {
|
|
||||||
EV.unsubscribe(EVENTS.tokenRefreshed, onTokenRefreshed);
|
|
||||||
reject("Timeout while refreshing token.");
|
|
||||||
}, 15000);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
isRefreshingToken = true;
|
|
||||||
try {
|
|
||||||
await this.saveToken(
|
await this.saveToken(
|
||||||
await http.post(`${constants.AUTH_HOST}${ENDPOINTS.token}`, {
|
await http.post(`${constants.AUTH_HOST}${ENDPOINTS.token}`, {
|
||||||
refresh_token,
|
refresh_token,
|
||||||
@@ -80,17 +67,8 @@ class TokenManager {
|
|||||||
client_id: "notesnook",
|
client_id: "notesnook",
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
EV.publish(EVENTS.tokenRefreshed, { success: true });
|
EV.publish(EVENTS.tokenRefreshed);
|
||||||
} catch (e) {
|
});
|
||||||
EV.publish(EVENTS.tokenRefreshed, {
|
|
||||||
success: false,
|
|
||||||
error: e,
|
|
||||||
});
|
|
||||||
console.error("Failed to refresh token:", e);
|
|
||||||
throw e;
|
|
||||||
} finally {
|
|
||||||
isRefreshingToken = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async revokeToken() {
|
async revokeToken() {
|
||||||
|
|||||||
Reference in New Issue
Block a user