From 3170379c67a9cf33374d9f9ab89dafed16ba7edf Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Tue, 27 Dec 2022 19:21:46 -0800 Subject: Update startRegistration to use new values --- .../src/helpers/toAuthenticatorAttachment.ts | 18 ++++++++ packages/browser/src/methods/startRegistration.ts | 53 ++++++++++++---------- 2 files changed, 48 insertions(+), 23 deletions(-) create mode 100644 packages/browser/src/helpers/toAuthenticatorAttachment.ts (limited to 'packages/browser/src') diff --git a/packages/browser/src/helpers/toAuthenticatorAttachment.ts b/packages/browser/src/helpers/toAuthenticatorAttachment.ts new file mode 100644 index 0000000..7a2aca0 --- /dev/null +++ b/packages/browser/src/helpers/toAuthenticatorAttachment.ts @@ -0,0 +1,18 @@ +import { AuthenticatorAttachment } from '@simplewebauthn/typescript-types'; + +const attachments: AuthenticatorAttachment[] = ['cross-platform', 'platform']; + +/** + * If possible coerce a `string` value into a known `AuthenticatorAttachment` + */ +export function toAuthenticatorAttachment(attachment: string | null): AuthenticatorAttachment | undefined { + if (!attachment) { + return; + } + + if (attachments.indexOf(attachment as AuthenticatorAttachment) < 0) { + return; + } + + return attachment as AuthenticatorAttachment; +} diff --git a/packages/browser/src/methods/startRegistration.ts b/packages/browser/src/methods/startRegistration.ts index bc30707..14419ca 100644 --- a/packages/browser/src/methods/startRegistration.ts +++ b/packages/browser/src/methods/startRegistration.ts @@ -1,7 +1,8 @@ import { PublicKeyCredentialCreationOptionsJSON, RegistrationCredential, - RegistrationCredentialJSON, + RegistrationResponseJSON, + PublicKeyCredentialFuture, } from '@simplewebauthn/typescript-types'; import { utf8StringToBuffer } from '../helpers/utf8StringToBuffer'; @@ -11,6 +12,7 @@ import { browserSupportsWebAuthn } from '../helpers/browserSupportsWebAuthn'; import { toPublicKeyCredentialDescriptor } from '../helpers/toPublicKeyCredentialDescriptor'; import { identifyRegistrationError } from '../helpers/identifyRegistrationError'; import { webauthnAbortService } from '../helpers/webAuthnAbortService'; +import { toAuthenticatorAttachment } from '../helpers/toAuthenticatorAttachment'; /** * Begin authenticator "registration" via WebAuthn attestation @@ -19,21 +21,29 @@ import { webauthnAbortService } from '../helpers/webAuthnAbortService'; */ export async function startRegistration( creationOptionsJSON: PublicKeyCredentialCreationOptionsJSON, -): Promise { +): Promise { if (!browserSupportsWebAuthn()) { throw new Error('WebAuthn is not supported in this browser'); } + const globalPublicKeyCredential = + window.PublicKeyCredential as unknown as PublicKeyCredentialFuture; + + let publicKey: PublicKeyCredentialCreationOptions; // We need to convert some values to Uint8Arrays before passing the credentials to the navigator - const publicKey: PublicKeyCredentialCreationOptions = { - ...creationOptionsJSON, - challenge: base64URLStringToBuffer(creationOptionsJSON.challenge), - user: { - ...creationOptionsJSON.user, - id: utf8StringToBuffer(creationOptionsJSON.user.id), - }, - excludeCredentials: creationOptionsJSON.excludeCredentials.map(toPublicKeyCredentialDescriptor), - }; + if (typeof globalPublicKeyCredential.parseCreationOptionsFromJSON === 'function') { + publicKey = globalPublicKeyCredential.parseCreationOptionsFromJSON(creationOptionsJSON); + } else { + publicKey = { + ...creationOptionsJSON, + challenge: base64URLStringToBuffer(creationOptionsJSON.challenge), + user: { + ...creationOptionsJSON.user, + id: utf8StringToBuffer(creationOptionsJSON.user.id), + }, + excludeCredentials: creationOptionsJSON.excludeCredentials?.map(toPublicKeyCredentialDescriptor), + }; + } // Finalize options const options: CredentialCreationOptions = { publicKey }; @@ -52,27 +62,24 @@ export async function startRegistration( throw new Error('Registration was not completed'); } + // Use toJSON() if it's available in the browser + if (typeof credential.toJSON === 'function') { + return credential.toJSON() as RegistrationResponseJSON; + } + + // Manually construct an instance of RegistrationResponseJSON const { id, rawId, response, type } = credential; - // Convert values to base64 to make it easier to send back to the server - const credentialJSON: RegistrationCredentialJSON = { + return { id, rawId: bufferToBase64URLString(rawId), response: { attestationObject: bufferToBase64URLString(response.attestationObject), clientDataJSON: bufferToBase64URLString(response.clientDataJSON), + transports: response.getTransports(), }, type, clientExtensionResults: credential.getClientExtensionResults(), - authenticatorAttachment: credential.authenticatorAttachment, + authenticatorAttachment: toAuthenticatorAttachment(credential.authenticatorAttachment), }; - - /** - * Include the authenticator's transports if the browser supports querying for them - */ - if (typeof response.getTransports === 'function') { - credentialJSON.transports = response.getTransports(); - } - - return credentialJSON; } -- cgit v1.2.3