summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/passkey.ts71
-rw-r--r--lib/types.ts2
2 files changed, 68 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}` };
}
}
diff --git a/lib/types.ts b/lib/types.ts
new file mode 100644
index 0000000..a22e8be
--- /dev/null
+++ b/lib/types.ts
@@ -0,0 +1,2 @@
+export type Result<T> = { ok: T } | { error: string };
+export type AsyncRes<T> = Promise<Result<T>>;