From 697ed671f394cbd07ea9751fe17f262744d99a49 Mon Sep 17 00:00:00 2001 From: polwex 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') 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 ( - + <> + + + ); } -- cgit v1.2.3