1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-17 16:53:34 +00:00

[PM-6400] Move core FIDO2 code from vault to platform ownership (#8044)

* [PM-6400] Move core FIDO2 code from vault to platform ownership

- lib/common/vault/abstractions/fido2 -> lib/common/platform/abstractions/fido2
- lib/common/vault/services/fido2 -> lib/common/platform/services/fido2

* [PM-6400] fix: wrong imports
This commit is contained in:
Andreas Coroiu
2024-05-14 16:08:41 +02:00
committed by GitHub
parent 79a0b0d46d
commit 7f91e84456
28 changed files with 46 additions and 46 deletions

View File

@@ -0,0 +1,144 @@
/**
* This class represents an abstraction of the WebAuthn Authenticator model as described by W3C:
* https://www.w3.org/TR/webauthn-3/#sctn-authenticator-model
*
* The authenticator provides key management and cryptographic signatures.
*/
export abstract class Fido2AuthenticatorService {
/**
* Create and save a new credential as described in:
* https://www.w3.org/TR/webauthn-3/#sctn-op-make-cred
*
* @param params Parameters for creating a new credential
* @param abortController An AbortController that can be used to abort the operation.
* @returns A promise that resolves with the new credential and an attestation signature.
**/
makeCredential: (
params: Fido2AuthenticatorMakeCredentialsParams,
tab: chrome.tabs.Tab,
abortController?: AbortController,
) => Promise<Fido2AuthenticatorMakeCredentialResult>;
/**
* Generate an assertion using an existing credential as describe in:
* https://www.w3.org/TR/webauthn-3/#sctn-op-get-assertion
*
* @param params Parameters for generating an assertion
* @param abortController An AbortController that can be used to abort the operation.
* @returns A promise that resolves with the asserted credential and an assertion signature.
*/
getAssertion: (
params: Fido2AuthenticatorGetAssertionParams,
tab: chrome.tabs.Tab,
abortController?: AbortController,
) => Promise<Fido2AuthenticatorGetAssertionResult>;
}
export enum Fido2AlgorithmIdentifier {
ES256 = -7,
RS256 = -257,
}
export enum Fido2AuthenticatorErrorCode {
Unknown = "UnknownError",
NotSupported = "NotSupportedError",
InvalidState = "InvalidStateError",
NotAllowed = "NotAllowedError",
Constraint = "ConstraintError",
}
export class Fido2AuthenticatorError extends Error {
constructor(readonly errorCode: Fido2AuthenticatorErrorCode) {
super(errorCode);
}
}
export interface PublicKeyCredentialDescriptor {
id: BufferSource;
transports?: ("ble" | "hybrid" | "internal" | "nfc" | "usb")[];
type: "public-key";
}
/**
* Parameters for {@link Fido2AuthenticatorService.makeCredential}
*
* This interface represents the input parameters described in
* https://www.w3.org/TR/webauthn-3/#sctn-op-make-cred
*/
export interface Fido2AuthenticatorMakeCredentialsParams {
/** The hash of the serialized client data, provided by the client. */
hash: BufferSource;
/** The Relying Party's PublicKeyCredentialRpEntity. */
rpEntity: {
name: string;
id?: string;
};
/** The user accounts PublicKeyCredentialUserEntity, containing the user handle given by the Relying Party. */
userEntity: {
id: BufferSource;
name?: string;
displayName?: string;
icon?: string;
};
/** A sequence of pairs of PublicKeyCredentialType and public key algorithms (COSEAlgorithmIdentifier) requested by the Relying Party. This sequence is ordered from most preferred to least preferred. The authenticator makes a best-effort to create the most preferred credential that it can. */
credTypesAndPubKeyAlgs: {
alg: number;
type: "public-key"; // not used
}[];
/** An OPTIONAL list of PublicKeyCredentialDescriptor objects provided by the Relying Party with the intention that, if any of these are known to the authenticator, it SHOULD NOT create a new credential. excludeCredentialDescriptorList contains a list of known credentials. */
excludeCredentialDescriptorList?: PublicKeyCredentialDescriptor[];
/** A map from extension identifiers to their authenticator extension inputs, created by the client based on the extensions requested by the Relying Party, if any. */
extensions?: {
appid?: string;
appidExclude?: string;
credProps?: boolean;
uvm?: boolean;
};
/** A Boolean value that indicates that individually-identifying attestation MAY be returned by the authenticator. */
enterpriseAttestationPossible?: boolean; // Ignored by bitwarden at the moment
/** The effective resident key requirement for credential creation, a Boolean value determined by the client. Resident is synonymous with discoverable. */
requireResidentKey: boolean;
requireUserVerification: boolean;
/** Forwarded to user interface */
fallbackSupported: boolean;
/** The constant Boolean value true. It is included here as a pseudo-parameter to simplify applying this abstract authenticator model to implementations that may wish to make a test of user presence optional although WebAuthn does not. */
// requireUserPresence: true; // Always required
}
export interface Fido2AuthenticatorMakeCredentialResult {
credentialId: BufferSource;
attestationObject: BufferSource;
authData: BufferSource;
publicKey: BufferSource;
publicKeyAlgorithm: number;
}
/**
* Parameters for {@link Fido2AuthenticatorService.getAssertion}
* This interface represents the input parameters described in
* https://www.w3.org/TR/webauthn-3/#sctn-op-get-assertion
*/
export interface Fido2AuthenticatorGetAssertionParams {
/** The callers RP ID, as determined by the user agent and the client. */
rpId: string;
/** The hash of the serialized client data, provided by the client. */
hash: BufferSource;
allowCredentialDescriptorList: PublicKeyCredentialDescriptor[];
/** The effective user verification requirement for assertion, a Boolean value provided by the client. */
requireUserVerification: boolean;
/** The constant Boolean value true. It is included here as a pseudo-parameter to simplify applying this abstract authenticator model to implementations that may wish to make a test of user presence optional although WebAuthn does not. */
// requireUserPresence: boolean; // Always required
extensions: unknown;
/** Forwarded to user interface */
fallbackSupported: boolean;
}
export interface Fido2AuthenticatorGetAssertionResult {
selectedCredential: {
id: Uint8Array;
userHandle?: Uint8Array;
};
authenticatorData: Uint8Array;
signature: Uint8Array;
}

View File

@@ -0,0 +1,180 @@
export const UserRequestedFallbackAbortReason = "UserRequestedFallback";
export type UserVerification = "discouraged" | "preferred" | "required";
/**
* This class represents an abstraction of the WebAuthn Client as described by W3C:
* https://www.w3.org/TR/webauthn-3/#webauthn-client
*
* The WebAuthn Client is an intermediary entity typically implemented in the user agent
* (in whole, or in part). Conceptually, it underlies the Web Authentication API and embodies
* the implementation of the Web Authentication API's operations.
*
* It is responsible for both marshalling the inputs for the underlying authenticator operations,
* and for returning the results of the latter operations to the Web Authentication API's callers.
*/
export abstract class Fido2ClientService {
isFido2FeatureEnabled: (hostname: string, origin: string) => Promise<boolean>;
/**
* Allows WebAuthn Relying Party scripts to request the creation of a new public key credential source.
* For more information please see: https://www.w3.org/TR/webauthn-3/#sctn-createCredential
*
* @param params The parameters for the credential creation operation.
* @param abortController An AbortController that can be used to abort the operation.
* @returns A promise that resolves with the new credential.
*/
createCredential: (
params: CreateCredentialParams,
tab: chrome.tabs.Tab,
abortController?: AbortController,
) => Promise<CreateCredentialResult>;
/**
* Allows WebAuthn Relying Party scripts to discover and use an existing public key credential, with the users consent.
* Relying Party script can optionally specify some criteria to indicate what credential sources are acceptable to it.
* For more information please see: https://www.w3.org/TR/webauthn-3/#sctn-getAssertion
*
* @param params The parameters for the credential assertion operation.
* @param abortController An AbortController that can be used to abort the operation.
* @returns A promise that resolves with the asserted credential.
*/
assertCredential: (
params: AssertCredentialParams,
tab: chrome.tabs.Tab,
abortController?: AbortController,
) => Promise<AssertCredentialResult>;
}
/**
* Parameters for creating a new credential.
*/
export interface CreateCredentialParams {
/** The Relaying Parties origin, see: https://html.spec.whatwg.org/multipage/browsers.html#concept-origin */
origin: string;
/**
* A value which is true if and only if the callers environment settings object is same-origin with its ancestors.
* It is false if caller is cross-origin.
* */
sameOriginWithAncestors: boolean;
/** The Relying Party's preference for attestation conveyance */
attestation?: "direct" | "enterprise" | "indirect" | "none";
/** The Relying Party's requirements of the authenticator used in the creation of the credential. */
authenticatorSelection?: {
// authenticatorAttachment?: AuthenticatorAttachment; // not used
requireResidentKey?: boolean;
residentKey?: "discouraged" | "preferred" | "required";
userVerification?: UserVerification;
};
/** Challenge intended to be used for generating the newly created credential's attestation object. */
challenge: string; // b64 encoded
/**
* This member is intended for use by Relying Parties that wish to limit the creation of multiple credentials for
* the same account on a single authenticator. The client is requested to return an error if the new credential would
* be created on an authenticator that also contains one of the credentials enumerated in this parameter.
* */
excludeCredentials?: {
id: string; // b64 encoded
transports?: ("ble" | "hybrid" | "internal" | "nfc" | "usb")[];
type: "public-key";
}[];
/**
* This member contains additional parameters requesting additional processing by the client and authenticator.
**/
extensions?: {
appid?: string; // Not supported
appidExclude?: string; // Not supported
uvm?: boolean; // Not supported
credProps?: boolean;
};
/**
* This member contains information about the desired properties of the credential to be created.
* The sequence is ordered from most preferred to least preferred.
* The client makes a best-effort to create the most preferred credential that it can.
*/
pubKeyCredParams: PublicKeyCredentialParam[];
/** Data about the Relying Party responsible for the request. */
rp: {
id?: string;
name: string;
};
/** Data about the user account for which the Relying Party is requesting attestation. */
user: {
id: string; // b64 encoded
displayName: string;
name: string;
};
/** Forwarded to user interface */
fallbackSupported: boolean;
/**
* This member specifies a time, in milliseconds, that the caller is willing to wait for the call to complete.
* This is treated as a hint, and MAY be overridden by the client.
**/
timeout?: number;
}
/**
* The result of creating a new credential.
*/
export interface CreateCredentialResult {
credentialId: string;
clientDataJSON: string;
attestationObject: string;
authData: string;
publicKey: string;
publicKeyAlgorithm: number;
transports: string[];
extensions: {
credProps?: {
rk: boolean;
};
};
}
/**
* Parameters for asserting a credential.
*/
export interface AssertCredentialParams {
allowedCredentialIds: string[];
rpId: string;
origin: string;
challenge: string;
userVerification?: UserVerification;
timeout: number;
sameOriginWithAncestors: boolean;
fallbackSupported: boolean;
}
/**
* The result of asserting a credential.
*/
export interface AssertCredentialResult {
credentialId: string;
clientDataJSON: string;
authenticatorData: string;
signature: string;
userHandle: string;
}
/**
* A description of a key type and algorithm.
*
* @example {
* alg: -7, // ES256
* type: "public-key"
* }
*/
export interface PublicKeyCredentialParam {
alg: number;
type: "public-key";
}
/**
* Error thrown when the user requests a fallback to the browser's built-in WebAuthn implementation.
*/
export class FallbackRequestedError extends Error {
readonly fallbackRequested = true;
constructor() {
super("FallbackRequested");
}
}

View File

@@ -0,0 +1,107 @@
/**
* Parameters used to ask the user to confirm the creation of a new credential.
*/
export interface NewCredentialParams {
/**
* The name of the credential.
*/
credentialName: string;
/**
* The name of the user.
*/
userName: string;
/**
* Whether or not the user must be verified before completing the operation.
*/
userVerification: boolean;
/**
* The relying party ID is usually the URL
*/
rpId: string;
}
/**
* Parameters used to ask the user to pick a credential from a list of existing credentials.
*/
export interface PickCredentialParams {
/**
* The IDs of the credentials that the user can pick from.
*/
cipherIds: string[];
/**
* Whether or not the user must be verified before completing the operation.
*/
userVerification: boolean;
}
/**
* This service is used to provide a user interface with which the user can control FIDO2 operations.
* It acts as a way to remote control the user interface from the background script.
*
* The service is session based and is intended to be used by the FIDO2 authenticator to open a window,
* and then use this window to ask the user for input and/or display messages to the user.
*/
export abstract class Fido2UserInterfaceService {
/**
* Creates a new session.
* Note: This will not necessarily open a window until it is needed to request something from the user.
*
* @param fallbackSupported Whether or not the browser natively supports WebAuthn.
* @param abortController An abort controller that can be used to cancel/close the session.
*/
newSession: (
fallbackSupported: boolean,
tab: chrome.tabs.Tab,
abortController?: AbortController,
) => Promise<Fido2UserInterfaceSession>;
}
export abstract class Fido2UserInterfaceSession {
/**
* Ask the user to pick a credential from a list of existing credentials.
*
* @param params The parameters to use when asking the user to pick a credential.
* @param abortController An abort controller that can be used to cancel/close the session.
* @returns The ID of the cipher that contains the credentials the user picked.
*/
pickCredential: (
params: PickCredentialParams,
) => Promise<{ cipherId: string; userVerified: boolean }>;
/**
* Ask the user to confirm the creation of a new credential.
*
* @param params The parameters to use when asking the user to confirm the creation of a new credential.
* @param abortController An abort controller that can be used to cancel/close the session.
* @returns The ID of the cipher where the new credential should be saved.
*/
confirmNewCredential: (
params: NewCredentialParams,
) => Promise<{ cipherId: string; userVerified: boolean }>;
/**
* Make sure that the vault is unlocked.
* This will open a window and ask the user to login or unlock the vault if necessary.
*/
ensureUnlockedVault: () => Promise<void>;
/**
* Inform the user that the operation was cancelled because their vault contains excluded credentials.
*
* @param existingCipherIds The IDs of the excluded credentials.
*/
informExcludedCredential: (existingCipherIds: string[]) => Promise<void>;
/**
* Inform the user that the operation was cancelled because their vault does not contain any useable credentials.
*/
informCredentialNotFound: (abortController?: AbortController) => Promise<void>;
/**
* Close the session, including any windows that may be open.
*/
close: () => void;
}