[PM-6426] Implementing abortTimeout for Fido2ClientService using TaskSchedulerService
This commit is contained in:
parent
2f517336db
commit
f60a37fe2c
|
@ -830,6 +830,7 @@ export default class MainBackground {
|
|||
this.authService,
|
||||
this.vaultSettingsService,
|
||||
this.domainSettingsService,
|
||||
this.taskSchedulerService,
|
||||
this.logService,
|
||||
);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import { AuthService } from "../../../auth/abstractions/auth.service";
|
|||
import { AuthenticationStatus } from "../../../auth/enums/authentication-status";
|
||||
import { DomainSettingsService } from "../../../autofill/services/domain-settings.service";
|
||||
import { ConfigService } from "../../../platform/abstractions/config/config.service";
|
||||
import { TaskSchedulerService } from "../../../platform/abstractions/task-scheduler.service";
|
||||
import { Utils } from "../../../platform/misc/utils";
|
||||
import {
|
||||
Fido2AuthenticatorError,
|
||||
|
@ -34,6 +35,7 @@ describe("FidoAuthenticatorService", () => {
|
|||
let authService!: MockProxy<AuthService>;
|
||||
let vaultSettingsService: MockProxy<VaultSettingsService>;
|
||||
let domainSettingsService: MockProxy<DomainSettingsService>;
|
||||
let taskSchedulerService: MockProxy<TaskSchedulerService>;
|
||||
let client!: Fido2ClientService;
|
||||
let tab!: chrome.tabs.Tab;
|
||||
|
||||
|
@ -43,6 +45,7 @@ describe("FidoAuthenticatorService", () => {
|
|||
authService = mock<AuthService>();
|
||||
vaultSettingsService = mock<VaultSettingsService>();
|
||||
domainSettingsService = mock<DomainSettingsService>();
|
||||
taskSchedulerService = mock<TaskSchedulerService>();
|
||||
|
||||
client = new Fido2ClientService(
|
||||
authenticator,
|
||||
|
@ -50,6 +53,7 @@ describe("FidoAuthenticatorService", () => {
|
|||
authService,
|
||||
vaultSettingsService,
|
||||
domainSettingsService,
|
||||
taskSchedulerService,
|
||||
);
|
||||
configService.serverConfig$ = of({ environment: { vault: VaultUrl } } as any);
|
||||
vaultSettingsService.enablePasskeys$ = of(true);
|
||||
|
|
|
@ -6,6 +6,8 @@ import { AuthenticationStatus } from "../../../auth/enums/authentication-status"
|
|||
import { DomainSettingsService } from "../../../autofill/services/domain-settings.service";
|
||||
import { ConfigService } from "../../../platform/abstractions/config/config.service";
|
||||
import { LogService } from "../../../platform/abstractions/log.service";
|
||||
import { TaskSchedulerService } from "../../../platform/abstractions/task-scheduler.service";
|
||||
import { ScheduledTaskNames } from "../../../platform/enums/scheduled-task-name.enum";
|
||||
import { Utils } from "../../../platform/misc/utils";
|
||||
import {
|
||||
Fido2AuthenticatorError,
|
||||
|
@ -38,12 +40,26 @@ import { Fido2Utils } from "./fido2-utils";
|
|||
* It is highly recommended that the W3C specification is used a reference when reading this code.
|
||||
*/
|
||||
export class Fido2ClientService implements Fido2ClientServiceAbstraction {
|
||||
private readonly TIMEOUTS = {
|
||||
NO_VERIFICATION: {
|
||||
DEFAULT: 120000,
|
||||
MIN: 30000,
|
||||
MAX: 180000,
|
||||
},
|
||||
WITH_VERIFICATION: {
|
||||
DEFAULT: 300000,
|
||||
MIN: 30000,
|
||||
MAX: 600000,
|
||||
},
|
||||
};
|
||||
|
||||
constructor(
|
||||
private authenticator: Fido2AuthenticatorService,
|
||||
private configService: ConfigService,
|
||||
private authService: AuthService,
|
||||
private vaultSettingsService: VaultSettingsService,
|
||||
private domainSettingsService: DomainSettingsService,
|
||||
private taskSchedulerService: TaskSchedulerService,
|
||||
private logService?: LogService,
|
||||
) {}
|
||||
|
||||
|
@ -151,7 +167,7 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction {
|
|||
this.logService?.info(`[Fido2Client] Aborted with AbortController`);
|
||||
throw new DOMException("The operation either timed out or was not allowed.", "AbortError");
|
||||
}
|
||||
const timeout = setAbortTimeout(
|
||||
const timeout = await this.setAbortTimeout(
|
||||
abortController,
|
||||
params.authenticatorSelection?.userVerification,
|
||||
params.timeout,
|
||||
|
@ -200,7 +216,11 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction {
|
|||
};
|
||||
}
|
||||
|
||||
clearTimeout(timeout);
|
||||
await this.taskSchedulerService.clearScheduledTask({
|
||||
taskName: ScheduledTaskNames.fido2ClientAbortTimeout,
|
||||
timeoutId: timeout,
|
||||
});
|
||||
|
||||
return {
|
||||
credentialId: Fido2Utils.bufferToString(makeCredentialResult.credentialId),
|
||||
attestationObject: Fido2Utils.bufferToString(makeCredentialResult.attestationObject),
|
||||
|
@ -260,7 +280,11 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction {
|
|||
throw new DOMException("The operation either timed out or was not allowed.", "AbortError");
|
||||
}
|
||||
|
||||
const timeout = setAbortTimeout(abortController, params.userVerification, params.timeout);
|
||||
const timeout = await this.setAbortTimeout(
|
||||
abortController,
|
||||
params.userVerification,
|
||||
params.timeout,
|
||||
);
|
||||
|
||||
let getAssertionResult;
|
||||
try {
|
||||
|
@ -297,7 +321,10 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction {
|
|||
this.logService?.info(`[Fido2Client] Aborted with AbortController`);
|
||||
throw new DOMException("The operation either timed out or was not allowed.", "AbortError");
|
||||
}
|
||||
clearTimeout(timeout);
|
||||
await this.taskSchedulerService.clearScheduledTask({
|
||||
taskName: ScheduledTaskNames.fido2ClientAbortTimeout,
|
||||
timeoutId: timeout,
|
||||
});
|
||||
|
||||
return {
|
||||
authenticatorData: Fido2Utils.bufferToString(getAssertionResult.authenticatorData),
|
||||
|
@ -310,43 +337,29 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction {
|
|||
signature: Fido2Utils.bufferToString(getAssertionResult.signature),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const TIMEOUTS = {
|
||||
NO_VERIFICATION: {
|
||||
DEFAULT: 120000,
|
||||
MIN: 30000,
|
||||
MAX: 180000,
|
||||
},
|
||||
WITH_VERIFICATION: {
|
||||
DEFAULT: 300000,
|
||||
MIN: 30000,
|
||||
MAX: 600000,
|
||||
},
|
||||
};
|
||||
private setAbortTimeout = async (
|
||||
abortController: AbortController,
|
||||
userVerification?: UserVerification,
|
||||
timeout?: number,
|
||||
): Promise<number | NodeJS.Timeout> => {
|
||||
let clampedTimeout: number;
|
||||
|
||||
function setAbortTimeout(
|
||||
abortController: AbortController,
|
||||
userVerification?: UserVerification,
|
||||
timeout?: number,
|
||||
): number {
|
||||
let clampedTimeout: number;
|
||||
const { WITH_VERIFICATION, NO_VERIFICATION } = this.TIMEOUTS;
|
||||
if (userVerification === "required") {
|
||||
timeout = timeout ?? WITH_VERIFICATION.DEFAULT;
|
||||
clampedTimeout = Math.max(WITH_VERIFICATION.MIN, Math.min(timeout, WITH_VERIFICATION.MAX));
|
||||
} else {
|
||||
timeout = timeout ?? NO_VERIFICATION.DEFAULT;
|
||||
clampedTimeout = Math.max(NO_VERIFICATION.MIN, Math.min(timeout, NO_VERIFICATION.MAX));
|
||||
}
|
||||
|
||||
if (userVerification === "required") {
|
||||
timeout = timeout ?? TIMEOUTS.WITH_VERIFICATION.DEFAULT;
|
||||
clampedTimeout = Math.max(
|
||||
TIMEOUTS.WITH_VERIFICATION.MIN,
|
||||
Math.min(timeout, TIMEOUTS.WITH_VERIFICATION.MAX),
|
||||
return await this.taskSchedulerService.setTimeout(
|
||||
() => abortController.abort(),
|
||||
clampedTimeout,
|
||||
ScheduledTaskNames.fido2ClientAbortTimeout,
|
||||
);
|
||||
} else {
|
||||
timeout = timeout ?? TIMEOUTS.NO_VERIFICATION.DEFAULT;
|
||||
clampedTimeout = Math.max(
|
||||
TIMEOUTS.NO_VERIFICATION.MIN,
|
||||
Math.min(timeout, TIMEOUTS.NO_VERIFICATION.MAX),
|
||||
);
|
||||
}
|
||||
|
||||
return window.setTimeout(() => abortController.abort(), clampedTimeout);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue