@metamask-previews/passkey-controller 0.0.0-preview-4c0846313

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/LICENSE +21 -0
  3. package/README.md +155 -0
  4. package/dist/PasskeyController.cjs +448 -0
  5. package/dist/PasskeyController.cjs.map +1 -0
  6. package/dist/PasskeyController.d.cts +168 -0
  7. package/dist/PasskeyController.d.cts.map +1 -0
  8. package/dist/PasskeyController.d.mts +168 -0
  9. package/dist/PasskeyController.d.mts.map +1 -0
  10. package/dist/PasskeyController.mjs +443 -0
  11. package/dist/PasskeyController.mjs.map +1 -0
  12. package/dist/ceremony-manager.cjs +134 -0
  13. package/dist/ceremony-manager.cjs.map +1 -0
  14. package/dist/ceremony-manager.d.cts +71 -0
  15. package/dist/ceremony-manager.d.cts.map +1 -0
  16. package/dist/ceremony-manager.d.mts +71 -0
  17. package/dist/ceremony-manager.d.mts.map +1 -0
  18. package/dist/ceremony-manager.mjs +130 -0
  19. package/dist/ceremony-manager.mjs.map +1 -0
  20. package/dist/constants.cjs +33 -0
  21. package/dist/constants.cjs.map +1 -0
  22. package/dist/constants.d.cts +30 -0
  23. package/dist/constants.d.cts.map +1 -0
  24. package/dist/constants.d.mts +30 -0
  25. package/dist/constants.d.mts.map +1 -0
  26. package/dist/constants.mjs +30 -0
  27. package/dist/constants.mjs.map +1 -0
  28. package/dist/errors.cjs +57 -0
  29. package/dist/errors.cjs.map +1 -0
  30. package/dist/errors.d.cts +34 -0
  31. package/dist/errors.d.cts.map +1 -0
  32. package/dist/errors.d.mts +34 -0
  33. package/dist/errors.d.mts.map +1 -0
  34. package/dist/errors.mjs +53 -0
  35. package/dist/errors.mjs.map +1 -0
  36. package/dist/index.cjs +19 -0
  37. package/dist/index.cjs.map +1 -0
  38. package/dist/index.d.cts +9 -0
  39. package/dist/index.d.cts.map +1 -0
  40. package/dist/index.d.mts +9 -0
  41. package/dist/index.d.mts.map +1 -0
  42. package/dist/index.mjs +5 -0
  43. package/dist/index.mjs.map +1 -0
  44. package/dist/key-derivation.cjs +76 -0
  45. package/dist/key-derivation.cjs.map +1 -0
  46. package/dist/key-derivation.d.cts +43 -0
  47. package/dist/key-derivation.d.cts.map +1 -0
  48. package/dist/key-derivation.d.mts +43 -0
  49. package/dist/key-derivation.d.mts.map +1 -0
  50. package/dist/key-derivation.mjs +71 -0
  51. package/dist/key-derivation.mjs.map +1 -0
  52. package/dist/logger.cjs +9 -0
  53. package/dist/logger.cjs.map +1 -0
  54. package/dist/logger.d.cts +5 -0
  55. package/dist/logger.d.cts.map +1 -0
  56. package/dist/logger.d.mts +5 -0
  57. package/dist/logger.d.mts.map +1 -0
  58. package/dist/logger.mjs +6 -0
  59. package/dist/logger.mjs.map +1 -0
  60. package/dist/types.cjs +3 -0
  61. package/dist/types.cjs.map +1 -0
  62. package/dist/types.d.cts +92 -0
  63. package/dist/types.d.cts.map +1 -0
  64. package/dist/types.d.mts +92 -0
  65. package/dist/types.d.mts.map +1 -0
  66. package/dist/types.mjs +2 -0
  67. package/dist/types.mjs.map +1 -0
  68. package/dist/utils/crypto.cjs +55 -0
  69. package/dist/utils/crypto.cjs.map +1 -0
  70. package/dist/utils/crypto.d.cts +30 -0
  71. package/dist/utils/crypto.d.cts.map +1 -0
  72. package/dist/utils/crypto.d.mts +30 -0
  73. package/dist/utils/crypto.d.mts.map +1 -0
  74. package/dist/utils/crypto.mjs +49 -0
  75. package/dist/utils/crypto.mjs.map +1 -0
  76. package/dist/utils/encoding.cjs +42 -0
  77. package/dist/utils/encoding.cjs.map +1 -0
  78. package/dist/utils/encoding.d.cts +22 -0
  79. package/dist/utils/encoding.d.cts.map +1 -0
  80. package/dist/utils/encoding.d.mts +22 -0
  81. package/dist/utils/encoding.d.mts.map +1 -0
  82. package/dist/utils/encoding.mjs +36 -0
  83. package/dist/utils/encoding.mjs.map +1 -0
  84. package/dist/webauthn/constants.cjs +74 -0
  85. package/dist/webauthn/constants.cjs.map +1 -0
  86. package/dist/webauthn/constants.d.cts +68 -0
  87. package/dist/webauthn/constants.d.cts.map +1 -0
  88. package/dist/webauthn/constants.d.mts +68 -0
  89. package/dist/webauthn/constants.d.mts.map +1 -0
  90. package/dist/webauthn/constants.mjs +71 -0
  91. package/dist/webauthn/constants.mjs.map +1 -0
  92. package/dist/webauthn/decode-attestation-object.cjs +18 -0
  93. package/dist/webauthn/decode-attestation-object.cjs.map +1 -0
  94. package/dist/webauthn/decode-attestation-object.d.cts +10 -0
  95. package/dist/webauthn/decode-attestation-object.d.cts.map +1 -0
  96. package/dist/webauthn/decode-attestation-object.d.mts +10 -0
  97. package/dist/webauthn/decode-attestation-object.d.mts.map +1 -0
  98. package/dist/webauthn/decode-attestation-object.mjs +14 -0
  99. package/dist/webauthn/decode-attestation-object.mjs.map +1 -0
  100. package/dist/webauthn/decode-client-data-json.cjs +17 -0
  101. package/dist/webauthn/decode-client-data-json.cjs.map +1 -0
  102. package/dist/webauthn/decode-client-data-json.d.cts +9 -0
  103. package/dist/webauthn/decode-client-data-json.d.cts.map +1 -0
  104. package/dist/webauthn/decode-client-data-json.d.mts +9 -0
  105. package/dist/webauthn/decode-client-data-json.d.mts.map +1 -0
  106. package/dist/webauthn/decode-client-data-json.mjs +13 -0
  107. package/dist/webauthn/decode-client-data-json.mjs.map +1 -0
  108. package/dist/webauthn/match-expected-rp-id.cjs +43 -0
  109. package/dist/webauthn/match-expected-rp-id.cjs.map +1 -0
  110. package/dist/webauthn/match-expected-rp-id.d.cts +11 -0
  111. package/dist/webauthn/match-expected-rp-id.d.cts.map +1 -0
  112. package/dist/webauthn/match-expected-rp-id.d.mts +11 -0
  113. package/dist/webauthn/match-expected-rp-id.d.mts.map +1 -0
  114. package/dist/webauthn/match-expected-rp-id.mjs +39 -0
  115. package/dist/webauthn/match-expected-rp-id.mjs.map +1 -0
  116. package/dist/webauthn/parse-authenticator-data.cjs +69 -0
  117. package/dist/webauthn/parse-authenticator-data.cjs.map +1 -0
  118. package/dist/webauthn/parse-authenticator-data.d.cts +10 -0
  119. package/dist/webauthn/parse-authenticator-data.d.cts.map +1 -0
  120. package/dist/webauthn/parse-authenticator-data.d.mts +10 -0
  121. package/dist/webauthn/parse-authenticator-data.d.mts.map +1 -0
  122. package/dist/webauthn/parse-authenticator-data.mjs +65 -0
  123. package/dist/webauthn/parse-authenticator-data.mjs.map +1 -0
  124. package/dist/webauthn/types.cjs +3 -0
  125. package/dist/webauthn/types.cjs.map +1 -0
  126. package/dist/webauthn/types.d.cts +113 -0
  127. package/dist/webauthn/types.d.cts.map +1 -0
  128. package/dist/webauthn/types.d.mts +113 -0
  129. package/dist/webauthn/types.d.mts.map +1 -0
  130. package/dist/webauthn/types.mjs +2 -0
  131. package/dist/webauthn/types.mjs.map +1 -0
  132. package/dist/webauthn/verify-authentication-response.cjs +134 -0
  133. package/dist/webauthn/verify-authentication-response.cjs.map +1 -0
  134. package/dist/webauthn/verify-authentication-response.d.cts +63 -0
  135. package/dist/webauthn/verify-authentication-response.d.cts.map +1 -0
  136. package/dist/webauthn/verify-authentication-response.d.mts +63 -0
  137. package/dist/webauthn/verify-authentication-response.d.mts.map +1 -0
  138. package/dist/webauthn/verify-authentication-response.mjs +130 -0
  139. package/dist/webauthn/verify-authentication-response.mjs.map +1 -0
  140. package/dist/webauthn/verify-registration-response.cjs +205 -0
  141. package/dist/webauthn/verify-registration-response.cjs.map +1 -0
  142. package/dist/webauthn/verify-registration-response.d.cts +60 -0
  143. package/dist/webauthn/verify-registration-response.d.cts.map +1 -0
  144. package/dist/webauthn/verify-registration-response.d.mts +60 -0
  145. package/dist/webauthn/verify-registration-response.d.mts.map +1 -0
  146. package/dist/webauthn/verify-registration-response.mjs +201 -0
  147. package/dist/webauthn/verify-registration-response.mjs.map +1 -0
  148. package/dist/webauthn/verify-signature.cjs +176 -0
  149. package/dist/webauthn/verify-signature.cjs.map +1 -0
  150. package/dist/webauthn/verify-signature.d.cts +21 -0
  151. package/dist/webauthn/verify-signature.d.cts.map +1 -0
  152. package/dist/webauthn/verify-signature.d.mts +21 -0
  153. package/dist/webauthn/verify-signature.d.mts.map +1 -0
  154. package/dist/webauthn/verify-signature.mjs +172 -0
  155. package/dist/webauthn/verify-signature.mjs.map +1 -0
  156. package/package.json +78 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PasskeyController.cjs","sourceRoot":"","sources":["../src/PasskeyController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangedEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { Messenger } from '@metamask/messenger';\nimport { randomBytes } from '@noble/ciphers/webcrypto';\n\nimport { WEBAUTHN_TIMEOUT_MS, CeremonyManager } from './ceremony-manager';\nimport {\n controllerName,\n PasskeyControllerErrorCode,\n PasskeyControllerErrorMessage,\n} from './constants';\nimport { PasskeyControllerError } from './errors';\nimport {\n deriveKeyFromAuthenticationResponse,\n deriveKeyFromRegistrationResponse,\n} from './key-derivation';\nimport { createModuleLogger, projectLogger } from './logger';\nimport type { PasskeyRecord } from './types';\nimport { decryptWithKey, encryptWithKey } from './utils/crypto';\nimport { base64URLToBytes, bytesToBase64URL } from './utils/encoding';\nimport { COSEALG } from './webauthn/constants';\nimport { decodeClientDataJSON } from './webauthn/decode-client-data-json';\nimport type {\n PasskeyAuthenticationOptions,\n PasskeyAuthenticationResponse,\n PasskeyRegistrationOptions,\n PasskeyRegistrationResponse,\n} from './webauthn/types';\nimport { verifyAuthenticationResponse } from './webauthn/verify-authentication-response';\nimport { verifyRegistrationResponse } from './webauthn/verify-registration-response';\n\nexport type PasskeyControllerState = {\n passkeyRecord: PasskeyRecord | null;\n};\n\nexport type PasskeyControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n PasskeyControllerState\n>;\n\n/**\n * Actions exposed by {@link PasskeyController} on its messenger.\n *\n * Only `:getState` is exposed. Derived enrollment status is available via\n * {@link passkeyControllerSelectors.selectIsPasskeyEnrolled}, and lifecycle\n * methods ({@link PasskeyController.generateRegistrationOptions},\n * {@link PasskeyController.protectVaultKeyWithPasskey}, etc.) accept or\n * return non-`Json` runtime values (WebAuthn `PublicKeyCredential` objects\n * and the vault key string), so they require a direct controller reference.\n */\nexport type PasskeyControllerActions = PasskeyControllerGetStateAction;\n\nexport type PasskeyControllerStateChangedEvent = ControllerStateChangedEvent<\n typeof controllerName,\n PasskeyControllerState\n>;\n\nexport type PasskeyControllerEvents = PasskeyControllerStateChangedEvent;\n\nexport type PasskeyControllerMessenger = Messenger<\n typeof controllerName,\n PasskeyControllerActions,\n PasskeyControllerEvents\n>;\n\n/**\n * Returns the default (empty) state for {@link PasskeyController}.\n *\n * @returns A fresh state object with no enrolled passkey.\n */\nexport function getDefaultPasskeyControllerState(): PasskeyControllerState {\n return { passkeyRecord: null };\n}\n\nconst passkeyControllerMetadata = {\n passkeyRecord: {\n persist: true,\n includeInDebugSnapshot: false,\n includeInStateLogs: false,\n usedInUi: true,\n },\n} satisfies StateMetadata<PasskeyControllerState>;\n\nconst log = createModuleLogger(projectLogger, controllerName);\n\n/**\n * Selectors for {@link PasskeyControllerState}.\n *\n * Use these instead of dedicated getter methods on the controller, so that\n * derived values can be consumed from Redux selectors and other places that\n * only have access to a state object.\n */\nexport const passkeyControllerSelectors = {\n selectIsPasskeyEnrolled: (state: PasskeyControllerState): boolean =>\n state.passkeyRecord !== null,\n};\n\n/**\n * Passkey-based protection for the vault encryption key (WebAuthn).\n *\n * Uses PRF-backed derivation when available; otherwise uses the credential\n * `userHandle`.\n */\nexport class PasskeyController extends BaseController<\n typeof controllerName,\n PasskeyControllerState,\n PasskeyControllerMessenger\n> {\n readonly #ceremonyManager = new CeremonyManager();\n\n readonly #rpID: string;\n\n readonly #rpName: string;\n\n readonly #expectedOrigin: string | string[];\n\n readonly #userName: string;\n\n readonly #userDisplayName: string;\n\n /**\n * Constructs a new {@link PasskeyController}.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this controller.\n * @param args.state - Initial state. Missing properties are filled in with\n * defaults from {@link getDefaultPasskeyControllerState}.\n * @param args.rpID - WebAuthn Relying Party ID (typically the eTLD+1 of the\n * client origin, or `localhost` in dev).\n * @param args.rpName - Human-readable Relying Party name shown by the OS\n * passkey UI.\n * @param args.expectedOrigin - One or more acceptable origins for the\n * `clientDataJSON.origin` check (e.g. `chrome-extension://...`).\n * @param args.userName - Optional `user.name` shown by the OS passkey UI.\n * Defaults to `rpName` so client builds (Stable, Flask, etc.) can\n * differentiate without changes here.\n * @param args.userDisplayName - Optional `user.displayName` shown by the OS\n * passkey UI. Defaults to `rpName`.\n */\n constructor({\n messenger,\n state = {},\n rpID,\n rpName,\n expectedOrigin,\n userName,\n userDisplayName,\n }: {\n messenger: PasskeyControllerMessenger;\n state?: Partial<PasskeyControllerState>;\n rpID: string;\n rpName: string;\n expectedOrigin: string | string[];\n userName?: string;\n userDisplayName?: string;\n }) {\n super({\n messenger,\n metadata: passkeyControllerMetadata,\n name: controllerName,\n state: { ...getDefaultPasskeyControllerState(), ...state },\n });\n\n this.#rpID = rpID;\n this.#rpName = rpName;\n this.#expectedOrigin = expectedOrigin;\n this.#userName = userName ?? rpName;\n this.#userDisplayName = userDisplayName ?? rpName;\n }\n\n #requireEnrolled(): PasskeyRecord {\n const record = this.state.passkeyRecord;\n if (!record) {\n throw new PasskeyControllerError(\n PasskeyControllerErrorMessage.NotEnrolled,\n {\n code: PasskeyControllerErrorCode.NotEnrolled,\n },\n );\n }\n return record;\n }\n\n #getChallengeFromClientData(clientDataJSON: string): string {\n return decodeClientDataJSON(clientDataJSON).challenge;\n }\n\n /**\n * Checks if the passkey is enrolled.\n *\n * @returns Whether the passkey is enrolled.\n */\n isPasskeyEnrolled(): boolean {\n return passkeyControllerSelectors.selectIsPasskeyEnrolled(this.state);\n }\n\n /**\n * Registration options for enrolling a passkey.\n *\n * Call before {@link protectVaultKeyWithPasskey}.\n *\n * @param creationOptionsConfig - Optional configuration.\n * @param creationOptionsConfig.prfAvailable - Omit PRF when `false`. Default `true`.\n * @returns Options for `navigator.credentials.create()`.\n */\n generateRegistrationOptions(creationOptionsConfig?: {\n prfAvailable?: boolean;\n }): PasskeyRegistrationOptions {\n const includePrf = creationOptionsConfig?.prfAvailable !== false;\n const prfSalt = includePrf\n ? bytesToBase64URL(randomBytes(32).slice())\n : undefined;\n const userHandle = bytesToBase64URL(randomBytes(64).slice());\n const challenge = bytesToBase64URL(randomBytes(32).slice());\n\n const extensions: Record<string, unknown> = {};\n if (prfSalt) {\n extensions.prf = { eval: { first: prfSalt } };\n }\n\n const options: PasskeyRegistrationOptions = {\n rp: { name: this.#rpName, id: this.#rpID },\n user: {\n id: userHandle,\n name: this.#userName,\n displayName: this.#userDisplayName,\n },\n challenge,\n pubKeyCredParams: [\n { alg: COSEALG.EdDSA, type: 'public-key' },\n { alg: COSEALG.ES256, type: 'public-key' },\n { alg: COSEALG.RS256, type: 'public-key' },\n ],\n timeout: WEBAUTHN_TIMEOUT_MS,\n authenticatorSelection: {\n userVerification: 'preferred',\n authenticatorAttachment: 'platform',\n residentKey: 'preferred',\n },\n hints: ['client-device', 'hybrid'],\n attestation: 'none',\n ...(Object.keys(extensions).length > 0 ? { extensions } : {}),\n };\n\n this.#ceremonyManager.saveRegistrationCeremony(challenge, {\n userHandle,\n prfSalt: prfSalt ?? '',\n challenge,\n createdAt: Date.now(),\n });\n\n return options;\n }\n\n /**\n * WebAuthn request options for authenticating with the enrolled passkey.\n *\n * Call before {@link retrieveVaultKeyWithPasskey},\n * {@link verifyPasskeyAuthentication}, or {@link renewVaultKeyProtection}.\n *\n * @returns Options for `navigator.credentials.get()`.\n */\n generateAuthenticationOptions(): PasskeyAuthenticationOptions {\n const record = this.#requireEnrolled();\n\n const challenge = bytesToBase64URL(randomBytes(32).slice());\n\n const extensions: Record<string, unknown> = {};\n if (record.keyDerivation.method === 'prf') {\n extensions.prf = { eval: { first: record.keyDerivation.prfSalt } };\n }\n\n const options: PasskeyAuthenticationOptions = {\n challenge,\n rpId: this.#rpID,\n allowCredentials: [\n {\n id: record.credential.id,\n type: 'public-key',\n transports: record.credential.transports,\n },\n ],\n userVerification: 'preferred',\n hints: ['client-device', 'hybrid'],\n timeout: WEBAUTHN_TIMEOUT_MS,\n extensions,\n };\n\n this.#ceremonyManager.saveAuthenticationCeremony(challenge, {\n challenge,\n createdAt: Date.now(),\n });\n\n return options;\n }\n\n /**\n * Completes enrollment and binds the vault key to the new passkey.\n *\n * @param params - Protection parameters.\n * @param params.registrationResponse - Credential from `navigator.credentials.create()`.\n * @param params.vaultKey - Vault encryption key to protect.\n */\n async protectVaultKeyWithPasskey(params: {\n registrationResponse: PasskeyRegistrationResponse;\n vaultKey: string;\n }): Promise<void> {\n const { registrationResponse, vaultKey } = params;\n\n // get challenge\n const challenge = this.#getChallengeFromClientData(\n registrationResponse.response.clientDataJSON,\n );\n const registrationCeremony =\n this.#ceremonyManager.getRegistrationCeremony(challenge);\n if (!registrationCeremony) {\n log('No active passkey registration ceremony for challenge');\n throw new PasskeyControllerError(\n PasskeyControllerErrorMessage.NoRegistrationCeremony,\n { code: PasskeyControllerErrorCode.NoRegistrationCeremony },\n );\n }\n\n try {\n // verify registration response\n const { verified, registrationInfo } = await verifyRegistrationResponse({\n response: registrationResponse,\n expectedChallenge: registrationCeremony.challenge,\n expectedOrigin: this.#expectedOrigin,\n expectedRPID: this.#rpID,\n requireUserVerification: false,\n }).catch((error) => {\n log('Error verifying passkey registration response', error);\n throw new PasskeyControllerError(\n PasskeyControllerErrorMessage.RegistrationVerificationFailed,\n {\n code: PasskeyControllerErrorCode.RegistrationVerificationFailed,\n cause: error instanceof Error ? error : new Error(String(error)),\n },\n );\n });\n if (!verified || !registrationInfo) {\n log(\n 'Passkey registration verification returned unverified or missing registration info',\n );\n throw new PasskeyControllerError(\n PasskeyControllerErrorMessage.RegistrationVerificationFailed,\n { code: PasskeyControllerErrorCode.RegistrationVerificationFailed },\n );\n }\n\n // derive key\n const { encKey, keyDerivation } = deriveKeyFromRegistrationResponse(\n registrationResponse,\n registrationCeremony,\n registrationInfo.credentialId,\n );\n\n // encrypt vault key\n const { ciphertext, iv } = encryptWithKey(vaultKey, encKey);\n\n // persist passkey record\n this.update((state) => {\n state.passkeyRecord = {\n credential: {\n id: registrationInfo.credentialId,\n publicKey: bytesToBase64URL(registrationInfo.publicKey),\n counter: registrationInfo.counter,\n transports: registrationInfo.transports,\n },\n encryptedVaultKey: { ciphertext, iv },\n keyDerivation,\n };\n });\n } finally {\n this.#ceremonyManager.deleteRegistrationCeremony(challenge);\n }\n }\n\n /**\n * Returns the decrypted vault encryption key from the passkey authentication\n * response.\n *\n * @param authenticationResponse - Credential from `navigator.credentials.get()`.\n * @returns The vault encryption key.\n */\n async retrieveVaultKeyWithPasskey(\n authenticationResponse: PasskeyAuthenticationResponse,\n ): Promise<string> {\n // verify authentication response\n await this.#verifyAuthenticationResponse(authenticationResponse);\n\n // derive key (#verifyAuthenticationResponse guarantees enrolled)\n const passkeyRecord = this.#requireEnrolled();\n const encKey = deriveKeyFromAuthenticationResponse(\n authenticationResponse,\n passkeyRecord,\n );\n\n // decrypt vault key\n let vaultKey: string;\n try {\n vaultKey = decryptWithKey(\n passkeyRecord.encryptedVaultKey.ciphertext,\n passkeyRecord.encryptedVaultKey.iv,\n encKey,\n );\n } catch (cause) {\n log(\n 'Error decrypting vault key with passkey',\n cause instanceof Error ? cause : new Error(String(cause)),\n );\n throw new PasskeyControllerError(\n PasskeyControllerErrorMessage.VaultKeyDecryptionFailed,\n {\n code: PasskeyControllerErrorCode.VaultKeyDecryptionFailed,\n cause: cause instanceof Error ? cause : new Error(String(cause)),\n },\n );\n }\n\n return vaultKey;\n }\n\n /**\n * Returns whether passkey authentication succeeds for this credential (same\n * work as {@link retrieveVaultKeyWithPasskey} without exposing the vault key).\n *\n * Returns `false` only when the failure is a {@link PasskeyControllerError}\n * with a defined `code`. Unexpected errors (e.g. malformed `clientDataJSON`,\n * internal bugs) are rethrown.\n *\n * @param authenticationResponse - Credential from `navigator.credentials.get()`.\n * @returns `true` if authentication succeeds, otherwise `false`.\n */\n async verifyPasskeyAuthentication(\n authenticationResponse: PasskeyAuthenticationResponse,\n ): Promise<boolean> {\n try {\n await this.retrieveVaultKeyWithPasskey(authenticationResponse);\n return true;\n } catch (error: unknown) {\n if (error instanceof PasskeyControllerError && error.code !== undefined) {\n return false;\n }\n throw error;\n }\n }\n\n /**\n * Updates the vault encryption key for the same passkey (e.g. after a password change).\n *\n * Caller MUST first verify the assertion via {@link verifyPasskeyAuthentication}\n * or {@link retrieveVaultKeyWithPasskey}. This method does not re-verify\n * because the ceremony is single-use (deleted on verify) and the signature\n * counter is advanced (replay would be rejected). Authentication here is\n * enforced by the prior verification plus the `oldVaultKey` match below.\n *\n * @param params - Renewal parameters.\n * @param params.authenticationResponse - Credential from `navigator.credentials.get()`,\n * already verified by the caller.\n * @param params.oldVaultKey - Expected current vault key.\n * @param params.newVaultKey - New vault key to protect.\n */\n async renewVaultKeyProtection(params: {\n authenticationResponse: PasskeyAuthenticationResponse;\n oldVaultKey: string;\n newVaultKey: string;\n }): Promise<void> {\n const { authenticationResponse } = params;\n const passkeyRecord = this.#requireEnrolled();\n\n // derive key\n const encKey = deriveKeyFromAuthenticationResponse(\n authenticationResponse,\n passkeyRecord,\n );\n\n // decrypt vault key\n let decryptedVaultKey: string;\n try {\n decryptedVaultKey = decryptWithKey(\n passkeyRecord.encryptedVaultKey.ciphertext,\n passkeyRecord.encryptedVaultKey.iv,\n encKey,\n );\n } catch (error) {\n log(\n 'Error decrypting vault key during passkey vault key renewal',\n error instanceof Error ? error : new Error(String(error)),\n );\n throw new PasskeyControllerError(\n PasskeyControllerErrorMessage.VaultKeyDecryptionFailed,\n {\n code: PasskeyControllerErrorCode.VaultKeyDecryptionFailed,\n cause: error instanceof Error ? error : new Error(String(error)),\n },\n );\n }\n\n // check if vault key matches\n const { oldVaultKey, newVaultKey } = params;\n if (decryptedVaultKey !== oldVaultKey) {\n log(\n 'Passkey renewal rejected: decrypted vault key does not match oldVaultKey',\n );\n throw new PasskeyControllerError(\n PasskeyControllerErrorMessage.VaultKeyMismatch,\n { code: PasskeyControllerErrorCode.VaultKeyMismatch },\n );\n }\n\n // encrypt new vault key\n const { ciphertext, iv } = encryptWithKey(newVaultKey, encKey);\n\n // persist passkey record (mutate current state only for vault key material)\n this.update((state) => {\n if (!state.passkeyRecord) {\n throw new PasskeyControllerError(\n PasskeyControllerErrorMessage.NotEnrolled,\n {\n code: PasskeyControllerErrorCode.NotEnrolled,\n },\n );\n }\n state.passkeyRecord.encryptedVaultKey = { ciphertext, iv };\n });\n }\n\n /**\n * Unenrolls the passkey, removing the protected vault key material.\n */\n removePasskey(): void {\n this.update(() => getDefaultPasskeyControllerState());\n this.#ceremonyManager.clear();\n }\n\n /**\n * Resets state and clears in-flight registration/authentication ceremonies.\n */\n clearState(): void {\n this.removePasskey();\n }\n\n /**\n * Releases all in-flight ceremony state and tears down the messenger.\n */\n destroy(): void {\n this.#ceremonyManager.clear();\n super.destroy();\n }\n\n /**\n * Verifies an authentication response for the enrolled passkey.\n *\n * @param authenticationResponse - Authentication result JSON.\n */\n async #verifyAuthenticationResponse(\n authenticationResponse: PasskeyAuthenticationResponse,\n ): Promise<void> {\n let challenge: string | undefined;\n try {\n // get challenge\n challenge = this.#getChallengeFromClientData(\n authenticationResponse.response.clientDataJSON,\n );\n\n // get passkey record\n const record = this.#requireEnrolled();\n\n // get authentication ceremony\n const authenticationCeremony =\n this.#ceremonyManager.getAuthenticationCeremony(challenge);\n if (!authenticationCeremony) {\n log('No active passkey authentication ceremony for challenge');\n throw new PasskeyControllerError(\n PasskeyControllerErrorMessage.NoAuthenticationCeremony,\n { code: PasskeyControllerErrorCode.NoAuthenticationCeremony },\n );\n }\n\n // verify authentication response\n const result = await verifyAuthenticationResponse({\n response: authenticationResponse,\n expectedChallenge: authenticationCeremony.challenge,\n expectedOrigin: this.#expectedOrigin,\n expectedRPID: this.#rpID,\n credential: {\n id: record.credential.id,\n publicKey: base64URLToBytes(record.credential.publicKey),\n counter: record.credential.counter,\n transports: record.credential.transports,\n },\n // UV optional for device compatibility; vault key remains password-gated.\n requireUserVerification: false,\n }).catch((error) => {\n log(\n 'Error verifying passkey authentication response',\n error instanceof Error ? error : new Error(String(error)),\n );\n throw new PasskeyControllerError(\n PasskeyControllerErrorMessage.AuthenticationVerificationFailed,\n {\n code: PasskeyControllerErrorCode.AuthenticationVerificationFailed,\n cause: error instanceof Error ? error : new Error(String(error)),\n },\n );\n });\n if (!result.verified) {\n log('Passkey authentication verification returned unverified');\n throw new PasskeyControllerError(\n PasskeyControllerErrorMessage.AuthenticationVerificationFailed,\n {\n code: PasskeyControllerErrorCode.AuthenticationVerificationFailed,\n },\n );\n }\n\n // persist passkey record with updated counter without clobbering concurrent updates\n this.update((state) => {\n if (!state.passkeyRecord) {\n throw new PasskeyControllerError(\n PasskeyControllerErrorMessage.NotEnrolled,\n { code: PasskeyControllerErrorCode.NotEnrolled },\n );\n }\n const latest = state.passkeyRecord;\n latest.credential.counter = Math.max(\n result.authenticationInfo.newCounter,\n latest.credential.counter,\n );\n });\n } finally {\n if (challenge) {\n this.#ceremonyManager.deleteAuthenticationCeremony(challenge);\n }\n }\n }\n}\n"]}
@@ -0,0 +1,168 @@
1
+ import type { ControllerGetStateAction, ControllerStateChangedEvent } from "@metamask/base-controller";
2
+ import { BaseController } from "@metamask/base-controller";
3
+ import type { Messenger } from "@metamask/messenger";
4
+ import { controllerName } from "./constants.cjs";
5
+ import type { PasskeyRecord } from "./types.cjs";
6
+ import type { PasskeyAuthenticationOptions, PasskeyAuthenticationResponse, PasskeyRegistrationOptions, PasskeyRegistrationResponse } from "./webauthn/types.cjs";
7
+ export type PasskeyControllerState = {
8
+ passkeyRecord: PasskeyRecord | null;
9
+ };
10
+ export type PasskeyControllerGetStateAction = ControllerGetStateAction<typeof controllerName, PasskeyControllerState>;
11
+ /**
12
+ * Actions exposed by {@link PasskeyController} on its messenger.
13
+ *
14
+ * Only `:getState` is exposed. Derived enrollment status is available via
15
+ * {@link passkeyControllerSelectors.selectIsPasskeyEnrolled}, and lifecycle
16
+ * methods ({@link PasskeyController.generateRegistrationOptions},
17
+ * {@link PasskeyController.protectVaultKeyWithPasskey}, etc.) accept or
18
+ * return non-`Json` runtime values (WebAuthn `PublicKeyCredential` objects
19
+ * and the vault key string), so they require a direct controller reference.
20
+ */
21
+ export type PasskeyControllerActions = PasskeyControllerGetStateAction;
22
+ export type PasskeyControllerStateChangedEvent = ControllerStateChangedEvent<typeof controllerName, PasskeyControllerState>;
23
+ export type PasskeyControllerEvents = PasskeyControllerStateChangedEvent;
24
+ export type PasskeyControllerMessenger = Messenger<typeof controllerName, PasskeyControllerActions, PasskeyControllerEvents>;
25
+ /**
26
+ * Returns the default (empty) state for {@link PasskeyController}.
27
+ *
28
+ * @returns A fresh state object with no enrolled passkey.
29
+ */
30
+ export declare function getDefaultPasskeyControllerState(): PasskeyControllerState;
31
+ /**
32
+ * Selectors for {@link PasskeyControllerState}.
33
+ *
34
+ * Use these instead of dedicated getter methods on the controller, so that
35
+ * derived values can be consumed from Redux selectors and other places that
36
+ * only have access to a state object.
37
+ */
38
+ export declare const passkeyControllerSelectors: {
39
+ selectIsPasskeyEnrolled: (state: PasskeyControllerState) => boolean;
40
+ };
41
+ /**
42
+ * Passkey-based protection for the vault encryption key (WebAuthn).
43
+ *
44
+ * Uses PRF-backed derivation when available; otherwise uses the credential
45
+ * `userHandle`.
46
+ */
47
+ export declare class PasskeyController extends BaseController<typeof controllerName, PasskeyControllerState, PasskeyControllerMessenger> {
48
+ #private;
49
+ /**
50
+ * Constructs a new {@link PasskeyController}.
51
+ *
52
+ * @param args - The constructor arguments.
53
+ * @param args.messenger - The messenger suited for this controller.
54
+ * @param args.state - Initial state. Missing properties are filled in with
55
+ * defaults from {@link getDefaultPasskeyControllerState}.
56
+ * @param args.rpID - WebAuthn Relying Party ID (typically the eTLD+1 of the
57
+ * client origin, or `localhost` in dev).
58
+ * @param args.rpName - Human-readable Relying Party name shown by the OS
59
+ * passkey UI.
60
+ * @param args.expectedOrigin - One or more acceptable origins for the
61
+ * `clientDataJSON.origin` check (e.g. `chrome-extension://...`).
62
+ * @param args.userName - Optional `user.name` shown by the OS passkey UI.
63
+ * Defaults to `rpName` so client builds (Stable, Flask, etc.) can
64
+ * differentiate without changes here.
65
+ * @param args.userDisplayName - Optional `user.displayName` shown by the OS
66
+ * passkey UI. Defaults to `rpName`.
67
+ */
68
+ constructor({ messenger, state, rpID, rpName, expectedOrigin, userName, userDisplayName, }: {
69
+ messenger: PasskeyControllerMessenger;
70
+ state?: Partial<PasskeyControllerState>;
71
+ rpID: string;
72
+ rpName: string;
73
+ expectedOrigin: string | string[];
74
+ userName?: string;
75
+ userDisplayName?: string;
76
+ });
77
+ /**
78
+ * Checks if the passkey is enrolled.
79
+ *
80
+ * @returns Whether the passkey is enrolled.
81
+ */
82
+ isPasskeyEnrolled(): boolean;
83
+ /**
84
+ * Registration options for enrolling a passkey.
85
+ *
86
+ * Call before {@link protectVaultKeyWithPasskey}.
87
+ *
88
+ * @param creationOptionsConfig - Optional configuration.
89
+ * @param creationOptionsConfig.prfAvailable - Omit PRF when `false`. Default `true`.
90
+ * @returns Options for `navigator.credentials.create()`.
91
+ */
92
+ generateRegistrationOptions(creationOptionsConfig?: {
93
+ prfAvailable?: boolean;
94
+ }): PasskeyRegistrationOptions;
95
+ /**
96
+ * WebAuthn request options for authenticating with the enrolled passkey.
97
+ *
98
+ * Call before {@link retrieveVaultKeyWithPasskey},
99
+ * {@link verifyPasskeyAuthentication}, or {@link renewVaultKeyProtection}.
100
+ *
101
+ * @returns Options for `navigator.credentials.get()`.
102
+ */
103
+ generateAuthenticationOptions(): PasskeyAuthenticationOptions;
104
+ /**
105
+ * Completes enrollment and binds the vault key to the new passkey.
106
+ *
107
+ * @param params - Protection parameters.
108
+ * @param params.registrationResponse - Credential from `navigator.credentials.create()`.
109
+ * @param params.vaultKey - Vault encryption key to protect.
110
+ */
111
+ protectVaultKeyWithPasskey(params: {
112
+ registrationResponse: PasskeyRegistrationResponse;
113
+ vaultKey: string;
114
+ }): Promise<void>;
115
+ /**
116
+ * Returns the decrypted vault encryption key from the passkey authentication
117
+ * response.
118
+ *
119
+ * @param authenticationResponse - Credential from `navigator.credentials.get()`.
120
+ * @returns The vault encryption key.
121
+ */
122
+ retrieveVaultKeyWithPasskey(authenticationResponse: PasskeyAuthenticationResponse): Promise<string>;
123
+ /**
124
+ * Returns whether passkey authentication succeeds for this credential (same
125
+ * work as {@link retrieveVaultKeyWithPasskey} without exposing the vault key).
126
+ *
127
+ * Returns `false` only when the failure is a {@link PasskeyControllerError}
128
+ * with a defined `code`. Unexpected errors (e.g. malformed `clientDataJSON`,
129
+ * internal bugs) are rethrown.
130
+ *
131
+ * @param authenticationResponse - Credential from `navigator.credentials.get()`.
132
+ * @returns `true` if authentication succeeds, otherwise `false`.
133
+ */
134
+ verifyPasskeyAuthentication(authenticationResponse: PasskeyAuthenticationResponse): Promise<boolean>;
135
+ /**
136
+ * Updates the vault encryption key for the same passkey (e.g. after a password change).
137
+ *
138
+ * Caller MUST first verify the assertion via {@link verifyPasskeyAuthentication}
139
+ * or {@link retrieveVaultKeyWithPasskey}. This method does not re-verify
140
+ * because the ceremony is single-use (deleted on verify) and the signature
141
+ * counter is advanced (replay would be rejected). Authentication here is
142
+ * enforced by the prior verification plus the `oldVaultKey` match below.
143
+ *
144
+ * @param params - Renewal parameters.
145
+ * @param params.authenticationResponse - Credential from `navigator.credentials.get()`,
146
+ * already verified by the caller.
147
+ * @param params.oldVaultKey - Expected current vault key.
148
+ * @param params.newVaultKey - New vault key to protect.
149
+ */
150
+ renewVaultKeyProtection(params: {
151
+ authenticationResponse: PasskeyAuthenticationResponse;
152
+ oldVaultKey: string;
153
+ newVaultKey: string;
154
+ }): Promise<void>;
155
+ /**
156
+ * Unenrolls the passkey, removing the protected vault key material.
157
+ */
158
+ removePasskey(): void;
159
+ /**
160
+ * Resets state and clears in-flight registration/authentication ceremonies.
161
+ */
162
+ clearState(): void;
163
+ /**
164
+ * Releases all in-flight ceremony state and tears down the messenger.
165
+ */
166
+ destroy(): void;
167
+ }
168
+ //# sourceMappingURL=PasskeyController.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PasskeyController.d.cts","sourceRoot":"","sources":["../src/PasskeyController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EACxB,2BAA2B,EAE5B,kCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAIrD,OAAO,EACL,cAAc,EAGf,wBAAoB;AAOrB,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAgB;AAK7C,OAAO,KAAK,EACV,4BAA4B,EAC5B,6BAA6B,EAC7B,0BAA0B,EAC1B,2BAA2B,EAC5B,6BAAyB;AAI1B,MAAM,MAAM,sBAAsB,GAAG;IACnC,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG,wBAAwB,CACpE,OAAO,cAAc,EACrB,sBAAsB,CACvB,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,MAAM,wBAAwB,GAAG,+BAA+B,CAAC;AAEvE,MAAM,MAAM,kCAAkC,GAAG,2BAA2B,CAC1E,OAAO,cAAc,EACrB,sBAAsB,CACvB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,kCAAkC,CAAC;AAEzE,MAAM,MAAM,0BAA0B,GAAG,SAAS,CAChD,OAAO,cAAc,EACrB,wBAAwB,EACxB,uBAAuB,CACxB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gCAAgC,IAAI,sBAAsB,CAEzE;AAaD;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B;qCACJ,sBAAsB,KAAG,OAAO;CAElE,CAAC;AAEF;;;;;GAKG;AACH,qBAAa,iBAAkB,SAAQ,cAAc,CACnD,OAAO,cAAc,EACrB,sBAAsB,EACtB,0BAA0B,CAC3B;;IAaC;;;;;;;;;;;;;;;;;;OAkBG;gBACS,EACV,SAAS,EACT,KAAU,EACV,IAAI,EACJ,MAAM,EACN,cAAc,EACd,QAAQ,EACR,eAAe,GAChB,EAAE;QACD,SAAS,EAAE,0BAA0B,CAAC;QACtC,KAAK,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAC;QACxC,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,cAAc,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B;IAgCD;;;;OAIG;IACH,iBAAiB,IAAI,OAAO;IAI5B;;;;;;;;OAQG;IACH,2BAA2B,CAAC,qBAAqB,CAAC,EAAE;QAClD,YAAY,CAAC,EAAE,OAAO,CAAC;KACxB,GAAG,0BAA0B;IA+C9B;;;;;;;OAOG;IACH,6BAA6B,IAAI,4BAA4B;IAkC7D;;;;;;OAMG;IACG,0BAA0B,CAAC,MAAM,EAAE;QACvC,oBAAoB,EAAE,2BAA2B,CAAC;QAClD,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,IAAI,CAAC;IAyEjB;;;;;;OAMG;IACG,2BAA2B,CAC/B,sBAAsB,EAAE,6BAA6B,GACpD,OAAO,CAAC,MAAM,CAAC;IAoClB;;;;;;;;;;OAUG;IACG,2BAA2B,CAC/B,sBAAsB,EAAE,6BAA6B,GACpD,OAAO,CAAC,OAAO,CAAC;IAYnB;;;;;;;;;;;;;;OAcG;IACG,uBAAuB,CAAC,MAAM,EAAE;QACpC,sBAAsB,EAAE,6BAA6B,CAAC;QACtD,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC,IAAI,CAAC;IA6DjB;;OAEG;IACH,aAAa,IAAI,IAAI;IAKrB;;OAEG;IACH,UAAU,IAAI,IAAI;IAIlB;;OAEG;IACH,OAAO,IAAI,IAAI;CA2FhB"}
@@ -0,0 +1,168 @@
1
+ import type { ControllerGetStateAction, ControllerStateChangedEvent } from "@metamask/base-controller";
2
+ import { BaseController } from "@metamask/base-controller";
3
+ import type { Messenger } from "@metamask/messenger";
4
+ import { controllerName } from "./constants.mjs";
5
+ import type { PasskeyRecord } from "./types.mjs";
6
+ import type { PasskeyAuthenticationOptions, PasskeyAuthenticationResponse, PasskeyRegistrationOptions, PasskeyRegistrationResponse } from "./webauthn/types.mjs";
7
+ export type PasskeyControllerState = {
8
+ passkeyRecord: PasskeyRecord | null;
9
+ };
10
+ export type PasskeyControllerGetStateAction = ControllerGetStateAction<typeof controllerName, PasskeyControllerState>;
11
+ /**
12
+ * Actions exposed by {@link PasskeyController} on its messenger.
13
+ *
14
+ * Only `:getState` is exposed. Derived enrollment status is available via
15
+ * {@link passkeyControllerSelectors.selectIsPasskeyEnrolled}, and lifecycle
16
+ * methods ({@link PasskeyController.generateRegistrationOptions},
17
+ * {@link PasskeyController.protectVaultKeyWithPasskey}, etc.) accept or
18
+ * return non-`Json` runtime values (WebAuthn `PublicKeyCredential` objects
19
+ * and the vault key string), so they require a direct controller reference.
20
+ */
21
+ export type PasskeyControllerActions = PasskeyControllerGetStateAction;
22
+ export type PasskeyControllerStateChangedEvent = ControllerStateChangedEvent<typeof controllerName, PasskeyControllerState>;
23
+ export type PasskeyControllerEvents = PasskeyControllerStateChangedEvent;
24
+ export type PasskeyControllerMessenger = Messenger<typeof controllerName, PasskeyControllerActions, PasskeyControllerEvents>;
25
+ /**
26
+ * Returns the default (empty) state for {@link PasskeyController}.
27
+ *
28
+ * @returns A fresh state object with no enrolled passkey.
29
+ */
30
+ export declare function getDefaultPasskeyControllerState(): PasskeyControllerState;
31
+ /**
32
+ * Selectors for {@link PasskeyControllerState}.
33
+ *
34
+ * Use these instead of dedicated getter methods on the controller, so that
35
+ * derived values can be consumed from Redux selectors and other places that
36
+ * only have access to a state object.
37
+ */
38
+ export declare const passkeyControllerSelectors: {
39
+ selectIsPasskeyEnrolled: (state: PasskeyControllerState) => boolean;
40
+ };
41
+ /**
42
+ * Passkey-based protection for the vault encryption key (WebAuthn).
43
+ *
44
+ * Uses PRF-backed derivation when available; otherwise uses the credential
45
+ * `userHandle`.
46
+ */
47
+ export declare class PasskeyController extends BaseController<typeof controllerName, PasskeyControllerState, PasskeyControllerMessenger> {
48
+ #private;
49
+ /**
50
+ * Constructs a new {@link PasskeyController}.
51
+ *
52
+ * @param args - The constructor arguments.
53
+ * @param args.messenger - The messenger suited for this controller.
54
+ * @param args.state - Initial state. Missing properties are filled in with
55
+ * defaults from {@link getDefaultPasskeyControllerState}.
56
+ * @param args.rpID - WebAuthn Relying Party ID (typically the eTLD+1 of the
57
+ * client origin, or `localhost` in dev).
58
+ * @param args.rpName - Human-readable Relying Party name shown by the OS
59
+ * passkey UI.
60
+ * @param args.expectedOrigin - One or more acceptable origins for the
61
+ * `clientDataJSON.origin` check (e.g. `chrome-extension://...`).
62
+ * @param args.userName - Optional `user.name` shown by the OS passkey UI.
63
+ * Defaults to `rpName` so client builds (Stable, Flask, etc.) can
64
+ * differentiate without changes here.
65
+ * @param args.userDisplayName - Optional `user.displayName` shown by the OS
66
+ * passkey UI. Defaults to `rpName`.
67
+ */
68
+ constructor({ messenger, state, rpID, rpName, expectedOrigin, userName, userDisplayName, }: {
69
+ messenger: PasskeyControllerMessenger;
70
+ state?: Partial<PasskeyControllerState>;
71
+ rpID: string;
72
+ rpName: string;
73
+ expectedOrigin: string | string[];
74
+ userName?: string;
75
+ userDisplayName?: string;
76
+ });
77
+ /**
78
+ * Checks if the passkey is enrolled.
79
+ *
80
+ * @returns Whether the passkey is enrolled.
81
+ */
82
+ isPasskeyEnrolled(): boolean;
83
+ /**
84
+ * Registration options for enrolling a passkey.
85
+ *
86
+ * Call before {@link protectVaultKeyWithPasskey}.
87
+ *
88
+ * @param creationOptionsConfig - Optional configuration.
89
+ * @param creationOptionsConfig.prfAvailable - Omit PRF when `false`. Default `true`.
90
+ * @returns Options for `navigator.credentials.create()`.
91
+ */
92
+ generateRegistrationOptions(creationOptionsConfig?: {
93
+ prfAvailable?: boolean;
94
+ }): PasskeyRegistrationOptions;
95
+ /**
96
+ * WebAuthn request options for authenticating with the enrolled passkey.
97
+ *
98
+ * Call before {@link retrieveVaultKeyWithPasskey},
99
+ * {@link verifyPasskeyAuthentication}, or {@link renewVaultKeyProtection}.
100
+ *
101
+ * @returns Options for `navigator.credentials.get()`.
102
+ */
103
+ generateAuthenticationOptions(): PasskeyAuthenticationOptions;
104
+ /**
105
+ * Completes enrollment and binds the vault key to the new passkey.
106
+ *
107
+ * @param params - Protection parameters.
108
+ * @param params.registrationResponse - Credential from `navigator.credentials.create()`.
109
+ * @param params.vaultKey - Vault encryption key to protect.
110
+ */
111
+ protectVaultKeyWithPasskey(params: {
112
+ registrationResponse: PasskeyRegistrationResponse;
113
+ vaultKey: string;
114
+ }): Promise<void>;
115
+ /**
116
+ * Returns the decrypted vault encryption key from the passkey authentication
117
+ * response.
118
+ *
119
+ * @param authenticationResponse - Credential from `navigator.credentials.get()`.
120
+ * @returns The vault encryption key.
121
+ */
122
+ retrieveVaultKeyWithPasskey(authenticationResponse: PasskeyAuthenticationResponse): Promise<string>;
123
+ /**
124
+ * Returns whether passkey authentication succeeds for this credential (same
125
+ * work as {@link retrieveVaultKeyWithPasskey} without exposing the vault key).
126
+ *
127
+ * Returns `false` only when the failure is a {@link PasskeyControllerError}
128
+ * with a defined `code`. Unexpected errors (e.g. malformed `clientDataJSON`,
129
+ * internal bugs) are rethrown.
130
+ *
131
+ * @param authenticationResponse - Credential from `navigator.credentials.get()`.
132
+ * @returns `true` if authentication succeeds, otherwise `false`.
133
+ */
134
+ verifyPasskeyAuthentication(authenticationResponse: PasskeyAuthenticationResponse): Promise<boolean>;
135
+ /**
136
+ * Updates the vault encryption key for the same passkey (e.g. after a password change).
137
+ *
138
+ * Caller MUST first verify the assertion via {@link verifyPasskeyAuthentication}
139
+ * or {@link retrieveVaultKeyWithPasskey}. This method does not re-verify
140
+ * because the ceremony is single-use (deleted on verify) and the signature
141
+ * counter is advanced (replay would be rejected). Authentication here is
142
+ * enforced by the prior verification plus the `oldVaultKey` match below.
143
+ *
144
+ * @param params - Renewal parameters.
145
+ * @param params.authenticationResponse - Credential from `navigator.credentials.get()`,
146
+ * already verified by the caller.
147
+ * @param params.oldVaultKey - Expected current vault key.
148
+ * @param params.newVaultKey - New vault key to protect.
149
+ */
150
+ renewVaultKeyProtection(params: {
151
+ authenticationResponse: PasskeyAuthenticationResponse;
152
+ oldVaultKey: string;
153
+ newVaultKey: string;
154
+ }): Promise<void>;
155
+ /**
156
+ * Unenrolls the passkey, removing the protected vault key material.
157
+ */
158
+ removePasskey(): void;
159
+ /**
160
+ * Resets state and clears in-flight registration/authentication ceremonies.
161
+ */
162
+ clearState(): void;
163
+ /**
164
+ * Releases all in-flight ceremony state and tears down the messenger.
165
+ */
166
+ destroy(): void;
167
+ }
168
+ //# sourceMappingURL=PasskeyController.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PasskeyController.d.mts","sourceRoot":"","sources":["../src/PasskeyController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EACxB,2BAA2B,EAE5B,kCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAIrD,OAAO,EACL,cAAc,EAGf,wBAAoB;AAOrB,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAgB;AAK7C,OAAO,KAAK,EACV,4BAA4B,EAC5B,6BAA6B,EAC7B,0BAA0B,EAC1B,2BAA2B,EAC5B,6BAAyB;AAI1B,MAAM,MAAM,sBAAsB,GAAG;IACnC,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG,wBAAwB,CACpE,OAAO,cAAc,EACrB,sBAAsB,CACvB,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,MAAM,wBAAwB,GAAG,+BAA+B,CAAC;AAEvE,MAAM,MAAM,kCAAkC,GAAG,2BAA2B,CAC1E,OAAO,cAAc,EACrB,sBAAsB,CACvB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,kCAAkC,CAAC;AAEzE,MAAM,MAAM,0BAA0B,GAAG,SAAS,CAChD,OAAO,cAAc,EACrB,wBAAwB,EACxB,uBAAuB,CACxB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gCAAgC,IAAI,sBAAsB,CAEzE;AAaD;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B;qCACJ,sBAAsB,KAAG,OAAO;CAElE,CAAC;AAEF;;;;;GAKG;AACH,qBAAa,iBAAkB,SAAQ,cAAc,CACnD,OAAO,cAAc,EACrB,sBAAsB,EACtB,0BAA0B,CAC3B;;IAaC;;;;;;;;;;;;;;;;;;OAkBG;gBACS,EACV,SAAS,EACT,KAAU,EACV,IAAI,EACJ,MAAM,EACN,cAAc,EACd,QAAQ,EACR,eAAe,GAChB,EAAE;QACD,SAAS,EAAE,0BAA0B,CAAC;QACtC,KAAK,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAC;QACxC,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,cAAc,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B;IAgCD;;;;OAIG;IACH,iBAAiB,IAAI,OAAO;IAI5B;;;;;;;;OAQG;IACH,2BAA2B,CAAC,qBAAqB,CAAC,EAAE;QAClD,YAAY,CAAC,EAAE,OAAO,CAAC;KACxB,GAAG,0BAA0B;IA+C9B;;;;;;;OAOG;IACH,6BAA6B,IAAI,4BAA4B;IAkC7D;;;;;;OAMG;IACG,0BAA0B,CAAC,MAAM,EAAE;QACvC,oBAAoB,EAAE,2BAA2B,CAAC;QAClD,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,IAAI,CAAC;IAyEjB;;;;;;OAMG;IACG,2BAA2B,CAC/B,sBAAsB,EAAE,6BAA6B,GACpD,OAAO,CAAC,MAAM,CAAC;IAoClB;;;;;;;;;;OAUG;IACG,2BAA2B,CAC/B,sBAAsB,EAAE,6BAA6B,GACpD,OAAO,CAAC,OAAO,CAAC;IAYnB;;;;;;;;;;;;;;OAcG;IACG,uBAAuB,CAAC,MAAM,EAAE;QACpC,sBAAsB,EAAE,6BAA6B,CAAC;QACtD,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC,IAAI,CAAC;IA6DjB;;OAEG;IACH,aAAa,IAAI,IAAI;IAKrB;;OAEG;IACH,UAAU,IAAI,IAAI;IAIlB;;OAEG;IACH,OAAO,IAAI,IAAI;CA2FhB"}