diff options
author | Matthew Miller <matthew@millerti.me> | 2023-06-25 11:16:24 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-25 11:16:24 -0700 |
commit | 67aad754c531a53bc0f9915ebdfc0e995df74a47 (patch) | |
tree | 9bf7c563778134b2e8b8df1c423f04d7e216ff37 | |
parent | ba4ce17cbc5e6aed06e8b909f47784ccd06c78d8 (diff) | |
parent | 5787bb38d60bda3bcada741353016ca328f116f0 (diff) |
Merge pull request #400 from MasterKale/feat/json-type-updatesm7n-openwrtopenwrt
feat/json-type-updates
-rw-r--r-- | packages/browser/src/methods/startRegistration.test.ts | 50 | ||||
-rw-r--r-- | packages/browser/src/methods/startRegistration.ts | 23 | ||||
-rw-r--r-- | packages/typescript-types/src/index.ts | 6 |
3 files changed, 79 insertions, 0 deletions
diff --git a/packages/browser/src/methods/startRegistration.test.ts b/packages/browser/src/methods/startRegistration.test.ts index debaba3..e27099d 100644 --- a/packages/browser/src/methods/startRegistration.test.ts +++ b/packages/browser/src/methods/startRegistration.test.ts @@ -250,6 +250,56 @@ test('should return authenticatorAttachment if present', async () => { expect(response.authenticatorAttachment).toEqual('cross-platform'); }); +test('should return convenience values if getters present', async () => { + /** + * I call them "convenience values" because the getters for public key algorithm, + * public key bytes, and authenticator data are alternative ways to access information + * that's already buried in the response. + */ + // Mock extension return values from authenticator + mockNavigatorCreate.mockImplementation((): Promise<any> => { + return new Promise(resolve => { + resolve({ + response: { + getPublicKeyAlgorithm: () => 777, + getPublicKey: () => new Uint8Array([0, 0, 0, 0]).buffer, + getAuthenticatorData: () => new Uint8Array([0, 0, 0, 0]).buffer, + }, + getClientExtensionResults: () => { }, + }); + }); + }); + + const response = await startRegistration(goodOpts1); + + expect(response.response.publicKeyAlgorithm).toEqual(777); + expect(response.response.publicKey).toEqual('AAAAAA'); + expect(response.response.authenticatorData).toEqual('AAAAAA'); +}); + +test('should not return convenience values if getters missing', async () => { + /** + * I call them "convenience values" because the getters for public key algorithm, + * public key bytes, and authenticator data are alternative ways to access information + * that's already buried in the response. + */ + // Mock extension return values from authenticator + mockNavigatorCreate.mockImplementation((): Promise<any> => { + return new Promise(resolve => { + resolve({ + response: {}, + getClientExtensionResults: () => { }, + }); + }); + }); + + const response = await startRegistration(goodOpts1); + + expect(response.response.publicKeyAlgorithm).toBeUndefined(); + expect(response.response.publicKey).toBeUndefined(); + expect(response.response.authenticatorData).toBeUndefined(); +}); + describe('WebAuthnError', () => { describe('AbortError', () => { const AbortError = generateCustomError('AbortError'); diff --git a/packages/browser/src/methods/startRegistration.ts b/packages/browser/src/methods/startRegistration.ts index 546347b..5b97a5e 100644 --- a/packages/browser/src/methods/startRegistration.ts +++ b/packages/browser/src/methods/startRegistration.ts @@ -64,6 +64,26 @@ export async function startRegistration( transports = response.getTransports(); } + // L3 says this is required, but browser and webview support are still not guaranteed. + let responsePublicKeyAlgorithm: number | undefined = undefined; + if (typeof response.getPublicKeyAlgorithm === 'function') { + responsePublicKeyAlgorithm = response.getPublicKeyAlgorithm(); + } + + let responsePublicKey: string | undefined = undefined; + if (typeof response.getPublicKey === 'function') { + const _publicKey = response.getPublicKey(); + if (_publicKey !== null) { + responsePublicKey = bufferToBase64URLString(_publicKey); + } + } + + // L3 says this is required, but browser and webview support are still not guaranteed. + let responseAuthenticatorData: string | undefined; + if (typeof response.getAuthenticatorData === 'function') { + responseAuthenticatorData = bufferToBase64URLString(response.getAuthenticatorData()); + } + return { id, rawId: bufferToBase64URLString(rawId), @@ -71,6 +91,9 @@ export async function startRegistration( attestationObject: bufferToBase64URLString(response.attestationObject), clientDataJSON: bufferToBase64URLString(response.clientDataJSON), transports, + publicKeyAlgorithm: responsePublicKeyAlgorithm, + publicKey: responsePublicKey, + authenticatorData: responseAuthenticatorData, }, type, clientExtensionResults: credential.getClientExtensionResults(), diff --git a/packages/typescript-types/src/index.ts b/packages/typescript-types/src/index.ts index 8435241..33193c9 100644 --- a/packages/typescript-types/src/index.ts +++ b/packages/typescript-types/src/index.ts @@ -19,6 +19,7 @@ import type { AuthenticatorAttachment, PublicKeyCredentialCreationOptions, PublicKeyCredentialRequestOptions, + COSEAlgorithmIdentifier, } from './dom'; export * from './dom'; @@ -129,7 +130,12 @@ export interface AuthenticatorAttestationResponseJSON { clientDataJSON: Base64URLString; attestationObject: Base64URLString; // Optional in L2, but becomes required in L3. Play it safe until L3 becomes Recommendation + authenticatorData?: Base64URLString; + // Optional in L2, but becomes required in L3. Play it safe until L3 becomes Recommendation transports?: AuthenticatorTransportFuture[]; + // Optional in L2, but becomes required in L3. Play it safe until L3 becomes Recommendation + publicKeyAlgorithm?: COSEAlgorithmIdentifier; + publicKey?: Base64URLString; } /** |