Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

165
Vistas
Firebase 9, Remix: addDoc() returns "PERMISSION DENIED" error

I have a remix app using firebase & a firestore database.

The sign in works fine, the GET /documents as well (no rules for GET)

When I try to create a new document with addDoc() I get a PERMISSION DENIED error.

My rules:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow create, update, delete: if request.auth != null && request.auth.token.email_verified && request.auth.token.email == 'my_email@gmail.com';
      allow read: if true;
    }
  }
}

Since I use Remix (SSR) I am initializing firebase in the client-side:

if (getApps().length === 0) {
  initializeApp({
    apiKey: "...",
    authDomain: "...",
    projectId: "...",
    storageBucket: "...",
    messagingSenderId: "...",
    appId: "...",
    measurementId: "...",
  });
}

And I have firebase-admin in the server-side:

const serviceAccount = require("~/firebase-service-account.json");
serviceAccount.private_key_id = process.env.FIREBASE_PRIVATE_KEY_ID;
serviceAccount.private_key = process.env.FIREBASE_PRIVATE_KEY;

if (getApps().length === 0) {
  admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
  });
}

I use Google authentication in the client-side like this:

const submit = useSubmit();

const signInWithGoogle = async () => {
  const provider = new GoogleAuthProvider();
  const { user } = await signInWithPopup(auth, provider);

  if (user) {
    const formData = new FormData();
    formData.set("user", JSON.stringify(user));
    submit(formData, { method: "post" });
  }
};

Then the formData is handled by my server-side code and create a sessionCookie with auth().createSessionCookie().

Everything works fine in my dashboard (only accessible by logged-in users, I am using auth().verifySessionCookie() to check that) until I create a new document with the addDoc function from firebase 9. auth comes from firebase-admin package.

Here is the code I use:

const addDocument = async <T>(name: string, data: T): Promise<T> => {
  console.log(getAuth().currentUser) // null
  await addDoc(collection(db, name), data as Record<string, any>);

  cache().deleteEntry(name);

  return data;
};

When my write rule is set to true it works fine but when I put request.auth != null I have the permission error so I guess the problem is in the authentication part.

about 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

While you may be using the Admin SDK on the server, that last code snippet is definitely a regular JavaScript SDK (as the Admin SDK doesn't have the concept of a currentUser). When you sign in the user on the client, that state does not automatically get transported to your server-side code.

The most common approach for accessing Firebase from the server until recently was to use the Admin SDK (which bypasses security rules) and perform any authorization checks in your application code.

You can use the regular JavaScript SDKs on the server, but you will have to ensure their sign-in state yourself. There is some work in progress to do this automatically for Next.js and Angular Universal, but not yet for Remix.run. How these work (and what you'd have to do) is that they:

  1. Pass the sign-in information in session cookies
  2. Verify the ID token in the server-side code with Admin SDK.
  3. If the verification succeeds, they mint a custom token for the user.
  4. And then sign in with that custom token in the regular JavaScript SDK.

You'll need to ensure that you have a separate FirebaseApp/Auth instance for each user, and will probably want to set up a LRU cache for those to prevent having to perform that translation on each call.

about 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda