Skip to content

Commit

Permalink
fix: use verify from @dcl/platform-crypto-middleware (#699)
Browse files Browse the repository at this point in the history
* fix: use verify from @dcl/platform-crypto-middleware

* remove unused fetch

* retrocompatibility

* forward error from validateSignature

* use independent fetcher for signature

* improvements

* test: fix broken tests

* chore: imports order and prettier fix

* test: add tests for the authentication middleware logic

---------

Signed-off-by: Mateo Miccino <[email protected]>
Co-authored-by: Juanma Hidalgo <[email protected]>
  • Loading branch information
Mateo Miccino and juanmahidalgo authored Sep 6, 2023
1 parent 4fc551a commit 9980fbf
Show file tree
Hide file tree
Showing 6 changed files with 214 additions and 59 deletions.
61 changes: 41 additions & 20 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"@apollo/client": "^3.3.9",
"@dcl/crypto": "^3.0.1",
"@dcl/hashing": "^1.1.0",
"@dcl/platform-crypto-middleware": "^1.0.2",
"@dcl/schemas": "^8.2.2",
"@ethersproject/solidity": "^5.7.0",
"@types/escape-html": "0.0.20",
Expand Down
6 changes: 3 additions & 3 deletions src/Collection/Collection.router.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1207,7 +1207,7 @@ describe('Collection router', () => {
now = 1633022119407
lock = new Date(now)
mockAuthenticationSignatureValidationDate()
jest.spyOn(Date, 'now').mockReturnValueOnce(now)
jest.spyOn(Date, 'now').mockReturnValue(now)
mockExistsMiddleware(Collection, dbCollection.id)
mockCollectionAuthorizationMiddleware(dbCollection.id, wallet.address)
;(Collection.findByIds as jest.MockedFunction<
Expand Down Expand Up @@ -1382,7 +1382,7 @@ describe('Collection router', () => {
mockThirdPartyCollectionIsPublished(dbTPCollection.id, false)
jest
.spyOn(Date, 'now')
.mockReturnValueOnce(lockDate.getTime() + 1000 * 60 * 60 * 24)
.mockReturnValue(lockDate.getTime() + 1000 * 60 * 60 * 24)
})

afterEach(() => {
Expand Down Expand Up @@ -1484,7 +1484,7 @@ describe('Collection router', () => {
mockIsCollectionPublished(dbCollection.id, false)
jest
.spyOn(Date, 'now')
.mockReturnValueOnce(lockDate.getTime() + 1000 * 60 * 60 * 24)
.mockReturnValue(lockDate.getTime() + 1000 * 60 * 60 * 24)
})

afterEach(() => {
Expand Down
5 changes: 3 additions & 2 deletions src/ethereum/api/peer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import fetch from 'node-fetch'
import { Emote, Wearable } from '@dcl/schemas'
import { AuthLink } from '@dcl/crypto'
import { ILoggerComponent } from '@well-known-components/interfaces'
import { IFetchComponent, ILoggerComponent } from '@well-known-components/interfaces'
import { createConsoleLogComponent } from '@well-known-components/logger'
import { createFetchComponent } from '@well-known-components/fetch-component'
import { env } from 'decentraland-commons'
Expand Down Expand Up @@ -35,8 +34,10 @@ export const PEER_URL = env.get('PEER_URL', '')
export class PeerAPI {
contentClient: ContentClient
logger: ILoggerComponent.ILogger
signatureFetcher: IFetchComponent

constructor() {
this.signatureFetcher = createFetchComponent()
this.contentClient = createContentClient({
url: `${PEER_URL}/content`,
fetcher: createFetchComponent(),
Expand Down
125 changes: 125 additions & 0 deletions src/middleware/authentication.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { Request } from 'express'
import { Authenticator } from '@dcl/crypto'
import { verify } from '@dcl/platform-crypto-middleware'
import {
INVALID_AUTH_CHAIN_MESSAGE,
MISSING_ETH_ADDRESS_ERROR,
decodeAuthChain,
} from './authentication'

jest.mock('@dcl/crypto')
jest.mock('@dcl/platform-crypto-middleware')

describe('decodeAuthChain', () => {
let mockRequest: Request

beforeEach(() => {
mockRequest = {
headers: {},
method: 'GET',
path: '/',
} as Request
})

describe('when the auth chain is invalid', () => {
it('should throw an error for an invalid auth chain', async () => {
mockRequest.headers = {
'x-identity-auth-chain-0': '{"invalidPart": "data"}',
}

await expect(decodeAuthChain(mockRequest)).rejects.toThrow(
INVALID_AUTH_CHAIN_MESSAGE
)
})
})

describe('when the auth chain is valid', () => {
beforeEach(() => {
;(Authenticator.isValidAuthChain as jest.Mock).mockReturnValue(true)
})

afterEach(() => {
;(Authenticator.isValidAuthChain as jest.Mock).mockRestore()
})

describe('and it is missing an ETH address', () => {
it('should throw an error with the missing ETH address message', async () => {
await expect(decodeAuthChain(mockRequest)).rejects.toThrow(
MISSING_ETH_ADDRESS_ERROR
)
})
})

describe('and it has the ETH address defined', () => {
let validAddress = '0x12345'
beforeEach(() => {
;(Authenticator.ownerAddress as jest.Mock).mockReturnValue(validAddress)
})

afterEach(() => {
;(Authenticator.isValidAuthChain as jest.Mock).mockRestore()
})

describe('and the verify method does not throw an error', () => {
beforeEach(() => {
;(verify as jest.Mock).mockReturnValue(validAddress)
})

afterEach(() => {
;(verify as jest.Mock).mockRestore()
})

it('should return the eth address without throwing an error', async () => {
const result = await decodeAuthChain(mockRequest)
expect(result).toBe(validAddress)
await expect(decodeAuthChain(mockRequest)).resolves.not.toThrow()
})
})

describe('and the verify method throws an error', () => {
beforeEach(() => {
;(verify as jest.Mock).mockRejectedValue('Error')
})

afterEach(() => {
;(verify as jest.Mock).mockRestore()
})

describe('and the validateSignature function does not throw an error', () => {
beforeEach(() => {
;(Authenticator.validateSignature as jest.Mock).mockReturnValue({
ok: true,
})
})

afterEach(() => {
;(Authenticator.validateSignature as jest.Mock).mockRestore()
})
it('should return the eth address without throwing an error', async () => {
const result = await decodeAuthChain(mockRequest)
expect(result).toBe(validAddress)
await expect(decodeAuthChain(mockRequest)).resolves.not.toThrow()
})
})

describe('and the validateSignature method throws an error', () => {
let error: string
beforeEach(() => {
error = 'validateSignature failed'
;(Authenticator.validateSignature as jest.Mock).mockReturnValue({
ok: false,
message: error,
})
})

afterEach(() => {
;(Authenticator.validateSignature as jest.Mock).mockRestore()
})
it('should throw the error', async () => {
await expect(decodeAuthChain(mockRequest)).rejects.toThrow(error)
})
})
})
})
})
})
Loading

0 comments on commit 9980fbf

Please sign in to comment.