Search code examples
swiftfirebase-realtime-databasefirebase-authenticationfirebase-securityfirebase-app-check

Firebase Realtime Database permission denied, what is auth?


TL;DR: Does AppAttest/DeviceCheck count as 'auth' in rules?

I have a Swift iOS app, which stores its logs to Google Realtime Database, and I am unable to send any data to the database, with "Permission denied" error. My goal is to ensure that only my app can write logs there, and prevent attackers from flooding the DB with random data. I thought the AppAttest/DeviceCheck could help me.

So, I configured AppAttest/Device check and it works. While my app launches, I see in debugger that it succeeds to pass DeviceCheck with Google. Inside FPersistentConnection, connectionState becomes ConnectionStateConnected and I receive FIRDatabaseConnectionContext with populated _appCheckToken but _authToken set to nil.

My DB rules look like this:

{
  "rules" : {
    ".read" : "false",
    ".write" : "auth != null"
  }
}

My question is: do I ever need the auth != null option, since I have DeviceCheck enforced, maybe ".write" : "true" is enough? My app neither cares about role management, nor authenticates with Google (it just dumps logs in a big pile), so maybe 'auth' is redundant?

Ultimately, what is 'auth'? Does AppAttest/DeviceCheck count as 'auth'?

PS: When I set ".write" : "true" everything works like a charm.


Solution

  • do I ever need the auth != null option, since I have DeviceCheck enforced, maybe ".write" : "true" is enough?

    App Check and Authentication are completely different things. One is not a substitute for the other. App Check isn't a 100% guaranteed way to ensure that only your app is accessing some resource. From the documentation:

    App Check relies on the strength of its attestation providers to determine app or device authenticity. It prevents some, but not all, abuse vectors directed towards your backends. Using App Check does not guarantee the elimination of all abuse, but by integrating with App Check, you are taking an important step towards abuse protection for your backend resources.

    However, a check for user authentication guarantees that only an actual authenticated user account (or someone who has a valid auth token for a user) can actually access the resource. But the bearer of the token does not need to be using your app in order to access the resource.

    You cannot substitute one for the other. For the best security, you should use them both, and especially use security rules with auth to correctly to give individuals access to only the data they should be able to read and write.