1 import { arrayToBinaryString, encodeBase64 } from '@proton/crypto/lib/utils';
4 AuthenticationCredentialsPayload,
6 PublicKeyCredentialRequestOptionsSerialized,
9 export * from './interface';
11 const convertRequestToExpectedFormat = (
12 publicKey: PublicKeyCredentialRequestOptionsSerialized
13 ): CredentialRequestOptions => {
14 const { challenge, allowCredentials, ...rest } = publicKey;
19 challenge: new Uint8Array(challenge).buffer,
20 allowCredentials: allowCredentials?.map((credentials) => ({
22 id: new Uint8Array(credentials.id),
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');
37 const response = publicKeyCredentials.response as AuthenticatorAttestationResponse & {
38 signature: ArrayBuffer;
39 authenticatorData: ArrayBuffer;
42 AuthenticationOptions: authenticationOptions,
43 ClientData: response.clientDataJSON
44 ? encodeBase64(arrayToBinaryString(new Uint8Array(response.clientDataJSON)))
46 AuthenticatorData: response.authenticatorData
47 ? encodeBase64(arrayToBinaryString(new Uint8Array(response.authenticatorData)))
49 Signature: response.signature ? encodeBase64(arrayToBinaryString(new Uint8Array(response.signature))) : null!,
50 CredentialID: publicKeyCredentials.rawId ? [...new Uint8Array(publicKeyCredentials.rawId)] : null!,