Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

164
Visualizações
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 Respostas
Responde à pergunta

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda