-
Notifications
You must be signed in to change notification settings - Fork 418
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Auth service worker doesn't store firebaseConfig options between restarts #295
Comments
I used the Development Tool to "Update on reload" which fixed the refresh issue, but that isn't a setting I can have my users change. |
Any luck with solving this? |
Hey @ESRuth, would you able to resolve this issue? Thanks |
I've just included the firebase config in the service worker itself, rather than having the app pass it the config when it's installed. None of the values should change so I don't see why it should be a problem. |
I am experiencing problems with the service worker, which fails upon page reload, sometimes after a few hours, or when the page is opened in a new browser tab. |
Having the same problem. Didn't clone the friendlyeats project, I copy pasted the auth code into my Next.js proiect and I have the same issue with the service worker. Still searching for a permanent solution. |
Having the same issue here as well. Hardcoding the values stops it from crashing however, obviously this is not ideal. |
I used Cache API, and it solved the issue of retaining the firebase config between runs. import { initializeApp } from "firebase/app";
import { getAuth, getIdToken } from "firebase/auth";
import { getInstallations, getToken } from "firebase/installations";
// region variables
const CACHE_NAME = 'config-cache-v1';
/** @type {FirebaseOptions | undefined} */
let CONFIG;
// endregion
// region listeners
self.addEventListener('install', (event) => {
// extract firebase config from query string
const serializedFirebaseConfig = new URL(location).searchParams.get('firebaseConfig');
if (!serializedFirebaseConfig) {
throw new Error('Firebase Config object not found in service worker query string.');
}
self.skipWaiting();
event.waitUntil(saveConfig(serializedFirebaseConfig));
});
self.addEventListener("activate", (event) => {
event.waitUntil(clients.claim());
});
self.addEventListener("fetch", (event) => {
const { origin } = new URL(event.request.url);
if (origin !== self.location.origin) return;
event.respondWith(fetchWithFirebaseHeaders(event.request));
});
// endregion
// region functions
/**
* @return string
* */
function getConfigUrl() {
return `${self.location.origin}/firebase-config`;
}
/**
* @param {string} config
*
* return Promise<void>
* */
async function saveConfig(config) {
const cache = await caches.open(CACHE_NAME);
const response = new Response(config, {
headers: { 'Content-Type': 'application/json' }
});
await cache.put(getConfigUrl(), response);
}
/**
* @param {Request} request
*
* @return Response
* */
async function fetchWithFirebaseHeaders(request) {
const config = await getConfig();
if (!config) {
return await fetch(request);
}
const app = initializeApp(config);
const auth = getAuth(app);
const installations = getInstallations(app);
const headers = new Headers(request.headers);
const [authIdToken, installationToken] = await Promise.all([
getAuthIdToken(auth),
getToken(installations),
]);
headers.append("Firebase-Instance-ID-Token", installationToken);
if (authIdToken) headers.append("Authorization", `Bearer ${authIdToken}`);
const newRequest = new Request(request, { headers });
return await fetch(newRequest);
}
/**
* @param {Auth} auth
*
* @return Promise<string | undefined>
* */
async function getAuthIdToken(auth) {
await auth.authStateReady();
if (!auth.currentUser) return;
return await getIdToken(auth.currentUser);
}
/**
* @return FirebaseOptions | undefined
* */
async function getConfig() {
if (CONFIG) return CONFIG;
const cache = await caches.open(CACHE_NAME);
const configResponse = await cache.match(getConfigUrl());
if (!configResponse) {
return;
}
const config = await configResponse.json();
CONFIG = config;
return CONFIG;
}
// endregion |
Hi @KirillSkomarovskiy - thanks for this. I'm still getting the error:
@rlw87 can you add a code snippet of your approach? Thanks all! |
Same problem from my side, just by coping codelab-friendlyeats-web and deploying it. |
Same here, it is crazy how hard it is to find a working example. |
Same problem here! |
Not inspiring much confidence in using firebase app hosting for nextjs... |
Then run
to compile the new service worker file and put it in public so that it works locally. For prod, you don't need to worry about this step, it will auto run this as part of the build process. |
The problem is that the configuration is initialized during the self.addEventListener("fetch", (event) => {
if (!firebaseConfig) {
const serializedFirebaseConfig = new URL(location).searchParams.get(
"firebaseConfig"
);
firebaseConfig = JSON.parse(serializedFirebaseConfig);
}
// rest of code
}); But I think you could get rid of the const serializedFirebaseConfig = new URL(location).searchParams.get(
"firebaseConfig"
);
if (!serializedFirebaseConfig) {
throw new Error(
"Firebase Config object not found in service worker query string."
);
}
const firebaseConfig = JSON.parse(serializedFirebaseConfig);
self.addEventListener("fetch", (event) => {
const { origin } = new URL(event.request.url);
if (origin !== self.location.origin) return;
event.respondWith(fetchWithFirebaseHeaders(event.request));
});
//... |
Did this work for you @adrolc I am having the same issues right now as well. |
This worked for me 👍🏽 |
+1 |
Description
If the auth service worker is restarted, it loses the firebaseConfig options that it was given at registration time and throws an exception.
Reproduction Steps
Expected
The service worker starts up again and the website loads as normal
Actual
You see the following error in the console and the page doesn't load
I'm new to working with service workers so I might be missing something, but it looks to me as though the service worker should be storing the firebaseConfig somewhere other than in memory, so it can be reloaded on restart of the service worker. It looks like due to the firebaseConfig variable only being populated on 'install' event, it will never get the required configuration again unless you either manually unregister it and let it re-install, or it is updated to a newer version.
https://github.com/firebase/friendlyeats-web/blob/41b0a4dbfca6c106d926fd5e65db53577f99ea75/nextjs-end/auth-service-worker.js#L6C5-L6C19
The text was updated successfully, but these errors were encountered: