firebase / firebase/firebase-js-sdk
fetch wrapper adds custom headers causing CORS preflight failure on securetoken.googleapis.com
- 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
Assessment
This issue has not been assessed yet.