nuxt SSR routes with auth enabled, not working in app hosting
Reproduction
https://github.com/OliverJEvans/firebase-test
Steps to reproduce the bug
- Clone barebones test repo
- Install deps
- Link to a Firebase project with at least app hosting setup (Blaze plan required)
- Build & Deploy
- Observe 500 error
/ssr route throws a 500 /csr renders fine.
Visit this project as example: https://my-web-app--testproject-31cc4.europe-west4.hosted.app/ssr <!-- server side rendered https://my-web-app--testproject-31cc4.europe-west4.hosted.app/csr <!-- client side rendered
Expected behavior
SSR routes should be built and accessible when auth is enabled.
Actual behavior
500 error on all SSR routes
The default Firebase app does not exist. Make sure you call initializeApp() before using any of the Firebase services.
Disabling auth and redeploying clears this issue.
Cloud Build logs report:
[warn] [nuxt-vuefire module] You activated both SSR and auth but you are not providing a service account for the admin SDK. See https://vuefire.vuejs.org/nuxt/getting-started.html#configuring-the-admin-sdk.
Which I would assume is saying the build can't find the service account.
Additional information
This codebase was setup from scratch using the official vuefire documentation, using a fresh Firebase project.
Perhaps the documentation here is out of date, missing something, or this is a bug? I found it suspicious, however, that there is this discussion from yesterday https://github.com/vuejs/vuefire/discussions/1592. I thought it be appropriate to set up a bare bones reproduction.
I appreciate this may not be a Vuefire specific issue, but I would greatly appreciate any help or pointers in the right direction here as I've been looking at this all day.
Nuxt: 4.0.3 Vuefire: 3.2.2 nuxt-vuefire: 1.1.0 Firebase: 12.0.0
I have the same problem on Nuxt 3. Both on pure SSR routes and on SSR + prerender ones (SSG).
@posva does anyone have some time to look into this issue? It's quite impactful, since App Hosting is now the official recommended (and the only non deprecated) way to deploy Nuxt apps.
I tried to contract again with Google for VueFire but I haven't heard back from them.
does anyone have some time to look into this issue?
Anyone is welcome! You are welcome too 😄
The issue is that nuxt-vuefire registers the nuxt plugin and the /api/__session route only in two cases:
- When the
GOOGLE_APPLICATION_CREDENTIALSenvironment variable is present. It doesn’t need to be valid, but with an invalid value, you'll get an error like "Error minting the cookie Credential implementation...". - When you run the Firebase emulators.
On the host (inside the container) created via Firebase App Hosting, the GOOGLE_APPLICATION_CREDENTIALS variable isn't present. The service account is connected differently during Firebase Admin initialisation. Because of this, the nuxt-vuefire plugin doesn't initialise.
To temporarily fix this, I made a patch using patch-package, which adds another or condition to the hasServiceAccount variable in the nuxt-vuefire\dist\module.mjs file to detect that we're in a Firebase App Hosting environment. After that, everything started working.
Yes, it's not direct proof of a service account being present on the host, but at least it worked for me.
const hasServiceAccount = (typeof process.env.GOOGLE_APPLICATION_CREDENTIALS === "string" && process.env.GOOGLE_APPLICATION_CREDENTIALS.length > 0) || !!process.env.FIREBASE_CONFIG;
Brackets are not required
nuxt-vuefire+1.1.0.patch
diff --git a/node_modules/nuxt-vuefire/dist/module.mjs b/node_modules/nuxt-vuefire/dist/module.mjs
index 4b1e8ce..00057bc 100644
--- a/node_modules/nuxt-vuefire/dist/module.mjs
+++ b/node_modules/nuxt-vuefire/dist/module.mjs
@@ -123,7 +123,7 @@ const module = defineNuxtModule({
addPlugin(resolve(runtimeDir, "payload-plugin"));
nuxt.options.build.transpile.push(runtimeDir);
nuxt.options.build.transpile.push(templatesDir);
- const hasServiceAccount = typeof process.env.GOOGLE_APPLICATION_CREDENTIALS === "string" && process.env.GOOGLE_APPLICATION_CREDENTIALS.length > 0;
+ const hasServiceAccount = (typeof process.env.GOOGLE_APPLICATION_CREDENTIALS === "string" && process.env.GOOGLE_APPLICATION_CREDENTIALS.length > 0) || !!process.env.FIREBASE_CONFIG;
if (typeof process.env.GOOGLE_APPLICATION_CREDENTIALS === "string" && process.env.GOOGLE_APPLICATION_CREDENTIALS?.[0] !== "{") {
const resolvedCredentials = resolve(
nuxt.options.rootDir,
- Install the
patch-packagedev dependency. - Place the
nuxt-vuefire+1.1.0.patchfile in your project's/patchesdirectory. - Add the following script to your
package.json:
"postinstall": "patch-package"
My nuxt.config.ts:
vuefire: {
auth: {
enabled: true,
sessionCookie: true,
},
config: {
apiKey: process.env.FIREBASE_API_KEY,
authDomain: process.env.FIREBASE_AUTH_DOMAIN,
projectId: process.env.FIREBASE_PROJECT_ID,
storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
appId: process.env.FIREBASE_APP_ID
}
}
You will probably also need to grant the appropriate permissions to the service account used for Firebase App Hosting deployment. Its name is roughly:
[email protected]
You can try adding some middleware:
server\middleware\setup.ts
import { initializeApp } from 'firebase-admin/app'
// Setup Firebase
initializeApp()
export default defineEventHandler(() => {})
I'm not using App Hosting yet, but I had to do something similar when hosting on Firebase functions.
You can try adding some middleware:
It's not the same thing. The issue isn't that Firebase Admin fails to initialise. nuxt-vuefire also adds the /auth/__session endpoint, which sets a cookie in the user's browser so that on page reload, the user can be authenticated server-side.
I only ran a quick test, but the patch seems to work correctly for me as well as a temporary workaround.
Thank you very much for this @vulpeep
Hi, do i still have to include GOOGLE_APPLICATION_CREDENTIALS at apphosting.yaml file?
I'm getting this error with app hosting.... [warn] [nuxt-vuefire module] You activated both SSR and auth but you are not providing a service account for the admin SDK. See https://vuefire.vuejs.org/nuxt/getting-started.html#configuring-the-admin-sdk.
Even though I've followed all the steps! I've created the service account. in my .env I have GOOGLE_APPLICATION_CREDENTIALS=service-account.json In the service-account.json file I've copied the contents of the file downloaded.
Everything works perfectly locally. It's only until I upload to app hosting. That I get the error message. " [warn] [nuxt-vuefire module] You activated both SSR and auth but you are not providing a service account for the admin SDK. See https://vuefire.vuejs.org/nuxt/getting-started.html#configuring-the-admin-sdk."
Hi, do i still have to include GOOGLE_APPLICATION_CREDENTIALS at apphosting.yaml file?
@nathan1658 as of today you do have to include it in apphosting.yaml, to avoid the warning, it looks like you also have to have something set to enable app check, but that looks like a bug, because it should use the role's permissions if that variable is not set.
However, you shouldn't have to set that environment variable for the server. Because cloud run/build should use the role to get access via this method: https://cloud.google.com/docs/authentication/application-default-credentials#attached-sa