Use same lock values as mobile clients
[ProtonMail-WebClient.git] / packages / shared / lib / webauthn / create.ts
blobab9257f9556501a60502267b3b0f7f0168de3168
1 import { arrayToBinaryString, encodeBase64 } from '@proton/crypto/lib/utils';
3 import type {
4     PublicKeyCredentialCreationOptionsSerialized,
5     RegisterCredentials,
6     RegisterCredentialsPayload,
7 } from './interface';
9 export * from './interface';
11 const convertCreationToExpectedFormat = (
12     publicKey: PublicKeyCredentialCreationOptionsSerialized
13 ): CredentialCreationOptions => {
14     const { challenge, user, excludeCredentials, ...rest } = publicKey;
16     return {
17         publicKey: {
18             ...rest,
19             challenge: new Uint8Array(challenge).buffer,
20             user: {
21                 ...user,
22                 id: new Uint8Array(user.id),
23             },
24             excludeCredentials: excludeCredentials?.map((credentials) => ({
25                 ...credentials,
26                 id: new Uint8Array(credentials.id),
27             })),
28         },
29     };
32 export const getCreatePayload = async (
33     registerCredentials: RegisterCredentials
34 ): Promise<RegisterCredentialsPayload> => {
35     const credentialCreationOptions = convertCreationToExpectedFormat(
36         registerCredentials.RegistrationOptions.publicKey
37     );
38     const credentials = await navigator.credentials.create(credentialCreationOptions);
39     const publicKeyCredentials = credentials as PublicKeyCredential;
40     if (!credentials || !('rawId' in credentials) || !('attestationObject' in publicKeyCredentials.response)) {
41         throw new Error('No credentials received');
42     }
43     const response = publicKeyCredentials.response as AuthenticatorAttestationResponse & {
44         getTransports: () => string[];
45     };
46     return {
47         RegistrationOptions: registerCredentials.RegistrationOptions,
48         ClientData: response.clientDataJSON
49             ? encodeBase64(arrayToBinaryString(new Uint8Array(response.clientDataJSON)))
50             : null!,
51         AttestationObject: response.attestationObject
52             ? encodeBase64(arrayToBinaryString(new Uint8Array(response.attestationObject)))
53             : null!,
54         Transports: response.getTransports?.() || [],
55         Name: '',
56     };