From 166b9d011286e3b3f37be15bde80c11a61eb2968 Mon Sep 17 00:00:00 2001 From: DellaBitta Date: Tue, 10 Sep 2024 20:40:36 -0400 Subject: [PATCH] Remove `referrerPolicy` from Cloudflare Worker `fetch` requests (#8393) The Cloudflare Worker runner runtime doesn't support the `fetch` parameter `referrerPolicy` and throws if one is defined. In attempt to better support Cloudlfare, we will remove this parameter from `fetch` requests when we detect the SDK running in a Cloudflare runner enviornment. --- .changeset/khaki-numbers-nail.md | 6 ++++ common/api-review/util.api.md | 5 +++ packages/auth/src/api/index.test.ts | 47 +++++++++++++++++++++++++++++ packages/auth/src/api/index.ts | 23 +++++++++----- packages/util/src/environment.ts | 14 +++++++-- 5 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 .changeset/khaki-numbers-nail.md diff --git a/.changeset/khaki-numbers-nail.md b/.changeset/khaki-numbers-nail.md new file mode 100644 index 00000000000..6580c989a1e --- /dev/null +++ b/.changeset/khaki-numbers-nail.md @@ -0,0 +1,6 @@ +--- +'@firebase/auth': patch +'@firebase/util': minor +--- + +Suppress the use of the `fetch` parameter `referrerPolicy` within Auth for `fetch` requests originating from Cloudflare Workers. Clouldflare Worker environments do not support this parameter and throw when it's used. diff --git a/common/api-review/util.api.md b/common/api-review/util.api.md index 09558e72ce8..91d2f04cb40 100644 --- a/common/api-review/util.api.md +++ b/common/api-review/util.api.md @@ -264,6 +264,11 @@ export function isBrowser(): boolean; // @public (undocumented) export function isBrowserExtension(): boolean; +// Warning: (ae-missing-release-tag) "isCloudflareWorker" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function isCloudflareWorker(): boolean; + // Warning: (ae-missing-release-tag) "isElectron" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public diff --git a/packages/auth/src/api/index.test.ts b/packages/auth/src/api/index.test.ts index d95be550867..11070509d73 100644 --- a/packages/auth/src/api/index.test.ts +++ b/packages/auth/src/api/index.test.ts @@ -22,6 +22,7 @@ import { useFakeTimers } from 'sinon'; import sinonChai from 'sinon-chai'; import { FirebaseError, getUA } from '@firebase/util'; +import * as utils from '@firebase/util'; import { mockEndpoint } from '../../test/helpers/api/helper'; import { testAuth, TestAuth } from '../../test/helpers/mock_auth'; @@ -308,6 +309,52 @@ describe('api/_performApiRequest', () => { }); }); + context('referer policy exists on fetch request', () => { + afterEach(mockFetch.tearDown); + + it('should have referrerPolicy set', async () => { + let referrerPolicySet: boolean = false; + mockFetch.setUpWithOverride( + (input: RequestInfo | URL, request?: RequestInit) => { + if (request !== undefined && request.referrerPolicy !== undefined) { + referrerPolicySet = true; + } + return Promise.resolve(new Response(JSON.stringify(serverResponse))); + } + ); + const promise = _performApiRequest( + auth, + HttpMethod.POST, + Endpoint.SIGN_UP, + request + ); + await expect(promise).to.be.fulfilled; + expect(referrerPolicySet).to.be.true; + }); + + it('should not have referrerPolicy set on Cloudflare workers', async () => { + sinon.stub(utils, 'isCloudflareWorker').returns(true); + let referrerPolicySet: boolean = false; + mockFetch.setUpWithOverride( + (input: RequestInfo | URL, request?: RequestInit) => { + if (request !== undefined && request.referrerPolicy !== undefined) { + referrerPolicySet = true; + } + return Promise.resolve(new Response(JSON.stringify(serverResponse))); + } + ); + const promise = _performApiRequest( + auth, + HttpMethod.POST, + Endpoint.SIGN_UP, + request + ); + await expect(promise).to.be.fulfilled; + expect(referrerPolicySet).to.be.false; + sinon.restore(); + }); + }); + context('with network issues', () => { afterEach(mockFetch.tearDown); diff --git a/packages/auth/src/api/index.ts b/packages/auth/src/api/index.ts index 81ecf5a356a..12d89b2bd7d 100644 --- a/packages/auth/src/api/index.ts +++ b/packages/auth/src/api/index.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { FirebaseError, querystring } from '@firebase/util'; +import { FirebaseError, isCloudflareWorker, querystring } from '@firebase/util'; import { AuthErrorCode, NamedErrorParams } from '../core/errors'; import { @@ -148,14 +148,23 @@ export async function _performApiRequest( headers[HttpHeader.X_FIREBASE_LOCALE] = auth.languageCode; } + const fetchArgs: RequestInit = { + method, + headers, + ...body + }; + + /* Security-conscious server-side frameworks tend to have built in mitigations for referrer + problems". See the Cloudflare GitHub issue #487: Error: The 'referrerPolicy' field on + 'RequestInitializerDict' is not implemented." + https://github.com/cloudflare/next-on-pages/issues/487 */ + if (!isCloudflareWorker()) { + fetchArgs.referrerPolicy = 'no-referrer'; + } + return FetchProvider.fetch()( _getFinalTarget(auth, auth.config.apiHost, path, query), - { - method, - headers, - referrerPolicy: 'no-referrer', - ...body - } + fetchArgs ); }); } diff --git a/packages/util/src/environment.ts b/packages/util/src/environment.ts index 998000308c3..a0467b08c59 100644 --- a/packages/util/src/environment.ts +++ b/packages/util/src/environment.ts @@ -79,7 +79,7 @@ export function isNode(): boolean { } /** - * Detect Browser Environment + * Detect Browser Environment. * Note: This will return true for certain test frameworks that are incompletely * mimicking a browser, and should not lead to assuming all browser APIs are * available. @@ -89,7 +89,7 @@ export function isBrowser(): boolean { } /** - * Detect Web Worker context + * Detect Web Worker context. */ export function isWebWorker(): boolean { return ( @@ -99,6 +99,16 @@ export function isWebWorker(): boolean { ); } +/** + * Detect Cloudflare Worker context. + */ +export function isCloudflareWorker(): boolean { + return ( + typeof navigator !== 'undefined' && + navigator.userAgent === 'Cloudflare-Workers' + ); +} + /** * Detect browser extensions (Chrome and Firefox at least). */