Firebase - permission denied after change of developer - ios

This is an odd one! I had a couple of developers building a mobile app using Firebase and React Native. They had everything working fine and left the company at the end of January. I have since picked this up to get it in to the hands of our staff. However I am running in to issues!
Before the guys left they added me to the Firebase account, I then created an iOS application in there and have made sure that I have changed the React Native code to point to the new Firebase iOS app.
That seems to be fine as users can log in with Facebook, their credentials are added to the Authentication table and they are given a UID. That UID is then used in our database as a primary key and appears to be added just fine, however at the next read/write attempt we get a permission denied error:
Error onDBEvent: Error Domain=com.firebase Code=1 "Permission Denied" UserInfo={NSLocalizedDescription=Permission Denied}
As this is code that I have not written I'm stabbing in the dark a bit as to where the issue may be, I think it is in this function:
export function likeDestination (destinationKey, score, taggedImageSetIndex, imageTagIndex) {
return function (dispatch, getState) {
const user = getState().auth.auth
let iTagIndex = imageTagIndex + 1
let updateValue = {}
updateValue[destinationKey] = score
console.log('likeDestination:: userID=', user.uid);
console.log('likeDestination:: taggedImageSetIndex=', taggedImageSetIndex);
// Set the user's preference for this tag then update (increment) the imageTagIndex
return firestack.database.ref(`user-data/${user.uid}/tagSets/${taggedImageSetIndex}/userScores`)
.update(updateValue)
.then(() => {
return firestack.database.ref(`user-data/${user.uid}/tagSets/${taggedImageSetIndex}`).update({imageTagIndex: iTagIndex})
})
.catch(err => {
console.log('Error in setting destination "like" data to Firebase:', err)
RouterActions.ErrorPage({ error: err })
})
}
}
It's worth stating that the console.log statements above return the correct values.
The only reference I can find for the getState function is below, not sure what the .auth.auth calls will do in order to get the user from the database but it seems to work!
export function getState (toggle) {
return {
type: GET_STATE,
payload: toggle
}
}
I've had a look through various posts around similar problems and they all seem to point to the rules in Firebase. The rules haven't changed since it worked and if I run those queries through the simulator I get a big tick next to the relevant read and write rule. Here are the rules for the DB:
{
"rules": {
"destination-scores": {
".read": true,
".write": false
},
"destinations": {
".read": true,
".write": false
},
"tv-admins": {
".read": "auth != null",
".write": false
},
"tv-queues": {
".read": "auth != null",
".write": "auth != null"
},
"tv-screens": {
".read": "auth != null",
".write": "root.child('tv-admins').child('ids').val().contains(auth.uid)",
".indexOn": "status"
},
"user-data": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
}
}
The queries in the code sample above are targeting the user-data rules and in the simulator that works fine, just not from the app. As I mentioned, the rules have not changed. What has changed is that the code is now running on my machine, as opposed to the original developer's, and there is a new iOS app created in Firebase.
As I also mentioned, I have ensured that I have replaced the old Firebase API key, messaging sender ID, Auth domain, DB URL and storage bucket with the new details. I believe this is working as users can log in via Facebook and get to the first stage in the app... at which point their user data has been added to the user-data table.
I'm new to Firebase and React Native so I'm not entirely sure where, in the code, this is happening but I suspect it may be this function:
export function connectUserData (firedb, user, authProvider, onUserDataChanged) {
const now = new Date()
return firedb.ref(`user-data/${user.uid}`)
.update({ email: user.email, connectedAt: now.toISOString(), authProvider: authProvider })
.catch(err => {
console.log('Error in updating meta data in connectUserData():', err)
throw new Error('Error in updating meta data in connectUserData()!')
})
}
This is called as part of an init function that checks if a user is authenticated... as in, they exist in the Authentication table/list in Firebase
I simply do not understand why I'm getting permission denied when I had permission, literally, seconds before! Any help would be much appreciated

Related

Realtime Database Rules not working as expected

I am facing a puzzling situation with Realtime Database Rules.
The rules below are working, they allow me to write data to FirstCollection:
{
"rules": {
"FirstCollection": {
".read": true,
"$Section": {
".write": "(auth!=null)"
}
}
}
}
This second set of rules used to work until yesterday, and it no longer works:
{
"rules": {
"FirstCollection": {
".read": true,
"$Section": {
".write": "(auth!=null)&&((auth.uid=='98ab..myOwnUID..23YZ')||(auth.uid=='98ab..aSecondUID..23YZ'))"
}
}
}
}
I have checked everything I could think about including the exact value of myOwnUID.
Can any experienced user spot the issue or any mistake I could be making (or could have made)?
Here is the issue I was having. The rules have in fact nothing wrong.
What happens is that the code in my app is creating a new user with the auth.createUserWithEmailAndPassword API function. And since this function has the "annoying side effect" of signing in as the newly created user, when I then hit the rules in the flow of the app my auth.uid is no longer what I expect it to be, thus explaining why the rules fires.

How to overcome the cascade in Firebase Realtime Database rules?

Given the following data structure:
items
categoryId1
itemId1
name
amount
dateAdded
itemId2
name
amount
dateAdded
categoryId2
itemId3
name
amount
dateAdded
I'd like to set the following rules:
If the user is logged-in using foo#gmail.com or bar#gmail.com, they should be able to add and update items.
Other logged-in users should be able to update only the item's amount.
I've tried the following Realtime Database rules:
{
"rules": {
"items": {
"$categoryId": {
"$itemId": {
".write": "auth !== null && auth.provider === 'password' && (auth.token.email === 'foo#gmail.com' || auth.token.email === 'bar#gmail.com')"
"amount": {
".write": "auth !== null && auth.provider === 'password'"
}
}
}
}
}
}
But, this doesn't allow someone_else#gmail.com to update the item's amount. The following promise gets rejected with "Permission Denied":
app
.database()
.ref(`items/${categoryId}`)
.push({
name,
amount,
dateAdded,
})
I know that with Realtime Database, rules work from top-down, with shallower rules overriding deeper rules.
So, what's the idiomatic way to overcome this? Is it possible to achieve the requirements above using this data structure, or do I need to restructure my data?
The problem was that the .write needed to be under $categoryId, not under $itemId. Thanks Frank!

confusing with firebase rules (read and write)

I'm using Firebase to make an IOS app but it seems i get a strange issue.
here's my current rules for the database:
{
"rules": {
".read": "auth == null",
".write": "auth != null"
}
}
In ma main app, I'm able to read and write as user or as non user to the database.
Im using a second app to edit my database by remote. they have the same firebase project so the same database.
Im registered on this second app but I'm not able to write and read on the database.
the consol say "permission denided".
If I simply change my database rules to :
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
I'm able to read and write on it.
Please help me to understand it.
{
{
"rules": {
".read": "auth == null",
".write": "auth != null"
}
}
In this first rule case .read is set to auth == null, which means that you will only be able to read from your database when not authenticated/signed in.
Changing .read to auth != null means you are only able to read from your database when authenticated.
More information is available here in the Firebase documentation.
As #creativecreatorormaybenot answered ".read": "auth == null" will only allow reading of the data when the user is not logged in.
If you want to allow both authenticated and unauthenticated users to read the data you'll want to use:
".read": true

Unable to retrieve data from Firebase unless user is signed in

I am trying to retrieve some data from Firebase but it won't retrieve anything unless I am signed in first. I've already tried editing my database's rules and setting the values to true.
Here are the Rules
{
"rules": {
".read": true,
".write": true
}
}
In your Firebase console, you can click on Database --> Rules (Tab)
In there you can specify whether or not you need to be authenticated in order to retrieve your data.
"rules": {
".read": "auth == null",
".write": "auth == null"
}
I would only leave it this way for testing. It's pretty easy to setup the simple anonymous Auth through Firebase :) Best of luck!
In case if you don't want any security you can use the below rules
"rules": {
".read": "true",
".write": "true"
}

Firebase Rules settings

I decided to use Firebase in an old objectiv C iOS app.
I installed what I needed following the instructions given here:
Add Firebase to your iOS app right after login into Firebase.
Then I followed the instructions given here:
https://firebase.google.com/docs/database/
in order to work with a database.
At this point it basically works, I can write some data.
Nevertheless I have this issue about the Rules settings.
I followed the information given here:
https://firebase.google.com/docs/database/security/quickstart
But if I set my rules like this:
{
"rules": {
".read": true,
".write": true
}
}
it works as expected. On the other hand, if I set them like this:
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
which is the default and should allow me to write data from my app, it does not work.
What is the problem?
If you don't want the user to login, you could automatically authenticate the user anonymously.
Authenticate with Firebase Anonymously on iOS
Then you could use:
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
After reading your comment in reply to cartant,it is clear that you want to allow your app users to access your database for reading and writing , without need of signing in.
I would also like to do this without requesting the user to login. Is this possible?
YES
It is possible to allow your users to access your DB without any signing process.
Actually
{
"rules": {
".read": true,
".write": true
}
}
this rule says that you are providing read and write permission to your user without signing in.
On the other hand
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
in this rule you are mentioning that your authentication ("auth != null")has to be performed before granting the read , write permissions to your user.
So to accomplish your goal just use the default rule i.e rule without authentication.

Resources