diff --git a/package-lock.json b/package-lock.json index 959b15a..dc0a0ca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@fullfabric/public-api", - "version": "1.6.0", + "version": "1.7.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@fullfabric/public-api", - "version": "1.6.0", + "version": "1.7.0", "license": "MIT", "dependencies": { "assert": "^2.0.0", diff --git a/package.json b/package.json index 0e31dee..2bb97e0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@fullfabric/public-api", - "version": "1.6.0", + "version": "1.7.0", "description": "Function wrappers for the FullFabric public API.", "type": "module", "browser": "dist/index.js", diff --git a/spec/utils/getPageDigest.spec.js b/spec/utils/getPageDigest.spec.js deleted file mode 100644 index 29e170d..0000000 --- a/spec/utils/getPageDigest.spec.js +++ /dev/null @@ -1,64 +0,0 @@ -import getPageDigest from '../../src/utils/getPageDigest' - -describe('utils.getPageDigest(opts)', () => { - let oldUserAgent - - beforeAll(() => { - oldUserAgent = navigator.userAgent - - Object.defineProperty(navigator, 'userAgent', { - configurable: true, - value: - 'Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/20.0.3' - }) - }) - - afterAll(() => { - Object.defineProperty(navigator, 'userAgent', { - configurable: true, - value: oldUserAgent - }) - }) - - describe('when no request-id meta element is available', () => { - it('returns null', async () => { - expect(await getPageDigest()).toBeNull() - }) - - it('can use a given requestId', async () => { - expect(await getPageDigest({ requestId: '12345' })).toEqual( - '7f1c12a5c58c6f29bcaeaf5c6382fef305660da38f2d0919deac9fc4a58705d4' - ) - }) - }) - - describe('when a request-id meta element is available', () => { - beforeEach(() => { - document.head.innerHTML = ` - - ` - }) - - it("uses the request-id meta element's content", async () => { - expect(await getPageDigest()).toEqual( - '7f1c12a5c58c6f29bcaeaf5c6382fef305660da38f2d0919deac9fc4a58705d4' - ) - }) - - it('can use a given requestId instead', async () => { - expect(await getPageDigest({ requestId: '54321' })).toEqual( - '0b3adfbef9370498eb8a03f99fba9e86a41b89d1beef6499646d20090db0739b' - ) - }) - - it("can suffix the digest with another digest of a source's type and ID", async () => { - expect( - await getPageDigest({ sourceType: 'form', sourceId: '12345' }) - ).toEqual( - '7f1c12a5c58c6f29bcaeaf5c6382fef305660da38f2d0919deac9fc4a58705d4' + - ':' + - '0daba4f5e1a46e9e2be8bd4aac8651a020267a7da81690be4f093abe635b6aa1' - ) - }) - }) -}) diff --git a/src/api/submitEventResponse.js b/src/api/submitEventResponse.js index 95ef9a5..b737ba1 100644 --- a/src/api/submitEventResponse.js +++ b/src/api/submitEventResponse.js @@ -2,7 +2,6 @@ import assert from 'assert' import { pick } from 'lodash-es' import checkResponse from '../utils/checkResponse' -import getPageDigest from '../utils/getPageDigest' import url from '../utils/url' /** @@ -10,7 +9,6 @@ import url from '../utils/url' * * @param {String} eventId An Event ID * @param {FormData} eventData The data to submit to the event. - * @param {String} [opts.requestId] Customize the requestId used for anti-spam. * @param {String} [opts.baseUrl] The base URL for the API. Set if different * from the current location. * @param {String} [opts.externalDomainToken] A token to include in the request @@ -30,12 +28,6 @@ export default async function submitEventResponse( 'eventData must be provided and be a FormData instance' ) - const digest = await getPageDigest({ - requestId: opts.requestId, - sourceType: 'event', - sourceId: eventId - }) - const urlOpts = { ...pick(opts, ['baseUrl']), query: { external_domain_token: opts.externalDomainToken } @@ -46,7 +38,6 @@ export default async function submitEventResponse( { credentials: 'same-origin', method: 'POST', - headers: { 'X-FF-DIGEST': digest }, body: eventData } ) diff --git a/src/api/submitForm.js b/src/api/submitForm.js index af78636..37aef2a 100644 --- a/src/api/submitForm.js +++ b/src/api/submitForm.js @@ -2,7 +2,6 @@ import assert from 'assert' import { pick } from 'lodash-es' import checkResponse from '../utils/checkResponse' -import getPageDigest from '../utils/getPageDigest' import url from '../utils/url' /** @@ -10,7 +9,6 @@ import url from '../utils/url' * * @param {String} formId A Form ID * @param {FormData} formData The data to submit to the form. - * @param {String} [opts.requestId] Customize the requestId used for anti-spam. * @param {String} [opts.baseUrl] The base URL for the API. Set if different * from the current location. * @param {String} [opts.externalDomainToken] A token to include in the request @@ -26,12 +24,6 @@ export default async function submitForm(formId, formData, opts = {}) { 'formData must be provided and be a FormData instance' ) - const digest = await getPageDigest({ - requestId: opts.requestId, - sourceType: 'form', - sourceId: formId - }) - const urlOpts = { ...pick(opts, ['baseUrl']), query: { external_domain_token: opts.externalDomainToken } @@ -42,7 +34,6 @@ export default async function submitForm(formId, formData, opts = {}) { { credentials: 'same-origin', method: 'POST', - headers: { 'X-FF-DIGEST': digest }, body: formData } ) diff --git a/src/utils/getPageDigest.js b/src/utils/getPageDigest.js deleted file mode 100644 index e8c8a2b..0000000 --- a/src/utils/getPageDigest.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Generates a digest for anti-spam purposes. - * - * This algorithm should match the backend's exactly, otherwise the requests - * will be unauthorized. - * - * By default, each digest is unique to a page load. When there are multiple - * submissions possible in the same page, e.g. via multiple forms, a source can - * be passed to generate a digest unique to it. - * - * @param {String} [requestId] ID of the request, pass if originating from an API request. - * @param {String} [sourceType] Type of source for the digest, should match backend. - * @param {String} [sourceId] ID of source for the digest, should match backend. - * @returns {String} The generated digest. - */ -export default async function getPageDigest({ - requestId, - sourceType, - sourceId -} = {}) { - requestId ||= document.querySelector("meta[name='request-id']")?.content || '' - - // If there's no requestId, no point generating a digest, won't ever match - // the backend. Same if we can't access the crypto API. - if (!requestId || !crypto?.subtle?.digest) return null - - let digest = await makeDigest(`${navigator.userAgent}:${requestId}`) - - if (sourceType && sourceId) { - const suffix = `${sourceType}:${sourceId}` - digest += `:${await makeDigest(suffix)}` - } - - return digest -} - -async function makeDigest(str) { - const message = new TextEncoder().encode(str) - const digestRaw = await crypto.subtle.digest('SHA-256', message) - - return Array.from(new Uint8Array(digestRaw)) - .map((b) => b.toString(16).padStart(2, '0')) - .join('') -} diff --git a/src/utils/index.js b/src/utils/index.js index 087a944..e0c3f89 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -1,4 +1,3 @@ -export { default as getPageDigest } from './getPageDigest' export { default as checkResponse } from './checkResponse' export { default as extractHeaders } from './extractHeaders' export { default as url } from './url'