Use same lock values as mobile clients
[ProtonMail-WebClient.git] / packages / shared / lib / webauthn / get.ts
blob2d6e070629aae809ada0a0211cecc30e357744e7
1 import { arrayToBinaryString, encodeBase64 } from '@proton/crypto/lib/utils';
3 import type {
4     AuthenticationCredentialsPayload,
5     AuthenticationOptions,
6     PublicKeyCredentialRequestOptionsSerialized,
7 } from './interface';
9 export * from './interface';
11 const convertRequestToExpectedFormat = (
12     publicKey: PublicKeyCredentialRequestOptionsSerialized
13 ): CredentialRequestOptions => {
14     const { challenge, allowCredentials, ...rest } = publicKey;
16     return {
17         publicKey: {
18             ...rest,
19             challenge: new Uint8Array(challenge).buffer,
20             allowCredentials: allowCredentials?.map((credentials) => ({
21                 ...credentials,
22                 id: new Uint8Array(credentials.id),
23             })),
24         },
25     };
28 export const getAuthentication = async (
29     authenticationOptions: AuthenticationOptions
30 ): Promise<AuthenticationCredentialsPayload> => {
31     const credentialRequestOptions = convertRequestToExpectedFormat(authenticationOptions.publicKey);
32     const credentials = await navigator.credentials.get(credentialRequestOptions);
33     const publicKeyCredentials = credentials as PublicKeyCredential;
34     if (!credentials || !('rawId' in credentials)) {
35         throw new Error('No credentials received, unsupported browser');
36     }
37     const response = publicKeyCredentials.response as AuthenticatorAttestationResponse & {
38         signature: ArrayBuffer;
39         authenticatorData: ArrayBuffer;
40     };
41     return {
42         AuthenticationOptions: authenticationOptions,
43         ClientData: response.clientDataJSON
44             ? encodeBase64(arrayToBinaryString(new Uint8Array(response.clientDataJSON)))
45             : null!,
46         AuthenticatorData: response.authenticatorData
47             ? encodeBase64(arrayToBinaryString(new Uint8Array(response.authenticatorData)))
48             : null!,
49         Signature: response.signature ? encodeBase64(arrayToBinaryString(new Uint8Array(response.signature))) : null!,
50         CredentialID: publicKeyCredentials.rawId ? [...new Uint8Array(publicKeyCredentials.rawId)] : null!,
51     };