Merge pull request #267 from Airtune/nip98-extract-pubkey

+nip98.unpackEventFromToken +nip98.validateEvent
This commit is contained in:
Alex Gleason
2023-08-08 08:48:29 -05:00
committed by GitHub
3 changed files with 62 additions and 15 deletions

View File

@@ -1,7 +1,5 @@
import {base64} from '@scure/base' import {getToken, unpackEventFromToken, validateEvent, validateToken} from './nip98.ts'
import {getToken, validateToken} from './nip98.ts'
import {Event, Kind, finishEvent} from './event.ts' import {Event, Kind, finishEvent} from './event.ts'
import {utf8Decoder} from './utils.ts'
import {generatePrivateKey, getPublicKey} from './keys.ts' import {generatePrivateKey, getPublicKey} from './keys.ts'
const sk = generatePrivateKey() const sk = generatePrivateKey()
@@ -12,9 +10,7 @@ describe('getToken', () => {
finishEvent(e, sk) finishEvent(e, sk)
) )
const decodedResult: Event = JSON.parse( const decodedResult: Event = await unpackEventFromToken(result)
utf8Decoder.decode(base64.decode(result))
)
expect(decodedResult.created_at).toBeGreaterThan(0) expect(decodedResult.created_at).toBeGreaterThan(0)
expect(decodedResult.content).toBe('') expect(decodedResult.content).toBe('')
@@ -31,9 +27,7 @@ describe('getToken', () => {
finishEvent(e, sk) finishEvent(e, sk)
) )
const decodedResult: Event = JSON.parse( const decodedResult: Event = await unpackEventFromToken(result)
utf8Decoder.decode(base64.decode(result))
)
expect(decodedResult.created_at).toBeGreaterThan(0) expect(decodedResult.created_at).toBeGreaterThan(0)
expect(decodedResult.content).toBe('') expect(decodedResult.content).toBe('')
@@ -57,9 +51,7 @@ describe('getToken', () => {
expect(result.startsWith(authorizationScheme)).toBe(true) expect(result.startsWith(authorizationScheme)).toBe(true)
const decodedResult: Event = JSON.parse( const decodedResult: Event = await unpackEventFromToken(result)
utf8Decoder.decode(base64.decode(result.replace(authorizationScheme, '')))
)
expect(decodedResult.created_at).toBeGreaterThan(0) expect(decodedResult.created_at).toBeGreaterThan(0)
expect(decodedResult.content).toBe('') expect(decodedResult.content).toBe('')
@@ -136,4 +128,43 @@ describe('validateToken', () => {
const result = validateToken(validToken, 'http://test.com', 'post') const result = validateToken(validToken, 'http://test.com', 'post')
await expect(result).rejects.toThrow(Error) await expect(result).rejects.toThrow(Error)
}) })
test('validateEvent returns true for valid decoded token with authorization scheme', async () => {
const validToken = await getToken(
'http://test.com',
'get',
e => finishEvent(e, sk),
true
)
const decodedResult: Event = await unpackEventFromToken(validToken)
const result = await validateEvent(decodedResult, 'http://test.com', 'get')
expect(result).toBe(true)
})
test('validateEvent throws an error for a wrong url', async () => {
const validToken = await getToken(
'http://test.com',
'get',
e => finishEvent(e, sk),
true
)
const decodedResult: Event = await unpackEventFromToken(validToken)
const result = validateEvent(decodedResult, 'http://wrong-test.com', 'get')
await expect(result).rejects.toThrow(Error)
})
test('validateEvent throws an error for a wrong method', async () => {
const validToken = await getToken(
'http://test.com',
'get',
e => finishEvent(e, sk),
true
)
const decodedResult: Event = await unpackEventFromToken(validToken)
const result = validateEvent(decodedResult, 'http://test.com', 'post')
await expect(result).rejects.toThrow(Error)
})
}) })

View File

@@ -20,7 +20,7 @@ const _authorizationScheme = 'Nostr '
* *
* @example * @example
* const sign = window.nostr.signEvent * const sign = window.nostr.signEvent
* await getToken('https://example.com/login', 'post', sign, true) * await nip98.getToken('https://example.com/login', 'post', (e) => sign(e), true)
*/ */
export async function getToken( export async function getToken(
loginUrl: string, loginUrl: string,
@@ -58,13 +58,20 @@ export async function getToken(
* Validate token for NIP-98 flow. * Validate token for NIP-98 flow.
* *
* @example * @example
* await validateToken('Nostr base64token', 'https://example.com/login', 'post') * await nip98.validateToken('Nostr base64token', 'https://example.com/login', 'post')
*/ */
export async function validateToken( export async function validateToken(
token: string, token: string,
url: string, url: string,
method: string method: string
): Promise<boolean> { ): Promise<boolean> {
const event = await unpackEventFromToken(token).catch((error) => { throw(error) })
const valid = await validateEvent(event, url, method).catch((error) => { throw(error) })
return valid
}
export async function unpackEventFromToken(token: string): Promise<Event> {
if (!token) { if (!token) {
throw new Error('Missing token') throw new Error('Missing token')
} }
@@ -76,6 +83,15 @@ export async function validateToken(
} }
const event = JSON.parse(eventB64) as Event const event = JSON.parse(eventB64) as Event
return event
}
export async function validateEvent(
event: Event,
url: string,
method: string
): Promise<boolean> {
if (!event) { if (!event) {
throw new Error('Invalid nostr event') throw new Error('Invalid nostr event')
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "nostr-tools", "name": "nostr-tools",
"version": "1.14.0", "version": "1.14.1",
"description": "Tools for making a Nostr client.", "description": "Tools for making a Nostr client.",
"repository": { "repository": {
"type": "git", "type": "git",