Note: This question is tagged polymer
because the Polymer library is used to generate the Javascript.
This question is about two different but related problems dealing with Firebase security. Problem 1 and Problem 2 seem to suggest opposite realities and opposite results when trying to get the Firebase security rules to work. (FWIW: Here is my prior unsuccessful attempt to write this question.)
Here is the live code in a JSBin.
http://jsbin.com/hinehoyigo/edit?html,output
Problem 1
Firebase Security Rules Block Writing to Firebase
Instructions
- Enter your firebase ID. Example: "hot-sauce-123"
- In a new tab or window, go to your firebase and open it
- Allow anonymous auth: Your firebase > Login & Auth > Anonymous tab > Check "Enable Anonymous User Authentication"
- Apply no security rules: Security & Rules >
{ "rules": { ".read": true, ".write": true } }
- Return back to jsbin
- Select "anonymous" as auth provider: dropdown menu > anonymous
- Click button labeled "login"
- Verify login status per fields to right
- Open your console: Chrome > View > Developer > Developer Tools
- Click button labeled "Print User to console"
- Double-check login status by verifying user object printed to console
- Click button labeled "Print Firebase to console"
- Verify correct firebase by checking Firebase URL printed to console
- Click button labeled "Write to Firebase — Plain Url"
- Check your firebase data; notice no write occured
- Click button labeled "Write to Firebase — .json Url"
- Check your firebase data; notice successful write
- Distinguish the two write attempts because former attempts to write {"quux":"baz"}; latter attempts to write {"jquux":"jbaz"}
- Add security rules: Security & Rules >
{ "rules": { "users": { "$uid": { ".read": "auth != null && auth.uid === $uid", ".write": "auth != null && auth.uid === $uid" } } } }
- Click again the button labeled "Write to Firebase — .json Url"
- Check your firebase data; notice write NOW FAILS
- Conclusion / Problem Statement: Firebase security rules block writing to Firebase.
Problem 2
Simulator blocks .json URL from being used (as required above)
Instructions
- Open your Firebase
- Verify security rules are in place (see above step #19 in Problem #1)...
- Open your simulator: Vertical Navigation Menu > Simulator
- Check radio button labeled "Custom Auth"
- Custom Auth input field should read something like "{ provider: 'anonymous', uid: 'ag69g401-f097-4171-bca4-927fd1a6e1f3' }"
- Click button labeled "Authenticate"
- Verify little green check mark is next to radio button labeled "Custom Auth"
- Go to section 2
- Click tab labeled "Write"
- In input field labeled URL, enter "users/ag69g401-f097-4171-bca4-927fd1a6e1f3/foo/bar"
- Verify the user ID in the URL path you just entered, matches the uid value in the above Custom Auth field
- Click button labeled "Simulate Write"
-
Notice response says something like:
Attempt to write{"key":"value"} to /users/ag69g401-f097-4171-bca4-927fd1a6e1f3/foo/bar
withauth={"provider":"anonymous","uid":"ag69g401-f097-4171-bca4-927fd1a6e1f3"}
/ /users /users/ag69g401-f097-4171-bca4-927fd1a6e1f3:.write: "auth != null && auth.uid === $uid" => true
Write was allowed. - Notice: This result is the opposite result from above steps #14 and #15 where the plain URL (without .json appended) failed to write
- Append ".json" to the URL so the input field reads something like "users/ag69g401-f097-4171-bca4-927fd1a6e1f3/foo/bar.json"
- Click button labeled "Simulate Write"
-
Notice response says something like:
Invalid path. Simulation aborted. - Notice: This result is the opposite result from above steps #16 and #17 where the .json appended URL was the only one that worked;
- Notice these simulator tests suggest the opposite results than those tested from the live code in above Problem #1
Problem 1
You're using the Polymer firebase-auth
element to authenticate with Firebase.
<firebase-auth id="firebaseLogin"
user="{{user}}"
...
Under the hood this calls the Firebase.authAnonymously()
method, which authenticates the current session in the Firebase JavaScript SDK.
You're writing to Firebase using:
computeFbTargetJson: function(f) {
return f + '.json';
}
and
this.set('$.ajax.url' , this.fbTargetJson);
this.set('$.ajax.body' , JSON.stringify({
jquux: 'jbaz'
}));
this.$.ajax.generateRequest();
This is doing an AJAX request to Firebase, which means that you're using Firebase's REST API. But since this is a regular HTTP call, it will not "inherit" then authentication from the Firebase JavaScript client.
To authenticate your REST request, you will need to pass in an auth
parameter as documented in the Firebase documentation. You can get the token from the Firebase reference using ref.getAuth().token
.
Problem 2
Each element in your Firebase database is accessibly by a unique URL. You can either access it with one of the Firebase SDKs or by directly accessing the REST API that Firebase exposes.
From what I can gather from the jsbin, you're writing to Firebase using:
computeFbTargetJson: function(f) {
return f + '.json';
}
and
this.set('$.ajax.url' , this.fbTargetJson);
this.set('$.ajax.body' , JSON.stringify({
jquux: 'jbaz'
}));
this.$.ajax.generateRequest();
This is doing an AJAX request to Firebase, which means that you're using Firebase's REST API. The first paragraph of that API documentation explains how Firebase database URLs map to the REST API:
We can use any Firebase app URL as a REST endpoint. All we need to do is append .json to the end of the URL and send a request from our favorite HTTPS client.
So in order to access any data in Firebase using the REST API, you append .json
to the URL of that data.
When you're using the Firebase Simulator, the operation is similar to using Firebase's JavaScript SDK. In that case, you should not put the .json
suffix at the end of the URL.
So given a Firebase database at https://mine.firebaseio.com/
, say you have a user profile at /users/de01fc8104
.
- You can access that record in the simulator or with a Firebase SDK as
https://mine.firebaseio.com/users/de01fc8104
- To access the record using the REST API, the URL is
https://mine.firebaseio.com/users/de01fc8104.json
Summary
Both of your problems are caused by the fact that you're using two different ways of accessing Firebase: the JavaScript SDK and the REST API. While these two methods can be used together, you will have to ensure you provide the information that is needed. In general you will have an easier experience if you stick to using one way of accessing Firebase from a single client.
@FrankvanPuffelen's answer in Polymer-speak translates into:
Use the <firebase-collection>
element's .add()
method to write data to Firebase from the client while under security rule enforcement. It's more efficient from a code standpoint as firebase-collection
handles all the necessary auth tokens for you automatically.
来源:https://stackoverflow.com/questions/34331388/firebase-security-rules-block-writing-to-firebase