firebase / firebase/firebase-js-sdk

fetch wrapper adds custom headers causing CORS preflight failure on securetoken.googleapis.com

Open
#10,086 1 comment 0 reactions 0 assignees View on GitHub
api: auth needs-attention type: feature request
Dominant language
TypeScript
Stars
5.1k
Forks
1k
Avg merge
2d 21h
Merged PRs (30d)
37

Description

### Operating System

MAC OS Apple M5

### Environment (if applicable)

Chrome Version 149.0.7827.103 (Official Build) (arm64)

### Firebase SDK Version

11.10.0

### Firebase SDK Product(s)

Firestore

### Project Tooling

- @angular/fire: 20.0.1
- firebase: 11.10
- Pendo: loaded via async in index.html
- Angular: 20

### Detailed Problem Description

Firebase JS SDK v11 switched token refresh from XHR to fetch(). If a third-party analytics tool (in our case, Pendo) wraps window.fetch and adds custom tracking headers, every Firebase token refresh request becomes a "non-simple"
request, triggering a CORS preflight (OPTIONS) to securetoken.googleapis.com. Google's token endpoint does not include Pendo's custom headers in Access-Control-Allow-Headers, so the preflight fails with:

Access to fetch at 'https://securetoken.googleapis.com/v1/token' blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Firebase: Error (auth/network-request-failed)

### Steps and code to reproduce issue

**Root cause**

Pendo patches window.fetch globally when pendo.js loads, adding proprietary tracking headers to all outgoing requests. These headers trigger a CORS preflight that securetoken.googleapis.com rejects.

This was not an issue with Firebase SDK v10, which used XHR for token refresh. The bug was introduced when upgrading @angular/fire 18 → 20 (Firebase SDK 10 → 11).

**Workaround**

We added an Object.defineProperty setter trap in index.html before Pendo loads, intercepting Pendo's fetch patch and routing securetoken.googleapis.com requests through the original native fetch:

> (function () {
> var _nativeFetch = window.fetch.bind(window);
> var _currentFetch = _nativeFetch;
> Object.defineProperty(window, 'fetch', {
> get: function () { return _currentFetch; },
> set: function (patchedFetch) {
> _currentFetch = function (input, init) {
> var url = typeof input === 'string' ? input
> : input instanceof Request ? input.url : String(input);
> if (url.includes('securetoken.googleapis.com')) {
> return _nativeFetch(input, init);
> }
> return patchedFetch.call(window, input, init);
> };
> },
> configurable: true,
> });
> })();

**Requested fix**

Firebase: expose a way to provide a custom fetch implementation to the auth SDK (e.g. via initializeAuth options), so apps can bypass third-party fetch wrappers for auth requests without a global hack.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.