From 8588de25f16486b56ef0ad533013bd8cb48ff120 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Thu, 9 Jan 2025 23:44:40 -0800 Subject: nostr signing --- src/routes/(app)/+layout.svelte | 6 +- .../(app)/[username]/(profile)/+layout.svelte | 22 ++-- src/routes/(app)/messages/[recipient]/+page.svelte | 2 +- src/routes/(app)/settings/+layout.svelte | 28 +++-- src/routes/(app)/settings/nostr/+page.server.ts | 6 ++ src/routes/(app)/settings/nostr/+page.svelte | 116 ++++++++++----------- src/routes/(static)/+layout.svelte | 2 + src/routes/(static)/login/+page.server.ts | 8 +- src/routes/(static)/login/+page.svelte | 76 ++++++++++---- src/routes/(static)/register/+page.server.ts | 4 +- src/routes/(static)/register/+page.svelte | 48 +++++---- 11 files changed, 197 insertions(+), 121 deletions(-) (limited to 'src/routes') diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte index e179005f..d037e5be 100644 --- a/src/routes/(app)/+layout.svelte +++ b/src/routes/(app)/+layout.svelte @@ -8,7 +8,7 @@ request, ndef, passwordPrompt, - signaturePrompt, + selectSigner, password, pin, theme as themeStore, @@ -91,8 +91,8 @@ {/if} -{#if browser && $signaturePrompt} - +{#if browser} + {/if} diff --git a/src/routes/(app)/[username]/(profile)/+layout.svelte b/src/routes/(app)/[username]/(profile)/+layout.svelte index a83ed8d0..a5f336e7 100644 --- a/src/routes/(app)/[username]/(profile)/+layout.svelte +++ b/src/routes/(app)/[username]/(profile)/+layout.svelte @@ -77,7 +77,7 @@ }; try { - await sign({ event, user }); + await sign(event); await send(event); } catch (e) { console.log(e); @@ -205,7 +205,8 @@ )}`} class="my-auto" > - + @@ -222,7 +223,8 @@ > - + @@ -234,12 +236,14 @@ {#if user && user.username !== subject.username && subject.pubkey} {#if following} {:else} {/if} @@ -266,7 +270,8 @@ class="rounded-2xl border py-5 px-6 font-bold hover:opacity-80 flex w-60" >
- +
@@ -296,7 +301,10 @@
- {s((1 * sats) / rate)} = {f(1, currency, locale, 0, 0)} diff --git a/src/routes/(app)/messages/[recipient]/+page.svelte b/src/routes/(app)/messages/[recipient]/+page.svelte index bc1a6383..d1cf6f94 100644 --- a/src/routes/(app)/messages/[recipient]/+page.svelte +++ b/src/routes/(app)/messages/[recipient]/+page.svelte @@ -91,7 +91,7 @@ user, }); event.id = getEventHash(event); - await sign({ event, user }); + await sign(event); await send(event); sent = true; diff --git a/src/routes/(app)/settings/+layout.svelte b/src/routes/(app)/settings/+layout.svelte index 85e5b0e6..c6cc81c4 100644 --- a/src/routes/(app)/settings/+layout.svelte +++ b/src/routes/(app)/settings/+layout.svelte @@ -9,7 +9,7 @@ import Pin from "$comp/Pin.svelte"; import { loading, t } from "$lib/translations"; import { fd, fail, auth, post, sleep, warning, success } from "$lib/utils"; - import { avatar, banner, password, pin, save } from "$lib/store"; + import { avatar, banner, signer, password, pin, save } from "$lib/store"; import { upload } from "$lib/upload"; import { page } from "$app/stores"; import { sign, send, setNsec } from "$lib/nostr"; @@ -53,10 +53,21 @@ }, }); - if (data.get("newNsec")) { - await setNsec(user, data.get("newNsec")); - data.set("nsec", user.nsec); - data.set("pubkey", user.pubkey); + if (!user.pubkey || user.pubkey === prev.pubkey) { + data.delete("pubkey"); + } else { + signer.set( + user.extension ? { method: "extension", ready: true } : null, + ); + let event = { + kind: 1, + created_at: Date.now(), + content: user.challenge, + tags: [], + }; + + let signedEvent = await sign(event); + data.set("event", JSON.stringify(signedEvent)); } if ($avatar) { @@ -89,7 +100,7 @@ } if ( - ["username", "about", "picture"].some( + ["username", "about", "picture", "display", "banner"].some( (a) => user[a] && user[a] !== prev[a], ) ) { @@ -101,14 +112,17 @@ name: user.username, about: user.about, picture: user.picture, + banner: user.banner, + displayName: user.display, }), tags: [], }; try { - await sign({ event, user }); + await sign(event); await send(event); } catch (e) { + console.log(e); warning("Nostr profile could not be updated"); } } diff --git a/src/routes/(app)/settings/nostr/+page.server.ts b/src/routes/(app)/settings/nostr/+page.server.ts index 4145935e..b4bb124b 100644 --- a/src/routes/(app)/settings/nostr/+page.server.ts +++ b/src/routes/(app)/settings/nostr/+page.server.ts @@ -1,5 +1,11 @@ +import { get } from "$lib/utils"; import updateUser from "$lib/settings"; +export const load = async () => { + const { challenge } = await get("/challenge"); + return { challenge }; +}; + export const actions = { default: updateUser, }; diff --git a/src/routes/(app)/settings/nostr/+page.svelte b/src/routes/(app)/settings/nostr/+page.svelte index 3757f96f..cfcfaf39 100644 --- a/src/routes/(app)/settings/nostr/+page.svelte +++ b/src/routes/(app)/settings/nostr/+page.svelte @@ -3,35 +3,29 @@ import { page } from "$app/stores"; import { tick } from "svelte"; import { t } from "$lib/translations"; - import { copy } from "$lib/utils"; + import { copy, fail } from "$lib/utils"; import { PUBLIC_COINOS_PUBKEY as pk, PUBLIC_COINOS_RELAY as relay, } from "$env/static/public"; + import { signer, save } from "$lib/store"; let { data } = $props(); - let { user } = $derived(data); - let { id, npub } = $derived(user); + let { challenge, user } = $derived(data); + let { npub } = $state(user); - let importing = $state(), - newNsec = $state(), + let newNsec = $state(), nsec = $state(), pin = $state(""), revealNsec = $state(), revealNwc = $state(); - let toggleImporting = () => { - revealNsec = false; - importing = !importing; - }; - let toggleNsec = async () => { try { nsec = await getNsec(user); revealNsec = !revealNsec; - importing = false; } catch (e) { - console.log(e); + fail("Failed to decrypt nsec"); } }; @@ -42,9 +36,19 @@ )}&secret=${user.nwc}&lud16=${lud16}`, ); let toggleNwc = () => (revealNwc = !revealNwc); + + let extension = $state(); + let getPubkey = async () => { + extension = true; + npub = await window.nostr.getPublicKey(); + await tick(); + $save.click(); + };
+ +

@@ -83,12 +87,10 @@

{/if} -
+
{$t("user.nostrPubkey")}
-
- {npub} -
+
-
-
- + + {$t("user.settings.syncWithExtension")} +
-

- {$t("user.settings.nostrDescription")} -

- -
- - - -
- {#if importing} - - {/if} +

+ {$t("user.settings.nostrDescription")} +

+ +
+ +
- {#if revealNsec} - - {/if} -
+ + + {/if} +
+{/if} diff --git a/src/routes/(static)/+layout.svelte b/src/routes/(static)/+layout.svelte index 44310c97..a0061a19 100644 --- a/src/routes/(static)/+layout.svelte +++ b/src/routes/(static)/+layout.svelte @@ -1,6 +1,7 @@

{$t("login.signIn")}

- {#if form?.error && !form?.message.includes("2fa")}
{form.error} @@ -126,10 +159,17 @@ {$t("login.signIn")} - +

{$t("login.noAccount")}

{/if} - - diff --git a/src/routes/(static)/register/+page.server.ts b/src/routes/(static)/register/+page.server.ts index bf908c54..2e5c5f19 100644 --- a/src/routes/(static)/register/+page.server.ts +++ b/src/routes/(static)/register/+page.server.ts @@ -6,9 +6,9 @@ export const load = async ({ parent }) => { if (user) redirect(307, `/${user.username}`); const index = Math.floor(Math.random() * 64) + 1; - const { id } = await get("/challenge"); + const { challenge } = await get("/challenge"); - return { index, id }; + return { index, challenge }; }; export const actions = { diff --git a/src/routes/(static)/register/+page.svelte b/src/routes/(static)/register/+page.svelte index 77394e1a..e7819f4f 100644 --- a/src/routes/(static)/register/+page.svelte +++ b/src/routes/(static)/register/+page.svelte @@ -8,13 +8,12 @@ import { fly } from "svelte/transition"; import { enhance } from "$app/forms"; - import Nostr from "$comp/Nostr.svelte"; import Pin from "$comp/Pin.svelte"; import Spinner from "$comp/Spinner.svelte"; import PasswordInput from "$comp/PasswordInput.svelte"; import { focus, fail } from "$lib/utils"; - import { avatar, password, loginRedirect } from "$lib/store"; + import { avatar, signer, password, loginRedirect } from "$lib/store"; import { t } from "$lib/translations"; import { page } from "$app/stores"; import { @@ -24,11 +23,22 @@ adjectives, animals, } from "unique-names-generator"; + import { sign } from "$lib/nostr"; let { form, data } = $props(); - let { id } = $derived(data); - - let nostrSignin = $state(); + let { challenge } = $derived(data); + + page.subscribe(async () => { + if (browser) { + setTimeout(() => { + password.set(undefined); + pin.set(undefined); + signer.set(undefined); + localStorage.clear(); + sessionStorage.clear(); + }, 500); + } + }); let username = $state(); let { index } = $state(data); @@ -161,24 +171,22 @@ }); let nostrLogin = async () => { - let pubkey = await window.nostr.getPublicKey(); - const formData = new FormData(); - - let ev = { + let event = { kind: 1, - pubkey, created_at: Date.now(), - content: id, + content: challenge, tags: [], }; - try { - let signedEvent = await window.nostr.signEvent(ev); + let signedEvent = await sign(event); + const formData = new FormData(); + + try { formData.append("loginRedirect", redirect); formData.append("token", token); formData.append("event", JSON.stringify(signedEvent)); - formData.append("id", id); + formData.append("challenge", challenge); let response = await fetch("/login?/nostr", { method: "POST", @@ -309,8 +317,14 @@ {/if} - @@ -325,5 +339,3 @@

- - -- cgit v1.2.3