Move to service layer

This commit is contained in:
Manav Rathi
2024-06-08 22:09:48 +05:30
parent b6761bd5b2
commit 81e274babd
2 changed files with 50 additions and 42 deletions

View File

@@ -5,7 +5,6 @@ import { nullToUndefined } from "@/utils/transform";
import { VerticallyCentered } from "@ente/shared/components/Container";
import EnteButton from "@ente/shared/components/EnteButton";
import EnteSpinner from "@ente/shared/components/EnteSpinner";
import { fromB64URLSafeNoPadding } from "@ente/shared/crypto/internal/libsodium";
import HTTPService from "@ente/shared/network/HTTPService";
import InfoIcon from "@mui/icons-material/Info";
import { Paper, Typography, styled } from "@mui/material";
@@ -13,6 +12,7 @@ import { t } from "i18next";
import _sodium from "libsodium-wrappers";
import { useEffect, useState } from "react";
import {
authenticatePasskey,
beginPasskeyAuthentication,
finishPasskeyAuthentication,
isWebAuthnSupported,
@@ -99,23 +99,9 @@ const Page = () => {
setStatus("waitingForUser");
let credential: Credential | null = null;
let tries = 0;
const maxTries = 3;
while (tries < maxTries) {
try {
credential = await getCredential(beginData.options.publicKey);
} catch (e) {
log.error("Couldn't get credential", e);
continue;
} finally {
tries++;
}
break;
}
const credential = await authenticatePasskey(
beginData.options.publicKey,
);
if (!credential) {
setStatus("failed");
@@ -147,30 +133,6 @@ const Page = () => {
window.location.href = `${redirect}?response=${encodedResponse}`;
};
const getCredential = async (
publicKey: any,
timeoutMillis: number = 60000, // Default timeout of 60 seconds
): Promise<Credential | null> => {
publicKey.challenge = await fromB64URLSafeNoPadding(
publicKey.challenge,
);
for (const listItem of publicKey.allowCredentials ?? []) {
listItem.id = await fromB64URLSafeNoPadding(listItem.id);
// note: we are orverwriting the transports array with all possible values.
// This is because the browser will only prompt the user for the transport that is available.
// Warning: In case of invalid transport value, the webauthn will fail on Safari & iOS browsers
listItem.transports = ["usb", "nfc", "ble", "internal"];
}
publicKey.timeout = timeoutMillis;
const publicKeyCredentialCreationOptions: CredentialRequestOptions = {
publicKey: publicKey,
};
const credential = await navigator.credentials.get(
publicKeyCredentialCreationOptions,
);
return credential;
};
useEffect(() => {
void authenticate();
}, []);

View File

@@ -355,6 +355,52 @@ export const beginPasskeyAuthentication = async (
}
};
/**
* Authenticate using a passkey that the user has previously created for the
* current domain.
*
* @param options
*/
export const authenticatePasskey = async (
publicKey: PublicKeyCredentialRequestOptions,
) => {
let tries = 0;
const maxTries = 3;
while (tries < maxTries) {
try {
return await getCredential(publicKey);
} catch (e) {
log.error("Couldn't get credential", e);
continue;
} finally {
tries++;
}
}
return undefined;
};
const getCredential = async (publicKey: any): Promise<Credential | null> => {
const timeoutMillis: number = 60000; // Default timeout of 60 seconds
publicKey.challenge = await fromB64URLSafeNoPadding(publicKey.challenge);
for (const listItem of publicKey.allowCredentials ?? []) {
listItem.id = await fromB64URLSafeNoPadding(listItem.id);
// note: we are orverwriting the transports array with all possible values.
// This is because the browser will only prompt the user for the transport that is available.
// Warning: In case of invalid transport value, the webauthn will fail on Safari & iOS browsers
listItem.transports = ["usb", "nfc", "ble", "internal"];
}
publicKey.timeout = timeoutMillis;
const publicKeyCredentialCreationOptions: CredentialRequestOptions = {
publicKey: publicKey,
};
const credential = await navigator.credentials.get(
publicKeyCredentialCreationOptions,
);
return credential;
};
export const finishPasskeyAuthentication = async (
credential: Credential,
sessionId: string,