From dc04d1eb853ceb35ba81c395cc9e6af6d11721b8 Mon Sep 17 00:00:00 2001 From: Josh Remaley Date: Mon, 13 Nov 2023 08:26:04 -0600 Subject: [PATCH] update to support body payload and hash --- nip98.ts | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/nip98.ts b/nip98.ts index 3e78ec6..6ea3937 100644 --- a/nip98.ts +++ b/nip98.ts @@ -1,9 +1,16 @@ +import { bytesToHex } from '@noble/hashes/utils' +import { sha256 } from '@noble/hashes/sha256' import { base64 } from '@scure/base' import { Event, EventTemplate, Kind, getBlankEvent, verifySignature } from './event' import { utf8Decoder, utf8Encoder } from './utils' const _authorizationScheme = 'Nostr ' +function hashPayload(payload: any): string { + const hash = sha256(utf8Encoder.encode(JSON.stringify(payload))) + return bytesToHex(hash) +} + /** * Generate token for NIP-98 flow. * @@ -16,6 +23,7 @@ export async function getToken( httpMethod: string, sign: (e: EventTemplate) => Promise> | Event, includeAuthorizationScheme: boolean = false, + payload?: Record, ): Promise { if (!loginUrl || !httpMethod) throw new Error('Missing loginUrl or httpMethod') @@ -25,6 +33,11 @@ export async function getToken( ['u', loginUrl], ['method', httpMethod], ] + + if (payload) { + event.tags.push(['payload', bytesToHex(sha256(utf8Encoder.encode(JSON.stringify(payload))))]) + } + event.created_at = Math.round(new Date().getTime() / 1000) const signedEvent = await sign(event) @@ -66,7 +79,7 @@ export async function unpackEventFromToken(token: string): Promise { return event } -export async function validateEvent(event: Event, url: string, method: string): Promise { +export async function validateEvent(event: Event, url: string, method: string, body?: any): Promise { if (!event) { throw new Error('Invalid nostr event') } @@ -96,5 +109,13 @@ export async function validateEvent(event: Event, url: string, method: string): throw new Error('Invalid nostr event, method tag invalid') } + if (Boolean(body) && Object.keys(body).length > 0) { + const payloadTag = event.tags.find(t => t[0] === 'payload') + const payloadHash = bytesToHex(sha256(utf8Encoder.encode(JSON.stringify(body)))) + if (payloadTag?.[1] !== payloadHash) { + throw new Error('Invalid payload tag hash, does not match request body hash') + } + } + return true }