Firestore emulator false negative unit test with authentication "request.auth.token.firebase" (not found)

180 views
Skip to first unread message

Christos Malliaridis

unread,
Jun 25, 2020, 7:39:43 PM6/25/20
to Firebase Google Group
Hello everyone, 

I was just getting started with "complex" rules for firestore and wrote some unit tests before I started writing down the rules for my application.

I confronted probably a bug in the firestore rules emulator and wanted to make sure others have this problem too before reporting it. 

What I wanted to achieve with the following test was an identification of anonymous users by the request attribute token.firebase.sign_in_provider
and prevent them from creating new files (since an anonymous user has a uid this criteria was insufficient).

My test suite abstracted to the minimum looks as follow:

# firestore.rules

rules_version = '2';

service cloud.firestore {
match /databases/{database}/documents {

match /{prefix=**}/{document} {
allow read, write: if request.auth.token.admin == true;
        // TODO Verify that this is not a bad practice
}

match /articles/{articleId} {
        allow read: if request.auth.uid != null;
        allow write: if "sign_in_provider" && request.auth.token.firebase
                     && request.auth.token.firebase.sign_in_provider != "anonymous";
    }
}


# firestore test

import * as firebase from "@firebase/testing";
import * as fs from "fs";

const projectId = "firestore-emulator-example";
const data = {
"title": "hello world"
}


const rules = fs.readFileSync("../firestore.rules", "utf8");

before(async () => {
await firebase.loadFirestoreRules({projectId, rules});
});

beforeEach(async () => {
await firebase.clearFirestoreData({projectId});
});

after(async () => {
await Promise.all(firebase.apps().map(app => app.delete()));
});

describe('Articles collection', () => {
  it('should allow authenticated users to create an article', async () => {
const db = firebase.initializeTestApp({"projectId": projectId, "auth": {
      "uid": "user-id",
"email": "us...@example.com",
"token": {
"sub": "user-id",
"aud": "test-project",
"firebase": {
"sign_in_provider": "password"
}
      }
    }}).firestore();
    const articles = db.collection("articles");
    await firebase.assertSucceeds(articles.doc("article-id").set(data));
});
});

P.S. I hope I abstracted everything correctly and provided all you need. Files 

Error says: 
  FirebaseError: 7 PERMISSION_DENIED: 
Property firebase is undefined on object. for 'create' @ L13


My test fails on the emulator but I get the expected behavior on the cloud firestore when deployed.

What I also though is that maybe the "token.firebase" attribute could be a protected token attribute that is only allowed and provided with a real authentication provider (in this case firebase) and therefore gets removed on test execution. 

Can anybody confirms wether it is a bug or I am doing it wrong (with a solution / suggestion if possible)?


Fire in the store, 
Christos Malliaridis
firestore.rules
test.ts

Sam Stern

unread,
Jun 26, 2020, 8:46:35 AM6/26/20
to Firebase Google Group
Hi Christos,

Thank you for all the details!  You're right this seems like a bug, from what I can tell you're doing everything correctly.    Would you mind filing this as a bug here:

That way we can assign it to the right engineers.

- Sam

--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/b48b5748-ddbf-49a5-9f44-7a9f5e2c4b74o%40googlegroups.com.

Christos Malliaridis

unread,
Jun 26, 2020, 11:26:41 PM6/26/20
to Firebase Google Group
Hello Sam,

I found a small typo in the rules set that won't change the behavior but might be for reproduction with the provided code sapmles relevant:
The line 
allow write: if "sign_in_provider" && request.auth.token.firebase && request.auth.token.firebase.sign_in_provider != "anonymous";  
should be 
allow write: if "sign_in_provider" in request.auth.token.firebase && request.auth.token.firebase.sign_in_provider != "anonymous";  

As requested I created a ticket that can be found at https://github.com/firebase/firebase-tools/issues/2405.

Greetings,
Christos
Reply all
Reply to author
Forward
0 new messages