Asked 1 month ago by ZenithPilot911
Firestore 404 Error on Refresh Due to Service Worker Import Issue in NextJS
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
Asked 1 month ago by ZenithPilot911
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
I'm using NextJS with the next-firebase-auth-edge library for handling Firebase authentication in my project. All session and cookie management is handled by the library, and immediately after signing in or signing up, my Firestore queries work as expected. However, after refreshing the page and re-executing the query, Firestore returns a 404 error with insufficient permission.
I followed the instructions for service workers from this guide, which explains how to use a fetch listener to inject the Firebase token into every request header for proper Firestore authentication.
Below is my auth-service-worker.js
file:
JAVASCRIPTimport { initializeApp } from "firebase/app"; import { getAuth, onAuthStateChanged, getIdToken } from "firebase/auth"; // Initialize the Firebase app in the service worker script. initializeApp(config); /** * Returns a promise that resolves with an ID token if available. * @return {!Promise<?string>} The promise that resolves with an ID token if * available. Otherwise, the promise resolves with null. */ const auth = getAuth(); const getIdTokenPromise = () => { return new Promise((resolve, reject) => { const unsubscribe = onAuthStateChanged(auth, (user) => { unsubscribe(); if (user) { getIdToken(user).then((idToken) => { resolve(idToken); }, (error) => { resolve(null); }); } else { resolve(null); } }); }); }; const getOriginFromUrl = (url) => { // https://stackoverflow.com/questions/1420881/how-to-extract-base-url-from-a-string-in-javascript const pathArray = url.split('/'); const protocol = pathArray[0]; const host = pathArray[2]; return protocol + '//' + host; }; // Get underlying body if available. Works for text and json bodies. const getBodyContent = (req) => { return Promise.resolve().then(() => { if (req.method !== 'GET') { if (req.headers.get('Content-Type').indexOf('json') !== -1) { return req.json() .then((json) => { return JSON.stringify(json); }); } else { return req.text(); } } }).catch((error) => { // Ignore error. }); }; self.addEventListener('fetch', (event) => { /** @type {FetchEvent} */ const evt = event; const requestProcessor = (idToken) => { let req = evt.request; let processRequestPromise = Promise.resolve(); // For same origin https requests, append idToken to header. if (self.location.origin == getOriginFromUrl(evt.request.url) && (self.location.protocol == 'https:' || self.location.hostname == 'localhost') && idToken) { // Clone headers as request headers are immutable. const headers = new Headers(); req.headers.forEach((val, key) => { headers.append(key, val); }); // Add ID token to header. headers.append('Authorization', 'Bearer ' + idToken); processRequestPromise = getBodyContent(req).then((body) => { try { req = new Request(req.url, { method: req.method, headers: headers, mode: 'same-origin', credentials: req.credentials, cache: req.cache, redirect: req.redirect, referrer: req.referrer, body, // bodyUsed: req.bodyUsed, // context: req.context }); } catch (e) { // This will fail for CORS requests. We just continue with the // fetch caching logic below and do not pass the ID token. } }); } return processRequestPromise.then(() => { return fetch(req); }); }; // Fetch the resource after checking for the ID token. // This can also be integrated with existing logic to serve cached files // in offline mode. evt.respondWith(getIdTokenPromise().then(requestProcessor, requestProcessor)); }); self.addEventListener('activate', (event) => { event.waitUntil(clients.claim()); });
When I register this service worker, I get the following error:
PLAINTEXTUncaught SyntaxError: Cannot use import statement outside a module (at auth-service-worker.js:1:1)
My Firestore security rules are as follows:
PLAINTEXTmatch /users/{userId} { allow read, create, update, write: if resourceMatchesUID(userId); } function resourceMatchesUID(userId) { return request.auth.uid == userId; }
I suspect the error is because the service worker isn’t being registered as a module, so import statements aren’t allowed. How can I resolve this to ensure that the Firebase ID token is correctly injected into Firestore requests, especially on page refresh?
Comments 0
•Answers 2
•Views 38
Answer by TychoAI Agent • 1 month ago
It looks like your service worker is being loaded as a classic script, so the browser isn’t allowing import statements. In other words, the error
Uncaught SyntaxError: Cannot use import statement outside a module
indicates that the file isn’t treated as an ES module.
To fix this, you have two options:
Register the Service Worker as an ES Module:
When you register your service worker, pass the option { type: "module" }
. For example:
JAVASCRIPTif ('serviceWorker' in navigator) { navigator.serviceWorker.register('/auth-service-worker.js', { scope: '/', type: 'module' }); }
This tells the browser to treat your service worker as an ES module so that the import
statements are valid.
Bundle or Transpile Your Service Worker Code:
If you can’t register it as a module for some reason (for example, if you need wider browser support or are using a specific build process), consider using a bundler like Webpack or Rollup. This will compile your code into a format that doesn’t use ES module syntax so that it runs as a classic service worker script.
Given that your Firestore query is failing on refresh with a 404 (insufficient permission), it’s likely because the service worker isn’t properly injecting the Firebase ID token into the request headers due to the import error causing the worker not to run. Once you resolve the import issue, the worker should intercept the fetch requests, add the Authorization header, and Firestore should be able to authenticate those requests according to your security rules.
Make sure that after correcting the service worker registration, your Firebase configuration (the config
object passed to initializeApp) is correctly set up and that your Firestore rules are configured to allow access only when the passed request.auth.uid
matches the user ID requested.
That should resolve the issue.
Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?
No comments yet.
Answer by CosmicDiscoverer844 • 1 month ago
So basically the issue was that I was using client Firestore SDK to query my Cloud Firestore. However, since the token is stored in the server, I had to use the server functions, which has access to a service account, which then can query Cloud Firestore.
Someone, please use the correct terminologies to further refine and make my answer more clearer.
Thanks in advance.
No comments yet.
No comments yet.