Skip to content

Commit

Permalink
feat: add verify metadata content option
Browse files Browse the repository at this point in the history
  • Loading branch information
Melisa Anabella Rossi committed Jun 17, 2024
1 parent 2a4fb7f commit be9ede1
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 2 deletions.
8 changes: 6 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,18 @@ export type DecentralandSignatureRequiredContext<P extends {} = {}> = {
verification: DecentralandSignatureData<P>
}

export type VerifyAuthChainHeadersOptions = {
export type VerifyAuthChainHeadersOptions<
P extends Record<string, any> = Record<string, any>
> = {
catalyst?: string
expiration?: number
verifyMetadataContent?: (authMetadata: P) => boolean
}

export type SessionOptions = {
optional?: boolean
onError?: (err: RequestError) => any
}

export type Options = VerifyAuthChainHeadersOptions & SessionOptions
export type Options<P extends Record<string, any> = Record<string, any>> =
VerifyAuthChainHeadersOptions<P> & SessionOptions
71 changes: 71 additions & 0 deletions src/verify.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import {
AUTH_TIMESTAMP_HEADER,
DEFAULT_EXPIRATION,
} from './types'

import verifyAuthChainHeaders, {
isEIP1664AuthChain,
verifyEIP1654Sign,
verifyPersonalSign,
} from './verify'
import RequestError from './errors'

const identity: AuthIdentity = {
ephemeralIdentity: {
Expand Down Expand Up @@ -262,5 +264,74 @@ describe(`src/verifyAuthChainHeaders`, () => {
verifyAuthChainHeaders(method, path, headers)
).rejects.toThrowError('Invalid signature:')
})

describe('when verifyMetadataContent function is defined', () => {
describe('and the verification returns true', () => {
test('should return all the information about a header signature', async () => {
const timestamp = Date.now()
const metadata = { signer: 'a signer' }
const method = 'get'
const path = '/path/to/resource'
const payload = [method, path, timestamp, JSON.stringify(metadata)]
.join(':')
.toLowerCase()
const chain = Authenticator.signPayload(identity, payload)
const headers = createAuthChainHeaders(chain, timestamp, metadata)
const options = { verifyMetadataContent: () => true }

expect(
await verifyAuthChainHeaders(method, path, headers, options)
).toEqual({
auth: identity.authChain[0].payload.toLowerCase(),
authMetadata: metadata,
})
})
})

describe('and the verification returns false', () => {
test('should throw an error indicating the metadata is invalid', async () => {
const timestamp = Date.now()
const metadata = { signer: 'a signer' }
const method = 'get'
const path = '/path/to/resource'
const payload = [method, path, timestamp, JSON.stringify(metadata)]
.join(':')
.toLowerCase()
const chain = Authenticator.signPayload(identity, payload)
const headers = createAuthChainHeaders(chain, timestamp, metadata)
const options = { verifyMetadataContent: () => false }

await expect(() =>
verifyAuthChainHeaders(method, path, headers, options)
).rejects.toThrowError(
`Invalid metadata content: ${JSON.stringify(metadata)}`
)
})
})

describe('and the verification throws an error', () => {
test('should throw an error indicating the metadata is invalid', async () => {
const timestamp = Date.now()
const error = 'a custom error'
const metadata = { signer: 'a signer' }
const method = 'get'
const path = '/path/to/resource'
const payload = [method, path, timestamp, JSON.stringify(metadata)]
.join(':')
.toLowerCase()
const chain = Authenticator.signPayload(identity, payload)
const headers = createAuthChainHeaders(chain, timestamp, metadata)
const options = {
verifyMetadataContent: () => {
throw new RequestError(error, 400)
},
}

await expect(() =>
verifyAuthChainHeaders(method, path, headers, options)
).rejects.toThrowError(error)
})
})
})
})
})
10 changes: 10 additions & 0 deletions src/verify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,16 @@ export default async function verify<P extends {} = {}>(
const ownerAddress = await verifySign(authChain, payload, options)
await verifyExpiration(timestamp, options)

if (
options.verifyMetadataContent &&
!options.verifyMetadataContent(metadata)
) {
throw new RequestError(
`Invalid metadata content: ${JSON.stringify(metadata)}`,
400
)
}

return {
auth: ownerAddress,
authMetadata: metadata as P,
Expand Down

0 comments on commit be9ede1

Please sign in to comment.