diff --git a/__tests__/plugins/signed-integrity.test.js b/__tests__/plugins/signed-integrity.test.js index cc8b882..b7cab3a 100644 --- a/__tests__/plugins/signed-integrity.test.js +++ b/__tests__/plugins/signed-integrity.test.js @@ -64,17 +64,39 @@ describe("plugin: signed-integrity", () => { // prepare it for inclusion in the JWT signature = btoa(signature).replace(/\//g, '_').replace(/\+/g, '-').replace(/=/g, '') + // need to test with bad algo! + var noneHeader = btoa('{"alg": "none"}').replace(/\//g, '_').replace(/\+/g, '-').replace(/=/g, '') + + // get an invalid signature + // an ECDSA signature for {alg: none} header makes zero sense + var noneSignature = await subtle.sign( + { + name: "ECDSA", + hash: {name: "SHA-384"} + }, + (await generateECDSAKeypair()).privateKey, + (noneHeader + '.' + payload) + ) + // prepare it for inclusion in the JWT + noneSignature = btoa(noneSignature).replace(/\//g, '_').replace(/\+/g, '-').replace(/=/g, '') + global.resolvingFetch = jest.fn((url, init)=>{ var content = '{"test": "success"}' var status = 200 var statusText = "OK" + if (url == 'https://resilient.is/test.json.integrity') { content = header + '.' + payload + '.' + signature - } else if (url == 'https://resilient.is/fail.json.integrity') { + // testing 404 not found on the integrity URL + } else if (url == 'https://resilient.is/not-found.json.integrity') { content = '{"test": "fail"}' status = 404 statusText = "Not Found" + // testing bad signature on the integrity JWT + } else if (url == 'https://resilient.is/bad-signature.json.integrity') { + content = header + '.' + payload + '.' + noneSignature } + return Promise.resolve( new Response( [content], @@ -179,12 +201,12 @@ describe("plugin: signed-integrity", () => { test("it should fetch content when integrity data not provided, and integrity data URL 404s", async () => { require("../../plugins/signed-integrity.js"); - const response = await LibResilientPluginConstructors.get('signed-integrity')(LR, init).fetch('https://resilient.is/fail.json', {}); + const response = await LibResilientPluginConstructors.get('signed-integrity')(LR, init).fetch('https://resilient.is/not-found.json', {}); expect(resolvingFetch).toHaveBeenCalledTimes(2); - expect(resolvingFetch).toHaveBeenNthCalledWith(1, 'https://resilient.is/fail.json.integrity') + expect(resolvingFetch).toHaveBeenNthCalledWith(1, 'https://resilient.is/not-found.json.integrity') expect(await response.json()).toEqual({test: "success"}) - expect(response.url).toEqual('https://resilient.is/fail.json') + expect(response.url).toEqual('https://resilient.is/not-found.json') }); test("it should refuse to fetch content when integrity data not provided and integrity data URL 404s, but requireIntegrity is set to true", async () => { @@ -195,13 +217,27 @@ describe("plugin: signed-integrity", () => { expect.assertions(4); try { - const response = await LibResilientPluginConstructors.get('signed-integrity')(LR, newInit).fetch('https://resilient.is/fail.json', {}); + const response = await LibResilientPluginConstructors.get('signed-integrity')(LR, newInit).fetch('https://resilient.is/not-found.json', {}); } catch (e) { expect(resolvingFetch).toHaveBeenCalledTimes(1); - expect(resolvingFetch).toHaveBeenCalledWith('https://resilient.is/fail.json.integrity') + expect(resolvingFetch).toHaveBeenCalledWith('https://resilient.is/not-found.json.integrity') expect(e).toBeInstanceOf(Error) expect(e.toString()).toMatch('No integrity data available, though required.') } }); + test("it should refuse to fetch content when integrity data not provided and integrity data URL is fetched, but JWT signature check fails", async () => { + require("../../plugins/signed-integrity.js"); + + expect.assertions(4); + try { + const response = await LibResilientPluginConstructors.get('signed-integrity')(LR, init).fetch('https://resilient.is/bad-signature.json', {}); + } catch (e) { + expect(resolvingFetch).toHaveBeenCalledTimes(1); + expect(resolvingFetch).toHaveBeenCalledWith('https://resilient.is/bad-signature.json.integrity') + expect(e).toBeInstanceOf(Error) + expect(e.toString()).toMatch('JWT signature validation failed') + } + }); + });