From 697ed671f394cbd07ea9751fe17f262744d99a49 Mon Sep 17 00:00:00 2001
From: polwex <polwex@sortug.com>
Date: Wed, 16 Jul 2025 08:51:35 +0700
Subject: m

---
 components/auth/Auth.tsx | 164 ++++++++---------------------------------------
 1 file changed, 28 insertions(+), 136 deletions(-)

(limited to 'components/auth/Auth.tsx')

diff --git a/components/auth/Auth.tsx b/components/auth/Auth.tsx
index 40512ca..2123774 100644
--- a/components/auth/Auth.tsx
+++ b/components/auth/Auth.tsx
@@ -1,149 +1,41 @@
 "use client";
 
+import { authenticateWithPasskey, createPasskey } from "@/lib/passkey";
 import PrimaryButton from "../PrimaryButton";
 import { SymbolView, SymbolViewProps, SymbolWeight } from "expo-symbols";
 import { useState } from "react";
+import toast from "react-hot-toast";
 import { Platform, StyleProp, ViewStyle } from "react-native";
 
-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";
-
 export function Passkee() {
   const [isLoading, setIsLoading] = useState(false);
-  async function handleCreatePasskey() {
-    const pkok =
-      await window.PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();
-    console.log({ pkok });
-
-    // if (Platform.OS !== "web") {
-    //   return false;
-    // }
-    console.log("creating passkey");
-
-    try {
-      // Generate a random user ID
-      const userId = new Uint8Array(16);
-      crypto.getRandomValues(userId);
-
-      // Generate a random challenge
-      const challenge = new Uint8Array(32);
-      crypto.getRandomValues(challenge);
-
-      const createCredentialOptions: CredentialCreationOptions = {
-        publicKey: {
-          // REQUIRED: Random challenge to prevent replay attacks
-          // Must be at least 16 bytes, we use 32 for extra security
-          challenge,
-
-          // REQUIRED: Relying Party (your website/app)
-          rp: {
-            // REQUIRED: Human-readable name shown in UI prompts
-            name: RELYING_PARTY_NAME,
-
-            // OPTIONAL: Domain that owns this credential
-            // If omitted, defaults to current domain
-            // Must match or be a registrable suffix of the current domain
-            id:
-              window.location.hostname === "localhost"
-                ? "localhost"
-                : RELYING_PARTY_ID,
-          },
-
-          // REQUIRED: User information
-          user: {
-            // REQUIRED: Unique user ID (must not contain PII)
-            // Used by authenticator to distinguish between accounts
-            id: userId,
-
-            // REQUIRED: Unique username/identifier for this RP
-            // Shown in some UI contexts, should be recognizable to user
-            name: "urbit-user",
-
-            // REQUIRED: Human-readable name for display
-            // Shown in account selectors and prompts
-            displayName: "Urbit Wallet User",
-          },
-
-          // REQUIRED: List of acceptable public key algorithms
-          // Order matters - authenticator will use first supported algorithm
-          pubKeyCredParams: [
-            { alg: -7, type: "public-key" }, // ES256 (ECDSA with SHA-256) - most common
-            { alg: -257, type: "public-key" }, // RS256 (RSASSA-PKCS1-v1_5) - fallback
-          ],
-
-          // OPTIONAL: Criteria for authenticator selection
-          authenticatorSelection: {
-            // OPTIONAL: "platform" (built-in like Touch ID) or "cross-platform" (USB key)
-            // Omitting allows both types
-            // authenticatorAttachment: "platform",
-
-            // OPTIONAL: User verification requirement
-            // "required" - must verify user (biometric/PIN)
-            // "preferred" - verify if possible, continue if not (default)
-            // "discouraged" - don't verify unless required by RP
-            userVerification: "preferred",
-
-            // OPTIONAL: Whether to create a discoverable credential (passkey)
-            // "required" - must create discoverable credential
-            // "preferred" - create if possible (default)
-            // "discouraged" - don't create discoverable credential
-            residentKey: "preferred",
-
-            // DEPRECATED: Use residentKey instead
-            // Kept for backwards compatibility with older authenticators
-            requireResidentKey: false,
-          },
-
-          // OPTIONAL: Time limit in milliseconds (default varies by browser)
-          // 60 seconds is reasonable for user interaction
-          timeout: 60000,
-
-          // OPTIONAL: Attestation preference (proof of authenticator legitimacy)
-          // "none" - no attestation needed (default, best for privacy)
-          // "indirect" - RP prefers attestation but allows anonymization
-          // "direct" - RP needs attestation from authenticator
-          // "enterprise" - RP needs attestation and device info (requires permission)
-          attestation: "none",
-
-          // OPTIONAL: List of credentials to exclude (prevent duplicates)
-          // excludeCredentials: [
-          //   { id: existingCredentialId, type: "public-key" }
-          // ],
-
-          // OPTIONAL: Extensions for additional features
-          // extensions: {
-          //   credProps: true,  // Request additional credential properties
-          //   hmacCreateSecret: true,  // For symmetric key operations
-          // },
-        },
-      };
-
-      const credential = (await navigator.credentials.create(
-        createCredentialOptions,
-      )) as PublicKeyCredential;
-      console.log({ credential });
-
-      if (credential) {
-        // Store the credential ID for later use
-        // await SecureStore.setItemAsync(PASSKEY_CREDENTIAL_ID_KEY, credential.id);
-
-        console.log("Passkey created successfully", credential.id);
-        return true;
-      }
-
-      return false;
-    } catch (error) {
-      console.error("Error creating passkey:", error);
-      return false;
-    }
+  async function handleCreate() {
+    //
+    const ok = await createPasskey();
+    if (!ok) toast.error("Error generating passkey");
+    else toast.success("Passkey generated!");
+  }
+  async function handleCheck() {
+    //
+    const ok = await authenticateWithPasskey();
+    if (!ok) toast.error("Can't login");
+    else toast.success("Passkey auth successful");
   }
+
   return (
-    <PrimaryButton
-      label="Create Passkey"
-      onPress={handleCreatePasskey}
-      isLoading={isLoading}
-      style={{ marginBottom: 16 }}
-    />
+    <>
+      <PrimaryButton
+        label="Create Passkey"
+        onPress={handleCreate}
+        isLoading={isLoading}
+        style={{ marginBottom: 16 }}
+      />
+      <PrimaryButton
+        label="Check Passkey"
+        onPress={handleCheck}
+        isLoading={isLoading}
+        style={{ marginBottom: 16 }}
+      />
+    </>
   );
 }
-- 
cgit v1.2.3

