firebase-tools icon indicating copy to clipboard operation
firebase-tools copied to clipboard

Rules using resource.data run twice in Firestore emulator

Open acmertz opened this issue 2 years ago • 16 comments

Rules that use resource.data appear to be evaluated twice in the Firestore emulator. The first time always fails with an error, but the second one succeeds and allows/denies access as expected. This feels similar to #4325, but doesn't involve the use of onSnapshot (although I observed the same issue when using onSnapshot instead of getDoc).

Everything appears correct from the client side - the code doesn't appear to run twice, nor are any errors returned from the request. My rules using resource.data appear to work correctly when deployed to Firebase and don't show any errors in the Firebase console.

[REQUIRED] Environment info

firebase-tools: 12.4.6

Platform: Windows 11

[REQUIRED] Test case

Rules:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /projects/{projectId} {
      allow read: if (request.auth != null) && (request.auth.uid != null) && (resource.data.owner == request.auth.uid);
    }
  }
}

Firestore data at /projects/doc_id_here (replacing doc_id_here with the ID of the doc and uuid_here with the UUID of the currently authenticated user):

{ owner: "uuid_here" }
Screenshot from Firestore emulator:Firestore emulator screenshot

[REQUIRED] Steps to reproduce

Set up a project with the rules and data listed above, then make a request to it from the JS client SDK. For example:

import {doc, getDoc, getFirestore, connectFirestoreEmulator, Firestore} from 'firebase/firestore';

const firebaseApp = { /* Firebase app config here */ }
const firestore = getFirestore(firebaseApp);
connectFirestoreEmulator(firestore, location.hostname, 8080);

export function getProject(projectId) {
    getDoc(doc(firestore, `projects/${projectId}`))
}

[REQUIRED] Expected behavior

The Firestore emulator shows one entry with the result of the request on the Requests tab.

Screenshot 2023-08-13 140609

[REQUIRED] Actual behavior

The Firestore emulator shows two entries for each request; the first one failing with an unknown error and the second one successfully evaluating the rules.

Screenshot 2023-08-13 140651

Click on the request to view details. There's an error icon at the top of the table and a green checkmark on the line containing the related rule, and the resource section under "Detailed information" in the right column reads (Error: unknown) (undefined):

Screenshot 2023-08-13 140915

acmertz avatar Aug 13 '23 19:08 acmertz

Same here.

Did you find any workaround by any chance? @acmertz ?

DavidWeiss2 avatar Oct 22 '23 16:10 DavidWeiss2

I'm having this, too, and I suspect it causes the data never to resolve or throw an error; it just hangs forever. Did you experience that, maybe, or is it another emulator bug?

kossnocorp avatar Jan 02 '24 03:01 kossnocorp

I'm seeing a similar issue on Mac. When I look into the logs on my IDE running the Firebase client it looks like only a single write is being performed but then I see this logged in the emulator Firestore requests.

Removing request.auth.uid == request.resource.data.userId from the firestore rules seems to fix the emulator logs.

image

joshqn avatar Jan 07 '24 02:01 joshqn

Same here.

For my app, I use role-based security and I check user's capabilities via Firestore collection. If this case also appears in production, I wonder if my document reads will peak?

Sample Role Document

{
    userId_12345: {
        ...
        capabilities: [
                "products.list",
                "products.get"
                ...
        ],
        ...
    }
}

Security Rule Function I wrote a function in security rules to get document and check capability for related action.

function checkCapabilities(request, capabilities) {
  
    // Gets user's role from collection
    let role = debug(
        get(/databases/$(database)/documents/Claims/$(request.auth.uid)).data
    );

    return // boolean if capabilities match with required action capability or not.

}

** Sample Query** This query fires double security rule check. debug() function logs checkCapabilities, it logs twice too.

....

const querySnapshot = await getDocs(
    query(
        collection(
            getFirestore(),
            "Products"
        ),
        where(
            "companyId", "==", selectedCompanyId
        )
    )
    .withConverter(productsConverter)
);

...

Emulator's Firestore Requests Screenshot 2024-01-08 at 7 31 37 AM

thekntl avatar Jan 08 '24 04:01 thekntl

Did you find any workaround by any chance?

@DavidWeiss2 I haven't found a proper workaround, unfortunately - in the meantime I've resorted to using a separate set of rules in my dev environment based on custom claims to cut down on the noise during development. This is less than ideal because it means I also have to test against my production ruleset before deploying. My application is fairly small so it isn't too difficult for me to run a smoke test of all critical features before deploying, but as it continues to grow, a proper fix or guidance from Firebase would definitely be appreciated.

acmertz avatar Jan 09 '24 15:01 acmertz

This is also happening to me. For every successful rule evaluation there is a preceding one that always errors out.

Here a single request has been made: image

transfer1992 avatar Feb 12 '24 22:02 transfer1992

Any idea if this issue exists only in emulator?

Piogar avatar Feb 18 '24 11:02 Piogar

Yes, it is emulator only.

On Sun, Feb 18, 2024, 13:43 Piogar @.***> wrote:

Any idea if this issue exists only in emulator?

— Reply to this email directly, view it on GitHub https://github.com/firebase/firebase-tools/issues/6252#issuecomment-1951217354, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADBVIS57VR3IXW7QJSAIZ73YUHSPNAVCNFSM6AAAAAA3O2T6V2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSNJRGIYTOMZVGQ . You are receiving this because you were mentioned.Message ID: @.***>

DavidWeiss2 avatar Feb 18 '24 11:02 DavidWeiss2

After upgrade firebase to version 13.4.0 still have this issue, Anyone got any idea to fix this now?

ASE55471 avatar Feb 28 '24 02:02 ASE55471

Experiencing same issue

dubem-design avatar Apr 29 '24 15:04 dubem-design