summaryrefslogtreecommitdiff
path: root/components/auth
diff options
context:
space:
mode:
Diffstat (limited to 'components/auth')
-rw-r--r--components/auth/Auth.tsx164
1 files changed, 28 insertions, 136 deletions
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 }}
+ />
+ </>
);
}