diff --git a/src/sign.ts b/src/sign.ts index f4f8d2e..94b8c62 100644 --- a/src/sign.ts +++ b/src/sign.ts @@ -5,14 +5,14 @@ import { type Event, type EventTemplate, finishEvent, HTTPException } from '@/de import { connectResponseSchema } from '@/schemas/nostr.ts'; import { jsonSchema } from '@/schema.ts'; import { Sub } from '@/subs.ts'; -import { Time } from '@/utils.ts'; +import { eventMatchesTemplate, Time } from '@/utils.ts'; import { createAdminEvent } from '@/utils/web.ts'; /** * Sign Nostr event using the app context. * * - If a secret key is provided, it will be used to sign the event. - * - If `X-Nostr-Sign` is passed, it will use a NIP-46 to sign the event. + * - If `X-Nostr-Sign` is passed, it will use NIP-46 to sign the event. */ async function signEvent(event: EventTemplate, c: AppContext): Promise> { const seckey = c.get('seckey'); @@ -54,13 +54,14 @@ async function signNostrConnect(event: EventTemplate< tags: [['p', pubkey]], }, c); - return awaitSignedEvent(pubkey, messageId, c); + return awaitSignedEvent(pubkey, messageId, event, c); } /** Wait for signed event to be sent through Nostr relay. */ async function awaitSignedEvent( pubkey: string, messageId: string, + template: EventTemplate, c: AppContext, ): Promise> { const sub = Sub.sub(messageId, '1', [{ kinds: [24133], authors: [pubkey], '#p': [Conf.pubkey] }]); @@ -79,12 +80,17 @@ async function awaitSignedEvent( for await (const event of sub) { if (event.kind === 24133) { const decrypted = await decryptAdmin(event.pubkey, event.content); - const msg = jsonSchema.pipe(connectResponseSchema).parse(decrypted); - if (msg.id === messageId) { + const result = jsonSchema + .pipe(connectResponseSchema) + .refine((msg) => msg.id === messageId) + .refine((msg) => eventMatchesTemplate(msg.result, template)) + .safeParse(decrypted); + + if (result.success) { close(); clearTimeout(timeout); - return msg.result as Event; + return result.data.result as Event; } } } diff --git a/src/utils.ts b/src/utils.ts index ede1e9c..1836298 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,4 +1,4 @@ -import { type Event, nip19, z } from '@/deps.ts'; +import { type Event, type EventTemplate, getEventHash, nip19, z } from '@/deps.ts'; import { getAuthor } from '@/queries.ts'; import { lookupNip05Cached } from '@/utils/nip05.ts'; @@ -106,11 +106,17 @@ function dedupeEvents(events: Event[]): Event[] { return [...new Map(events.map((event) => [event.id, event])).values()]; } +/** Ensure the template and event match on their shared keys. */ +function eventMatchesTemplate(event: Event, template: EventTemplate): boolean { + return getEventHash(event) === getEventHash({ pubkey: event.pubkey, ...template }); +} + export { bech32ToPubkey, dedupeEvents, eventAge, eventDateComparator, + eventMatchesTemplate, findTag, isFollowing, isRelay,