diff options
Diffstat (limited to 'lib/passkey.ts')
-rw-r--r-- | lib/passkey.ts | 71 |
1 files changed, 66 insertions, 5 deletions
diff --git a/lib/passkey.ts b/lib/passkey.ts index 573c62b..81a21a5 100644 --- a/lib/passkey.ts +++ b/lib/passkey.ts @@ -1,8 +1,14 @@ +"use client"; + +import { Platform } from "react-native"; +import * as SecureStore from "expo-secure-store"; +import type { AsyncRes } from "./types"; + const PASSKEY_CREDENTIAL_ID_KEY = "urbit_wallet_passkey_id"; const RELYING_PARTY_ID = "wallet.urbit.org"; // Change this to your domain const RELYING_PARTY_NAME = "Urbit Wallet"; -async function createPasskey() { +export async function createPasskey(): AsyncRes<PublicKeyCredential> { const pkok = await window.PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable(); console.log({ pkok }); @@ -117,15 +123,70 @@ async function createPasskey() { if (credential) { // Store the credential ID for later use - // await SecureStore.setItemAsync(PASSKEY_CREDENTIAL_ID_KEY, credential.id); + await SecureStore.setItemAsync(PASSKEY_CREDENTIAL_ID_KEY, credential.id); console.log("Passkey created successfully", credential.id); - return true; + return { ok: credential }; } - return false; + return { error: "Failed to create passkey" }; } catch (error) { console.error("Error creating passkey:", error); - return false; + return { error: `${error}` }; + } +} + +export async function authenticateWithPasskey(): AsyncRes<PublicKeyCredential> { + // if (Platform.OS !== "web") { + // return false; + // } + + try { + const credentialId = await SecureStore.getItemAsync( + PASSKEY_CREDENTIAL_ID_KEY, + ); + + if (!credentialId) { + console.log("No passkey found"); + return { error: "No passkey found" }; + } + + // Generate a random challenge + const challenge = new Uint8Array(32); + crypto.getRandomValues(challenge); + + const getCredentialOptions: CredentialRequestOptions = { + publicKey: { + challenge, + rpId: + window.location.hostname === "localhost" + ? "localhost" + : RELYING_PARTY_ID, + allowCredentials: [ + { + id: Uint8Array.from(atob(credentialId), (c) => c.charCodeAt(0)), + type: "public-key", + transports: ["internal", "hybrid"] as AuthenticatorTransport[], + }, + ], + userVerification: "preferred", + timeout: 60000, + }, + }; + + const credential = (await navigator.credentials.get( + getCredentialOptions, + )) as PublicKeyCredential; + + if (credential) { + // In a production app, you would send the assertion to your server + // to verify it. For this demo, we're just checking if we got a credential. + console.log("Passkey authentication successful"); + return { ok: credential }; + } + + return { error: "failed to generate creds" }; + } catch (error) { + return { error: `${error}` }; } } |