Questions about Firebase Security (Swift) - ios

Ok. I am unsure about a few things with Firebase and its security and I was hoping that you guys would help me clear a few things up and also this might be a great topic to get some noob questions cleared up.
1. Does FIRAuth.auth() manage tokens and connections?
I have very simple code in my project:
if let user = FIRAuth.auth()?.currentUser {
// Do Stuff
}
Is this all I need to do? How does this connect to Firebase? By this I mean is this data sent via GET/POST or is it encrypted? Should I be generating tokens and authentication and then checking that?
2. Is this sufficient rules to stop access to the DB?
I have defined some rules in my database:
{
"rules": {
".read": "auth != null",
".write": "auth != null",
"score": {
"$user_id": {
".write": "$user_id === auth.uid"
}
}
}
}
What I want to achieve here is the ability to save a score value in the DB. However, the database should only be accessible to the user logged in and also the entry with the user_id also. They should not be able to access another players score.
3. Can I test these rules?
Is there a way to have dummy users and privileges in the console so I can test these? If so, how?
4. Is it possible to have SQL injections if there is no SQL database?
Are there other methods I should be trying to stop, for example stopping MITM attack, etc.?
Appreciate all answers.

Related

Firebase rules: still not safe after implementing auth

I have these rules in my Firebase Real-time Database:
{
"rules": {
".read":"auth !== null && auth.uid === 'my_uid'",
".write": false
}
}
When I try to read the data without authentication, access is denied. So far, only my app can read it successfully.
Still, I'm getting an email from time to time, from Firebase, that my rules are not secure and that everyone can read the data.
What am I missing here?

Firebase Realtime Database Security Rules ( Read And Write )

Ok I have a Realtime database connected to a app and till today the rules ( read and write ) were set to true , everything was working fine ....but every time a message pops up saying
Your security rules are defined as public, so anyone can steal, modify, or delete data in your database
I tried few things but data was not accessed...data was only accessible when the rules were set to true
but is there any way to modify the rules to make it more secure
I want this Data to be accessed by only few known apps ( My Apps )
Start here in the docs and work your way through. It's very practical and easy to understand.
data was only accessible when the rules were set to true
Firebase RTDB has a public URL, so anyone can try connecting to it. It is your job to decide whether they can do this or not. If your rules for any path/node look like this, it is available to anyone who makes a request:
{
".read": true,
".write": true
}
If you only want to allow users of your app to connect to RTDB, you can use Firebase Auth and use conditions like this:
{
".read": "auth != null"
".write": "auth != null"
}
I want this Data to be accessed by only few known apps ( My Apps )
Access is determined on a user level, not by app. Start here in the docs.
but is there any way to modify the rules to make it more secure
Either in the Firebase Console, or deploy them via the CLI. If you're new to this, start with the Firebase Console and use the Rules Playground to test different rules. See docs for more information.
So unless someone has access to my Google account or a app /web integrated with my database... No one can access the data even if the rules are set to true, am I right ?
Your database is not "integrated". It is a deployed instance that is reachable via a public URL - that's how your clients connect to RTDB. If your rules allow any read or write operation, then your database is wide and open for everyone. Hence, the email that you have received informing you that this is not secure.
{
"rules": {
".read": "auth.uid !== null",
".write": "auth.uid !== null"
}
}
Currently accepted Rule docs

Swift Firebase Rule Permissions Denied when observeSingleEvent

I'm developing a app that allows teachers to record their students' lessons. Using Firebase Rules I want to allow teachers access to certain schools. I have the following Rules:
{
"rules": {
"Schools" : {
"$schoolId" : {
".read" : "data.child('Teachers').hasChild(auth.uid)",
".write" : "data.child('Teachers').hasChild(auth.uid) ||
root.child('User').child(auth.uid).child('Invitation').exists()"
}
},
"Users" : {
"$uid" : {
".read" : "auth.uid === $uid",
".write": "auth.uid === $uid"
}
}
}
}
In the simulator everything works fine, but when firing the below all permissions are denied to all schools.
DataService.ds.REF_SCHOOLS.observeSingleEvent(of: .value) { (snapshot) in
MySchools.mySchoolKeyList.removeAll()
MySchools.mySchoolList.removeAll()
if let snapshot = snapshot.children.allObjects as? [DataSnapshot] {
for snap in snapshot {
if let recordDict = snap.value as? Dictionary<String, AnyObject> {
if let name = (recordDict["SchoolName"] as? String) {
MySchools.mySchoolList.append(name)
}
MySchools.mySchoolKeyList.append(snap.key)
}
}
if MySchools.mySchoolList.isEmpty {
MySchools.mySchoolList.append("You do not belong to any schools.")
}
}
}
Below is snapshot of the Firebase database for reference:
Does anyone know what's wrong with my rules? Also how to handle the permission denied result would be appreciated.
Your code is trying to read from /Schools, but your rules don't give anyone permission to read from /Schools. So Firebase correctly rejects the read.
I have a feeling that you expected the read operation to automatically filter the result to only return the school nodes (/Schools/$schoolId) that the user has access to. But that is not how Firebase security rules work: rules cannot be used to filter data.
This is a common source of confusion for developers getting started with Firebase's server side security rules, so I recommend you check out of the some previous questions mentioning "rules are not filters".
Nowadays there is a way to get filtered data, without giving the user access to all Schools. For this you will need to:
Use a query to only request the schools that you're supposed to have access to.
Validate that this query is allowed on /Schools in your security rules.
For an example of this see query based rules in the documentation.
The code should be something like this:
let query = DataService.ds.REF_SCHOOLS.queryOrdered(byChild: "Teachers/"+uid).queryValue(equalTo: true);
query.observeSingleEvent(of: .value) { (snapshot) in
...
But the problem with this is that you would need to define an index for each teacher. While this is technically possible, it would lead to an unreasonable number of indexes.
In hindsight: your current data structure allows you to efficiently find the teachers for a specific school. It does not however allow you to efficiently find the schools for a specific teacher.
To efficiently allow finding the schools for a specific teacher, add an additional data structure to your database that maps schools to each teacher. E.g.
teacherSchools
teacherUid1
schoolId1: true
schoolId2: true
teacherUid2
schoolId2: true
schoolId3: true
With this structure you can easily read all school Ids for a teacher, and then load each school. This loading is a lot faster than most developers expect, since Firebase pipelines the requests over a single connection.
For a longer/another explanation of this approach, see Firebase query if child of child contains a value and Firebase Query Double Nested.

Can't get permission to firebase database IOS

I can't get permission to database.
In xcode console I am getting this message:
[Firebase/Database][I-RDB038012] Listener at /skelbimai failed: permission_denied
So I went to firebase database, then Rules and changed like this:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write;
}
}
}
And still I cant read write from database. Where I missed something?
The rules you changed are the rules for Cloud Firestore, while the error message is coming from the Firebase Realtime Database.
You'll need to switch your console from the Realtime Database to Firestore. To do so:
Go to the Firebase database console
Select Realtime Database
From here on the console will stick to showing the realtime database, unless you switch again.
If you already have the console open on one database, you can switch to the other by clicking on the dropdown next to Database and selecting the database you want to manage:
To grant full access to anyone, use these rules:
{
"rules": {
".read": "true",
".write": "true"
}
}
Please only use this for early development stages, as having your entire database publicly read-and-writeable makes it very easy to abuse.
Try Following
Goto Database -> Rules then
copy and paste it
{
"rules": {
".read": "true",
".write": "true"
}
}

Firebase Works In Simulator But Not On iPhone

I am trying to pull in data on a certain View Controller from my Firebase database using the following:
_refHandle = [_postRef observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
NSDictionary *postDict = snapshot.value;
// ...
}];
The code works great in the simulator but not working on the iPhone(code gets skipped over). I use this piece of code in other parts of my application and it works on both the device and simulator. I have also implemented this piece of code into a custom method for pulling in data (Still does not work). Does anyone know why this is not working on a real device?
I found that if you logged in, and delete the application, then after you install the application again, you will still be logged in. I do not know exactly, but I assumed that Firebase somehow binds the account cache to the Keychain with Bundle Identifier, not in the app local storage.
My solution is not good enough but it worked for me:
Remove your APP from real device.
Go to your project in Navigation Panel.
In General tab change your Bundle identifier, for example: "myApp.com" to "myApplication.com" or whatever you want.
Build and run
Bingo!
Update: Firebase remembers your data in keychain using your Bundle identifier as key, that's why it works when you change Bundle Identifier
It happens because of your security rules. In your Firebase Console:
Go to the Database menu item
Go to the Rules tab
Update the security rule to:
{
"rules": {
".read": true, // Or whatever rule you would like
".write": "auth != null"
}
}
Go to the Database menu item
Go to the Rules tab
Update the security rule to (for real device):
{
"rules":
{
".read": "auth != null",
".write": "auth != null"
}
}
Update the security rule to (for real simulator Test):
{
"rules":
{
".read": "auth == null",
".write": "auth == null"
}
}

Resources