mirror of
https://github.com/bitwarden/browser
synced 2025-12-17 00:33:44 +00:00
[EC-598] feat: implement full support for timeouts
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
export type UserVerification = "discouraged" | "preferred" | "required";
|
||||||
|
|
||||||
export interface CredentialRegistrationParams {
|
export interface CredentialRegistrationParams {
|
||||||
origin: string;
|
origin: string;
|
||||||
attestation?: "direct" | "enterprise" | "indirect" | "none";
|
attestation?: "direct" | "enterprise" | "indirect" | "none";
|
||||||
@@ -5,7 +7,7 @@ export interface CredentialRegistrationParams {
|
|||||||
// authenticatorAttachment?: AuthenticatorAttachment; // not used
|
// authenticatorAttachment?: AuthenticatorAttachment; // not used
|
||||||
requireResidentKey?: boolean;
|
requireResidentKey?: boolean;
|
||||||
residentKey?: "discouraged" | "preferred" | "required";
|
residentKey?: "discouraged" | "preferred" | "required";
|
||||||
userVerification?: "discouraged" | "preferred" | "required";
|
userVerification?: UserVerification;
|
||||||
};
|
};
|
||||||
challenge: string; // b64 encoded
|
challenge: string; // b64 encoded
|
||||||
excludeCredentials?: {
|
excludeCredentials?: {
|
||||||
@@ -48,7 +50,7 @@ export interface CredentialAssertParams {
|
|||||||
rpId: string;
|
rpId: string;
|
||||||
origin: string;
|
origin: string;
|
||||||
challenge: string;
|
challenge: string;
|
||||||
userVerification?: "discouraged" | "preferred" | "required";
|
userVerification?: UserVerification;
|
||||||
timeout: number;
|
timeout: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
CredentialRegistrationResult,
|
CredentialRegistrationResult,
|
||||||
Fido2Service as Fido2ServiceAbstraction,
|
Fido2Service as Fido2ServiceAbstraction,
|
||||||
NoCredentialFoundError,
|
NoCredentialFoundError,
|
||||||
|
UserVerification,
|
||||||
} from "../abstractions/fido2.service.abstraction";
|
} from "../abstractions/fido2.service.abstraction";
|
||||||
import { Fido2KeyView } from "../models/view/fido2-key.view";
|
import { Fido2KeyView } from "../models/view/fido2-key.view";
|
||||||
|
|
||||||
@@ -23,9 +24,18 @@ import { joseToDer } from "./ecdsa-utils";
|
|||||||
// We support self-signing, but Google won't accept it.
|
// We support self-signing, but Google won't accept it.
|
||||||
// TODO: Look into supporting self-signed packed format.
|
// TODO: Look into supporting self-signed packed format.
|
||||||
const STANDARD_ATTESTATION_FORMAT: "none" | "packed" = "none";
|
const STANDARD_ATTESTATION_FORMAT: "none" | "packed" = "none";
|
||||||
const DEFAULT_TIMEOUT = 120000;
|
const TIMEOUTS = {
|
||||||
const MIN_TIMEOUT = 30000;
|
NO_VERIFICATION: {
|
||||||
const MAX_TIMEOUT = 600000;
|
DEFAULT: 120000,
|
||||||
|
MIN: 30000,
|
||||||
|
MAX: 180000,
|
||||||
|
},
|
||||||
|
WITH_VERIFICATION: {
|
||||||
|
DEFAULT: 300000,
|
||||||
|
MIN: 30000,
|
||||||
|
MAX: 600000,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
interface BitCredential {
|
interface BitCredential {
|
||||||
credentialId: CredentialId;
|
credentialId: CredentialId;
|
||||||
@@ -54,7 +64,11 @@ export class Fido2Service implements Fido2ServiceAbstraction {
|
|||||||
// Comment: Timeouts could potentially be implemented using decorators.
|
// Comment: Timeouts could potentially be implemented using decorators.
|
||||||
// But since I try to use decorators a little as possible and only
|
// But since I try to use decorators a little as possible and only
|
||||||
// for the most generic solutions, I'm gonne leave this as is untill peer review.
|
// for the most generic solutions, I'm gonne leave this as is untill peer review.
|
||||||
const timeout = setAbortTimeout(abortController);
|
const timeout = setAbortTimeout(
|
||||||
|
abortController,
|
||||||
|
params.authenticatorSelection.userVerification,
|
||||||
|
params.timeout
|
||||||
|
);
|
||||||
|
|
||||||
const presence = await this.fido2UserInterfaceService.confirmNewCredential(
|
const presence = await this.fido2UserInterfaceService.confirmNewCredential(
|
||||||
{
|
{
|
||||||
@@ -139,7 +153,7 @@ export class Fido2Service implements Fido2ServiceAbstraction {
|
|||||||
params: CredentialAssertParams,
|
params: CredentialAssertParams,
|
||||||
abortController = new AbortController()
|
abortController = new AbortController()
|
||||||
): Promise<CredentialAssertResult> {
|
): Promise<CredentialAssertResult> {
|
||||||
const timeout = setAbortTimeout(abortController);
|
const timeout = setAbortTimeout(abortController, params.userVerification, params.timeout);
|
||||||
let credential: BitCredential | undefined;
|
let credential: BitCredential | undefined;
|
||||||
|
|
||||||
if (params.allowedCredentialIds && params.allowedCredentialIds.length > 0) {
|
if (params.allowedCredentialIds && params.allowedCredentialIds.length > 0) {
|
||||||
@@ -426,8 +440,26 @@ function authDataFlags(options: Flags): number {
|
|||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setAbortTimeout(abortController: AbortController, timeout = DEFAULT_TIMEOUT): number {
|
function setAbortTimeout(
|
||||||
// TODO: Set different timeouts depending on `userVerification` value
|
abortController: AbortController,
|
||||||
const clampedTimeout = Math.max(MIN_TIMEOUT, Math.min(timeout, MAX_TIMEOUT));
|
userVerification: UserVerification,
|
||||||
|
timeout?: number
|
||||||
|
): number {
|
||||||
|
let clampedTimeout: number;
|
||||||
|
|
||||||
|
if (userVerification === "discouraged") {
|
||||||
|
timeout = timeout ?? TIMEOUTS.NO_VERIFICATION.DEFAULT;
|
||||||
|
clampedTimeout = Math.max(
|
||||||
|
TIMEOUTS.NO_VERIFICATION.MIN,
|
||||||
|
Math.min(timeout, TIMEOUTS.NO_VERIFICATION.MAX)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
timeout = timeout ?? TIMEOUTS.WITH_VERIFICATION.DEFAULT;
|
||||||
|
clampedTimeout = Math.max(
|
||||||
|
TIMEOUTS.WITH_VERIFICATION.MIN,
|
||||||
|
Math.min(timeout, TIMEOUTS.WITH_VERIFICATION.MAX)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return window.setTimeout(() => abortController.abort(), clampedTimeout);
|
return window.setTimeout(() => abortController.abort(), clampedTimeout);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user