From 9a5ebf94a056621a036f33395abe9f28e2612e3a Mon Sep 17 00:00:00 2001 From: Timshel Date: Fri, 24 Jan 2025 20:23:22 +0100 Subject: [PATCH] Prevent parallel refreshToken calls (#10799) Co-authored-by: Todd Martin <106564991+trmartin4@users.noreply.github.com> Co-authored-by: Patrick-Pimentel-Bitwarden --- libs/common/src/services/api.service.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/libs/common/src/services/api.service.ts b/libs/common/src/services/api.service.ts index 0f8cdf81cf..03ea969c7b 100644 --- a/libs/common/src/services/api.service.ts +++ b/libs/common/src/services/api.service.ts @@ -158,6 +158,7 @@ export class ApiService implements ApiServiceAbstraction { private deviceType: string; private isWebClient = false; private isDesktopClient = false; + private refreshTokenPromise: Promise | undefined; /** * The message (responseJson.ErrorModel.Message) that comes back from the server when a new device verification is required. @@ -1733,7 +1734,18 @@ export class ApiService implements ApiServiceAbstraction { ); } - protected async refreshToken(): Promise { + // Keep the running refreshTokenPromise to prevent parallel calls. + protected refreshToken(): Promise { + if (this.refreshTokenPromise === undefined) { + this.refreshTokenPromise = this.internalRefreshToken(); + void this.refreshTokenPromise.finally(() => { + this.refreshTokenPromise = undefined; + }); + } + return this.refreshTokenPromise; + } + + private async internalRefreshToken(): Promise { const refreshToken = await this.tokenService.getRefreshToken(); if (refreshToken != null && refreshToken !== "") { return this.refreshAccessToken();