Firestore; security rules : if request.auth != null;

Oh no,

What raw error message does it give you if you put the alert on the get record collection?

image
Alert is set to:
image

It shows the following raw error in preview (both PC and iOS):
{“error”:{“code”:403,“message”:“Missing or insufficient permissions.”,“status”:“PERMISSION_DENIED”}}

I have used the rule below and it is working just fine:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write:if request.auth != null;
    }  
  }
}

I tried another rule , and it is working, too:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write:if request.auth.uid != null;
    }  
  }
}

BTW, if there is a firewall, try to disable it and re-check.

Thank you @Mazen_Al-Sakkaf and @Ashley_Mclean for your feedback when using these security rules in firebase. With your hints I now found that the troubles commences with the type of the data resource:

  1. Sadly the type “Google firebase / Cloud firestore” lacks the ability to work with sub-collections. (Firestore: get sub-collection - #4 by stayfoolish and Firebase firestore nested collections - #4 by Mari). :sleepy:
  2. To use sub-collections I followed the tutorials to the type “REST API direct integration”
  1. But I did not realize until now, that I separated the authentication from the data resource. This resulted in the disfunction when using a security rule.

Do you know where I can find an instruction, how to use “REST API direct integration” together with the authentication?

Hi,

Did you have a look at the following info for roles etc?

I am not sure if this could help you…

Thank you, Ashley, these roles are good to know!
While your link above seems to be more about administration roles, especially this part of the docs proofed to be very helpful:
https://firebase.google.com/docs/reference/rest/auth?hl=en#section-sign-in-email-password

Thankfully I figured something out, that allows the use of the Firestore security rules AND nested collections in Firestore. Hopefully the following discription can be beneficial for others, who stumble across the same issues as well:

  1. Delete the flow function “Email and password authentication (Firebase Auth)” , because it does not return the idToken in its outputs.
  2. Instead use a “http request” flow function with POST:
    URL:
    body:
  3. save the idToken into a AppVariable by using the output:
    image
  4. Adding ‘Authorization’ to the header of the ‘REST API direct integration’ in the data configurator.
  5. For GET, POST and DELETE: Binding the AppVariable with the idToken to the header
    image
    image
  6. For PATCH: Setting it into the header of the ‘http request’ (can not be done in the data configurator currently until PATCH is included in the data configurator)
    image
    image

Now the Firestore security rule works with my App: :sweat_smile:
image

I learnd about the solution thanks to this course in udemy.com, which I recommend to everyone starting AppGyver withFirebase: Complete Firebase Course by @o.ezzat :+1:

For the future there is the hope, that functionality of the Firebase-Connector grows and will include

  • nested collections
  • idToken in outputs

Then it should be better to use the pre-built flow function around Firebase Auth. Because most likely with the posted solution there will be other issues on the road, that I am not seeing currently (e.g. ensuring the persistance of the log-in)… But that might be a topic for another thread :wink:

4 Likes

Thank you @stayfoolish for the tutorial. It’s very helpful. Did you managed to get the idToken when the user is already signed in? FireBase Auth functions in AppGyver return a refresh token which can be used to get an ID token (See this reference doc. However I can’t retrieve the fresh token returned by Auth node. Please post here if you have any success.

1 Like

Hi @Alan_Alves ,

Firebase does respond according to the Docs you refer to (Firebase Auth REST API), including a new idToken. Most likely you approached it in the same way like I (see below).
My guess is, that it doesn’t work for your app right away, because you will get a NEW idToken. But the “… (Firebase Auth)” flow function still store the old idToken, which is not valid anymore. That means, the " … (Firebase Auth)" flow functions can not co-exist with refreshing the idToken via HTTP-request.

To exchange the refreshToken for a new idToken:

  1. image
  2. image
  3. connect to first output a image
  4. image

EDIT:
5. and to get the idToken only:

  • outputs[“HTTP request”].resBodyParsed.id_token or
    outputs[“HTTP request”].resBodyParsed[“id_token”]
1 Like

Thank you. Maybe that’s the reason we cannot retrieve the refreshToken from ...(Firebase auth). For those interested, to set the persitence:

  1. Create a local storage to store the refresh token
  2. Create a data record to save the refresh token on the first time the user logs in.
  3. On the sign in page mount, retrieve the refresh token from the local storage
  4. exchange it for the an idToken
  5. update the local data record to have newly generated refresh token.
  6. If the app cannot retrieve the token from the local storage or if the exchange is not successful, than skip steps 4 and/or 5 and load the input fields so the user may authenticate.
2 Likes

You are the best @stayfoolish . I have weeks looking for a solution until I found you. Thanks a lot!

1 Like

Hello I have a problem. When I add the header of the ‘Direct integration of the REST API’ in the data configurator and I go to the http request it does not show me the authorization header as a parameter. Can you help me?

image

Rules in Firestore

image

Select binding type: “list of values” instead of “formula”
image

1 Like

Thx for your work on this.
In my app, I’m storing my users and most of my data in my MSSQL back end.
Lets say I’m building an online catalog.
I’m only using AG as a mobile front-end browsing tool for end users. All of the maintenance of the inventory, categories, etc. is done with my backend tool storing data in MSSQL.
But I’m not actually storing images in MSSQL, I’d like to store them in firebase so all that image bandwidth isn’t hitting my server. I just store a path. (was going to store in an Azure (microsoft) container as public blobs, but threads here seem to like the better integration with FB so in my early stages I thought it would be better to change to FB).

However, a future release will let someone upload an image directly from the AG app., so it makes sense to integrate this now.

Do you see any reason why I can’t use BOTH REST API data for my main data, and Firebase for all my images?

Seems like I’d have to upload an image first, then save the Inventory record once I have the image path? Honestly, I’m going to want to save a hi-res image, a resized image, AND a 70x50px thumbnail.

Instead of 3 images, I could use something like Imgix.

You can do it, if you prefer to use more than one backend. There is no technical hurdle.

Great post. But it has struck me like a lightning as I just moved my app to production and thought everything would get secured like a charm just by changing the Firestore rules. Now I’m in soup as I have more than 50 DB hit-points in my app and almost 10 data resources. Any other way to implement some kind of a workable security of Firestore data? Also I have extensively used Firebase functions - would that be affected if I implement the authorization following your steps?

I have gone with some sort of hybrid. I have a few tables that are read only which prevents anyone changing the product or service they are getting, then the less sensitive tables are RW. Its not ideal, but I´ve limited the harm anyone could do.

Ie, I have a users table that needs to be updated as they progress through an adventure. But they can´t login in the first place unless there is a matching entry in the bookings table that is read only.

Not sure how that way of thinking could be applied to your app.

1 Like

The firebase functions are not affected by the firebase security rules.

1 Like

Thats really good news. I’m implementing your steps. I could login and store the id token now. But struggling to replace the " Get current user (Firebase Auth))" flow function. Any tip on this?

Hi I’ve now implemented your steps completely. Everything works great. The only thing that doesn’t work is my image uploads (to firebase storage) are now blocked - I use the Appgyver firebase files upload flow function. Any idea how to resolve this?

Thanks. My only question now is, if we use direct rest to login, will built in create and update record flow functions now not work properly if rules are set to only allow logged in users to write? So will every write request have to be done the same way, with direct rest and token?