Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RTDB emulator doesn't work properly with databaseAuthVariableOverride #2554

Open
rhodgkins opened this issue Aug 18, 2020 · 6 comments
Open

Comments

@rhodgkins
Copy link
Contributor

rhodgkins commented Aug 18, 2020

[REQUIRED] Environment info

firebase-tools: 8.7.0
Platform: macOS
node: v10.22.0
firebase-admin: 9.1.0
firebase-database-emulator: v4.5.0

[REQUIRED] Test case

Add some rules like the following:

{
   "rules": {
      "$userId": {
         "publicAccess": {
            ".validate": "newData.isBoolean()"
         },
         "data": {
            ".read": "$userId === auth.uid || (auth.token.auth_time >= ((now / 1000) - 60 * 60) && auth.token.customClaimAccess === $userId) || data.parent().child('publicAccess').val() === true"
         }
      }
   }
}

[REQUIRED] Steps to reproduce

const admin = require('firebase-admin')

const adminApp = admin.initializeApp({
   databaseURL: 'https://blah.firebaseio.com',
})

const noAuthApp = admin.initializeApp({
   databaseURL: 'https://blah.firebaseio.com',
   databaseAuthVariableOverride: null,
}, 'no-auth')
const userAuthApp = admin.initializeApp({
   databaseURL: 'https://blah.firebaseio.com',
   databaseAuthVariableOverride: {
      uid: 'USER_ID_1',
   },
}, 'user-auth')
const customClaimsAuthApp = admin.initializeApp({
   databaseURL: 'https://blah.firebaseio.com',
   databaseAuthVariableOverride: {
      uid: 'USER_ABC',
      token: {
         customClaimAccess: 'USER_ID_2',
         auth_time: (Date.now() / 1000)
      },
   },
}, 'custom-claims-auth')

const assert = require('assert').strict

async function test() {
   await adminApp.database().ref().set({
      USER_ID_1: {
         data: {
            blah: "hello1",
         },
      },
      USER_ID_2: {
         data: {
            blah: "hello2",
         },
      },
      USER_ID_3: {
         publicAccess: true,
         data: {
            blah: "hello3",
         },
      }
   })

   await assert.rejects(noAuthApp.database().ref('USER_ID_1/data').once('value'), /permission_denied/i, 'Should deny access with noAuthApp as not accessing public data')
   await assert.doesNotReject(userAuthApp.database().ref('USER_ID_1/data').once('value'), 'Should allow access with userAuthApp as accessing own data')
   await assert.doesNotReject(customClaimsAuthApp.database().ref('USER_ID_2/data').once('value'), 'Should allow access with customClaimsAuthApp as accessing data specified in claims')
   await assert.doesNotReject(noAuthApp.database().ref('USER_ID_3/data').once('value'), 'Should allow access with noAuthApp as accessing public data')
}

test().catch(error => {
   console.error(error)
}).finally(() => Promise.all(admin.apps.map(a => a.delete())))
  1. Run emulator firebase --project blah emulators:start --only database (can't use emulators:exec as need to keep it running to view the rule evaluations).
  2. Run the above script against the emulator FIREBASE_DATABASE_EMULATOR_HOST=localhost:9000 node script.js.
  3. View the evaluated DB rules: http://localhost:9000/.inspect/coverage?ns=blah

[REQUIRED] Expected behavior

I'd expect the tests to pass and the auth_time rule to be evaluated 3 times - returning true once and false twice.

[REQUIRED] Actual behavior

Rules are not always evaluated - seems to bail out...

image
image
image

To simplify the case when running:

await assert.rejects(noAuthApp.database().ref('USER_ID_1/data').once('value'), /permission_denied/i, 'Should deny access with noAuthApp as not accessing public data')

I'd expect this rule to be evaluated (as there's no auth.uid):
(auth.token.auth_time >= ((now / 1000) - 60 * 60) && auth.token.customClaimAccess === $userId) || data.parent().child('publicAccess').val() === true

image

The whole rule seems not to be evaluated, despite the first rule being evaluated...!

image

image

@rhodgkins
Copy link
Contributor Author

Just to add to this, I think the missing evaluations might be to do with null values because if you have a rule such as data.child('blah').val() < 100 || data.child('other').exists() and blah is unset (null) the hover info will show .val() returning null each time but the result count of data.child('blah').val() < 100 won't match this count.

@akauppi
Copy link

akauppi commented Jun 21, 2022

I'm also tackling with similar.

If you're still on this (2 years later!!!!):

  • are you sure the calls lead to the emulators? .firebaseio.com looks suspicious
  • By using demo-blah (anything starting with demo-) one makes sure the calls will not aim at the real Firebase project in the cloud.

I've created a request for proper documentation on how to use databaseAuthVariableOverride with firebase-admin and emulation.

@rhodgkins
Copy link
Contributor Author

@akauppi I don't understand your points sorry. The .firebaseio.com hostname is swapped out by the internals of the SDK when FIREBASE_DATABASE_EMULATOR_HOST envar is specified. I imagine its something to do with null checks in the emulator etc. etc. that doesn't quite match production.

@maneesht
Copy link
Contributor

maneesht commented Aug 1, 2022

@rhodgkins - have you tried running this with the latest version of firebase-admin and firebase-database-emulator?

@rhodgkins
Copy link
Contributor Author

@maneesht yep, if you run the reproduction steps above the same thing happens.

Ran firebase setup:emulators:database to get the latest DB emulator (it downloaded v4.8.0).

@google-oss-bot google-oss-bot added Needs: Attention and removed Needs: Author Feedback Issues awaiting author feedback labels Aug 2, 2022
@maneesht
Copy link
Contributor

@rhodgkins thank you for your patience. We might have identified what the problem is, however we do not have the bandwidth to support this right now. I will keep this open until we can look further into this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants