"use client"; import { useState } from "react"; import { Button, ButtonVariants } from "./Button"; import { useForm } from "react-hook-form"; import { useRouter } from "next/navigation"; import { Spinner } from "./Spinner"; import Alert from "./Alert"; import { RegisterPasskeyResponse } from "@zitadel/server"; import { coerceToArrayBuffer, coerceToBase64Url } from "#/utils/base64"; type Inputs = {}; type Props = { sessionId: string; isPrompt: boolean; }; export default function RegisterPasskey({ sessionId, isPrompt }: Props) { const { register, handleSubmit, formState } = useForm({ mode: "onBlur", }); const [error, setError] = useState(""); const [loading, setLoading] = useState(false); const router = useRouter(); async function submitRegister() { setError(""); setLoading(true); const res = await fetch("/passkeys", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ sessionId, }), }); const response = await res.json(); setLoading(false); if (!res.ok) { setError(response.details); return Promise.reject(response.details); } return response; } async function submitVerify( passkeyId: string, passkeyName: string, publicKeyCredential: any, sessionId: string ) { setLoading(true); const res = await fetch("/passkeys/verify", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ passkeyId, passkeyName, publicKeyCredential, sessionId, }), }); const response = await res.json(); setLoading(false); if (!res.ok) { setError(response.details); return Promise.reject(response.details); } return response; } function submitRegisterAndContinue(value: Inputs): Promise { return submitRegister().then((resp: RegisterPasskeyResponse) => { const passkeyId = resp.passkeyId; if ( resp.publicKeyCredentialCreationOptions && resp.publicKeyCredentialCreationOptions.publicKey ) { resp.publicKeyCredentialCreationOptions.publicKey.challenge = coerceToArrayBuffer( resp.publicKeyCredentialCreationOptions.publicKey.challenge, "challenge" ); resp.publicKeyCredentialCreationOptions.publicKey.user.id = coerceToArrayBuffer( resp.publicKeyCredentialCreationOptions.publicKey.user.id, "challenge" ); if ( resp.publicKeyCredentialCreationOptions.publicKey.excludeCredentials ) { resp.publicKeyCredentialCreationOptions.publicKey.excludeCredentials.map( (cred: any) => { cred.id = coerceToArrayBuffer( cred.id as string, "excludeCredentials.id" ); return cred; } ); } navigator.credentials .create(resp.publicKeyCredentialCreationOptions) .then((resp) => { console.log(resp); if ( resp && (resp as any).response.attestationObject && (resp as any).response.clientDataJSON && (resp as any).rawId ) { const attestationObject = (resp as any).response .attestationObject; const clientDataJSON = (resp as any).response.clientDataJSON; const rawId = (resp as any).rawId; const data = { id: resp.id, rawId: coerceToBase64Url(rawId, "rawId"), type: resp.type, response: { attestationObject: coerceToBase64Url( attestationObject, "attestationObject" ), clientDataJSON: coerceToBase64Url( clientDataJSON, "clientDataJSON" ), }, }; console.log(data); return submitVerify(passkeyId, "", data, sessionId); } else { setLoading(false); setError("An error on registering passkey"); return null; } }) .catch((error) => { console.error(error); setLoading(false); // setError(error); return null; }); } // return router.push(`/accounts`); }); } const { errors } = formState; return (
{error && (
{error}
)}
{isPrompt ? ( ) : ( )}
); }