diff options
author | Matthew Miller <matthew@millerti.me> | 2022-12-27 22:02:11 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-27 22:02:11 -0800 |
commit | 76c7a46b60b1093e9e71f38670175bee45512473 (patch) | |
tree | 686adb3a370e68f76541400740a0b722350d8705 /packages/browser/src | |
parent | 495c0881367ec3017553f74c3c826fb68cfd407f (diff) | |
parent | 08f7f69b221ce33b4bfa6108493fe20d0b7f93b0 (diff) |
Merge pull request #320 from MasterKale/feat/webauthn-L3-json-types
feat/webauthn-L3-json-types
Diffstat (limited to 'packages/browser/src')
5 files changed, 46 insertions, 24 deletions
diff --git a/packages/browser/src/helpers/toAuthenticatorAttachment.ts b/packages/browser/src/helpers/toAuthenticatorAttachment.ts new file mode 100644 index 0000000..366cf8f --- /dev/null +++ b/packages/browser/src/helpers/toAuthenticatorAttachment.ts @@ -0,0 +1,20 @@ +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/startAuthentication.test.ts b/packages/browser/src/methods/startAuthentication.test.ts index 9ebdd77..31dbde3 100644 --- a/packages/browser/src/methods/startAuthentication.test.ts +++ b/packages/browser/src/methods/startAuthentication.test.ts @@ -115,7 +115,7 @@ test('should return base64url-encoded response values', async () => { userHandle: Buffer.from(mockUserHandle, 'ascii'), }, getClientExtensionResults: () => ({}), - type: 'webauthn.get', + type: 'public-key', authenticatorAttachment: '', }); }); diff --git a/packages/browser/src/methods/startAuthentication.ts b/packages/browser/src/methods/startAuthentication.ts index 761a96c..cce28e7 100644 --- a/packages/browser/src/methods/startAuthentication.ts +++ b/packages/browser/src/methods/startAuthentication.ts @@ -1,7 +1,7 @@ import { PublicKeyCredentialRequestOptionsJSON, AuthenticationCredential, - AuthenticationCredentialJSON, + AuthenticationResponseJSON, } from '@simplewebauthn/typescript-types'; import { bufferToBase64URLString } from '../helpers/bufferToBase64URLString'; @@ -12,18 +12,19 @@ import { browserSupportsWebAuthnAutofill } from '../helpers/browserSupportsWebAu import { toPublicKeyCredentialDescriptor } from '../helpers/toPublicKeyCredentialDescriptor'; import { identifyAuthenticationError } from '../helpers/identifyAuthenticationError'; import { webauthnAbortService } from '../helpers/webAuthnAbortService'; +import { toAuthenticatorAttachment } from '../helpers/toAuthenticatorAttachment'; /** * Begin authenticator "login" via WebAuthn assertion * - * @param requestOptionsJSON Output from **@simplewebauthn/server**'s generateAssertionOptions(...) + * @param requestOptionsJSON Output from **@simplewebauthn/server**'s `generateAuthenticationOptions()` * @param useBrowserAutofill Initialize conditional UI to enable logging in via browser * autofill prompts */ export async function startAuthentication( requestOptionsJSON: PublicKeyCredentialRequestOptionsJSON, useBrowserAutofill = false, -): Promise<AuthenticationCredentialJSON> { +): Promise<AuthenticationResponseJSON> { if (!browserSupportsWebAuthn()) { throw new Error('WebAuthn is not supported in this browser'); } @@ -105,6 +106,6 @@ export async function startAuthentication( }, type, clientExtensionResults: credential.getClientExtensionResults(), - authenticatorAttachment: credential.authenticatorAttachment, + authenticatorAttachment: toAuthenticatorAttachment(credential.authenticatorAttachment), }; } diff --git a/packages/browser/src/methods/startRegistration.test.ts b/packages/browser/src/methods/startRegistration.test.ts index 38ea52e..8ba6f5a 100644 --- a/packages/browser/src/methods/startRegistration.test.ts +++ b/packages/browser/src/methods/startRegistration.test.ts @@ -102,7 +102,7 @@ test('should return base64url-encoded response values', async () => { getPublicKeyAlgorithm: () => -999, }, getClientExtensionResults: () => ({}), - type: 'webauthn.create', + type: 'public-key', authenticatorAttachment: '', }); }); @@ -219,9 +219,9 @@ test('should return "cable" transport from response', async () => { type: 'webauthn.create', }); - const response = await startRegistration(goodOpts1); + const regResponse = await startRegistration(goodOpts1); - expect(response.transports).toEqual(['cable']); + expect(regResponse.response.transports).toEqual(['cable']); }); test('should cancel an existing call when executed again', async () => { diff --git a/packages/browser/src/methods/startRegistration.ts b/packages/browser/src/methods/startRegistration.ts index bc30707..546347b 100644 --- a/packages/browser/src/methods/startRegistration.ts +++ b/packages/browser/src/methods/startRegistration.ts @@ -1,7 +1,8 @@ import { PublicKeyCredentialCreationOptionsJSON, RegistrationCredential, - RegistrationCredentialJSON, + RegistrationResponseJSON, + AuthenticatorTransportFuture, } from '@simplewebauthn/typescript-types'; import { utf8StringToBuffer } from '../helpers/utf8StringToBuffer'; @@ -11,15 +12,16 @@ 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 * - * @param creationOptionsJSON Output from @simplewebauthn/server's generateRegistrationOptions(...) + * @param creationOptionsJSON Output from **@simplewebauthn/server**'s `generateRegistrationOptions()` */ export async function startRegistration( creationOptionsJSON: PublicKeyCredentialCreationOptionsJSON, -): Promise<RegistrationCredentialJSON> { +): Promise<RegistrationResponseJSON> { if (!browserSupportsWebAuthn()) { throw new Error('WebAuthn is not supported in this browser'); } @@ -32,7 +34,9 @@ export async function startRegistration( ...creationOptionsJSON.user, id: utf8StringToBuffer(creationOptionsJSON.user.id), }, - excludeCredentials: creationOptionsJSON.excludeCredentials.map(toPublicKeyCredentialDescriptor), + excludeCredentials: creationOptionsJSON.excludeCredentials?.map( + toPublicKeyCredentialDescriptor, + ), }; // Finalize options @@ -54,25 +58,22 @@ export async function startRegistration( const { id, rawId, response, type } = credential; - // Convert values to base64 to make it easier to send back to the server - const credentialJSON: RegistrationCredentialJSON = { + // Continue to play it safe with `getTransports()` for now, even when L3 types say it's required + let transports: AuthenticatorTransportFuture[] | undefined = undefined; + if (typeof response.getTransports === 'function') { + transports = response.getTransports(); + } + + return { id, rawId: bufferToBase64URLString(rawId), response: { attestationObject: bufferToBase64URLString(response.attestationObject), clientDataJSON: bufferToBase64URLString(response.clientDataJSON), + transports, }, 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; } |