Firebase Auth User roles [duplicate] - swift

This question already has an answer here:
Is there any function in User Authentication for User Roles?
(1 answer)
Closed 1 year ago.
How can I add roles to users to let them see specific views in my app?
EX: They have admin, it shows something | They have user, it is normal | They have unassigned, it shows a different page.
I need help with first, making the groups through firebase, but also implementing it into my app.
I've searched far and wide but can't seem to find a tutorial for swiftUI. Anything appreciated.

Use Firebase Security Rules, It allows you to allow or disallow access to your database, It's very easy, and part of Firebase:
As per Firebase:
Firebase Security Rules stand between your data and malicious users. You can write simple or complex rules that protect your app's data to the level of granularity that your specific app requires. Firebase Security Rules leverage extensible, flexible configuration languages to define what data your users can access for Realtime Database, Cloud Firestore, and Cloud Storage. Firebase Realtime Database Rules leverage JSON in rule definitions, while Cloud Firestore Security Rules and Firebase Security Rules for Cloud Storage leverage a unique language built to accommodate more complex rules-specific structures.
Here's an example for Firestore:
service <<name>> {
// Specify your resource path.
match <<path>> {
// Allow the request if the following conditions are true.
allow read, write: if <<condition>>
}
}
... but for Realtime Database, It's JSON based:
{
"rules": {
"<<path>>": {
// Allow the request if the condition for each method is true.
".read": <<condition>>,
".write": <<condition>>
}
}
}
Read more on https://firebase.google.com/docs/rules

Related

Flutter App: Firebase Credentials viewable in Source Code (apk / web) = unsecure database? [duplicate]

The Firebase Web-App guide states I should put the given apiKey in my Html to initialize Firebase:
// TODO: Replace with your project's customized code snippet
<script src="https://www.gstatic.com/firebasejs/3.0.2/firebase.js"></script>
<script>
// Initialize Firebase
var config = {
apiKey: '<your-api-key>',
authDomain: '<your-auth-domain>',
databaseURL: '<your-database-url>',
storageBucket: '<your-storage-bucket>'
};
firebase.initializeApp(config);
</script>
By doing so, the apiKey is exposed to every visitor.
What is the purpose of that key and is it really meant to be public?
The apiKey in this configuration snippet just identifies your Firebase project on the Google servers. It is not a security risk for someone to know it. In fact, it is necessary for them to know it, in order for them to interact with your Firebase project. This same configuration data is also included in every iOS and Android app that uses Firebase as its backend.
In that sense it is very similar to the database URL that identifies the back-end database associated with your project in the same snippet: https://<app-id>.firebaseio.com. See this question on why this is not a security risk: How to restrict Firebase data modification?, including the use of Firebase's server side security rules to ensure only authorized users can access the backend services.
If you want to learn how to secure all data access to your Firebase backend services is authorized, read up on the documentation on Firebase security rules. These rules control access to file storage and database access, and are enforced on the Firebase servers. So no matter if it's your code, or somebody else's code that uses you configuration data, it can only do what the security rules allow it to do.
For another explanation of what Firebase uses these values for, and for which of them you can set quotas, see the Firebase documentation on using and managing API keys.
If you'd like to reduce the risk of committing this configuration data to version control, consider using the SDK auto-configuration of Firebase Hosting. While the keys will still end up in the browser in the same format, they won't be hard-coded into your code anymore with that.
Update (May 2021): Thanks to the new feature called Firebase App Check, it is now actually possible to limit access to the backend services in your Firebase project to only those coming from iOS, Android and Web apps that are registered in that specific project.
You'll typically want to combine this with the user authentication based security described above, so that you have another shield against abusive users that do use your app.
By combining App Check with security rules you have both broad protection against abuse, and fine gained control over what data each user can access, while still allowing direct access to the database from your client-side application code.
Building on the answers of prufrofro and Frank van Puffelen here, I put together this setup that doesn't prevent scraping, but can make it slightly harder to use your API key.
Warning: To get your data, even with this method, one can for example simply open the JS console in Chrome and type:
firebase.database().ref("/get/all/the/data").once("value", function (data) {
console.log(data.val());
});
Only the database security rules can protect your data.
Nevertheless, I restricted my production API key use to my domain name like this:
https://console.developers.google.com/apis
Select your Firebase project
Credentials
Under API keys, pick your Browser key. It should look like this: "Browser key (auto created by Google Service)"
In "Accept requests from these
HTTP referrers (web sites)", add the URL of your app (exemple: projectname.firebaseapp.com/* )
Now the app will only work on this specific domain name. So I created another API Key that will be private for localhost developement.
Click Create credentials > API Key
By default, as mentioned by Emmanuel Campos, Firebase only whitelists localhost and your Firebase hosting domain.
In order to make sure I don't publish the wrong API key by mistake, I use one of the following methods to automatically use the more restricted one in production.
Setup for Create-React-App
In /env.development:
REACT_APP_API_KEY=###dev-key###
In /env.production:
REACT_APP_API_KEY=###public-key###
In /src/index.js
const firebaseConfig = {
apiKey: process.env.REACT_APP_API_KEY,
// ...
};
I am not convinced to expose security/config keys to client. I would not call it secure, not because some one can steal all private information from first day, because someone can make excessive request, and drain your quota and make you owe to Google a lot of money.
You need to think about many concepts from restricting people not to access where they are not supposed to be, DOS attacks etc.
I would more prefer the client first will hit to your web server, there you put what ever first hand firewall, captcha , cloudflare, custom security in between the client and server, or between server and firebase and you are good to go. At least you can first stop suspect activity before it reaches to firebase. You will have much more flexibility.
I only see one good usage scenario for using client based config for internal usages. For example, you have internal domain, and you are pretty sure outsiders cannot access there, so you can setup environment like browser -> firebase type.
The API key exposure creates a vulnerability when user/password sign up is enabled. There is an open API endpoint that takes the API key and allows anyone to create a new user account. They then can use this new account to log in to your Firebase Auth protected app or use the SDK to auth with user/pass and run queries.
I've reported this to Google but they say it's working as intended.
If you can't disable user/password accounts you should do the following:
Create a cloud function to auto disable new users onCreate and create a new DB entry to manage their access.
Ex: MyUsers/{userId}/Access: 0
exports.addUser = functions.auth.user().onCreate(onAddUser);
exports.deleteUser = functions.auth.user().onDelete(onDeleteUser);
Update your rules to only allow reads for users with access > 1.
On the off chance the listener function doesn't disable the account fast enough then the read rules will prevent them from reading any data.
I believe once database rules are written accurately, it will be enough to protect your data. Moreover, there are guidelines that one can follow to structure your database accordingly. For example, making a UID node under users, and putting all under information under it. After that, you will need to implement a simple database rule as below
"rules": {
"users": {
"$uid": {
".read": "auth != null && auth.uid == $uid",
".write": "auth != null && auth.uid == $uid"
}
}
}
}
No other user will be able to read other users' data, moreover, domain policy will restrict requests coming from other domains.
One can read more about it on
Firebase Security rules
While the original question was answered (that the api key can be exposed - the protection of the data must be set from the DB rulles), I was also looking for a solution to restrict the access to specific parts of the DB.
So after reading this and some personal research about the possibilities, I came up with a slightly different approach to restrict data usage for unauthorised users:
I save my users in my DB too, under the same uid (and save the profile data in there). So i just set the db rules like this:
".read": "auth != null && root.child('/userdata/'+auth.uid+'/userRole').exists()",
".write": "auth != null && root.child('/userdata/'+auth.uid+'/userRole').exists()"
This way only a previous saved user can add new users in the DB so there is no way anyone without an account can do operations on DB.
Also adding new users is posible only if the user has a special role and edit only by admin or by that user itself (something like this):
"userdata": {
"$userId": {
".write": "$userId === auth.uid || root.child('/userdata/'+auth.uid+'/userRole').val() === 'superadmin'",
...
EXPOSURE OF API KEYS ISN'T A SECURITY RISK BUT ANYONE CAN PUT YOUR CREDENTIALS ON THEIR SITE.
Open api keys leads to attacks that can use a lot resources at firebase that will definitely cost your hard money.
You can always restrict you firebase project keys to domains / IP's.
https://console.cloud.google.com/apis/credentials/key
select your project Id and key and restrict it to Your Android/iOs/web App.
It is oky to include them, and special care is required only for Firebase ML or when using Firebase Authentication
API keys for Firebase are different from typical API keys:
Unlike how API keys are typically used, API keys for Firebase services are not used to control access to backend resources; that can only be done with Firebase Security Rules. Usually, you need to fastidiously guard API keys (for example, by using a vault service or setting the keys as environment variables); however, API keys for Firebase services are ok to include in code or checked-in config files.
Although API keys for Firebase services are safe to include in code, there are a few specific cases when you should enforce limits for your API key; for example, if you're using Firebase ML or using Firebase Authentication with the email/password sign-in method. Learn more about these cases later on this page.
For more informations, check the offical docs
I am making a blog website on github pages. I got an idea to embbed comments in the end of every blog page. I understand how firebase get and gives you data.
I have tested many times with project and even using console. I am totally disagree the saying vlit is vulnerable.
Believe me there is no issue of showing your api key publically if you have followed privacy steps recommend by firebase.
Go to https://console.developers.google.com/apis
and perfrom a security steup.
You should not expose this info. in public, specially api keys.
It may lead to a privacy leak.
Before making the website public you should hide it. You can do it in 2 or more ways
Complex coding/hiding
Simply put firebase SDK codes at bottom of your website or app thus firebase automatically does all works. you don't need to put API keys anywhere

Insecure Firestore rules and App Check - the right way to go for unauthenticated database access? [duplicate]

This question already has answers here:
What is the purpose of Firebase AppCheck?
(3 answers)
Does Firebase App Check discard the need for implementing Security Rules?
(1 answer)
Closed 6 months ago.
I have built an app (Android/iOS) using Flutter that allows its users to configure the app to receive a daily notification. Users can also submit a textfield. There is no requirement for users to register and authenticate.
I am using Firestore to store data from the app.
I have architected the app so that the Firestore rules allow any access:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}
To prevent anyone accessing my app's Firestore instance, I have implemented App Check, and Enforcement is enabled.
I have begun to get messages from Google '[Firebase] Your Cloud Firestore database has insecure rules'.
Can anyone advise:
Should I ignore the warnings from Google?
Must I implement user registration and authentiation when it's not necessary for the app?
Should I architect my app in a different way?
Should I do something else?
Thanks,
Luke
Should I ignore the warnings from Google?
Ignoring the warning is not recommended as it may cause security issues.
If you're allowing anyone to access database, then they can take advantage and modify, or delete your data. And your database remain unsecured
2.Must I implement user registration and authentiation when it's not necessary for the app?
If it is not necessary for authenticating user for your application then you can apply some validation rules to restrict certain database nodes or you can permit role based access. In this way you can reduce security issues.
#samthecodingman has given excellent details about number of ways to tighten up database to prevent security issues in similar thread

Firebase/Firestore - database has insecure rules?

I have a SwiftUI application, which uses Firebase as a back end, and my rules are something like this:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// This rule allows anyone on the internet to view, edit, and delete
// all data in your Firestore database. It is useful for getting
// started, but it is configured to expire after 30 days because it
// leaves your app open to attackers. At that time, all client
// requests to your Firestore database will be denied.
//
// Make sure to write security rules for your app before that time, or else
// your app will lose access to your Firestore database
match /{document=**} {
allow read, write: if request.time < timestamp.date(2020, 10, 28);
}
}
}
I understand that these rules allow anyone to read and write to the database. However, as long as they are only using the API provided to the them in the application, how is this insecure? For instance, I could understand the danger, if, say, someone took the xcode project from my laptop and created a button that deleted all users in the database. But, no one will have access to this code.
I do want users to be able to read and write to/from the database, so I was just wondering if these rules are insecure, and, if so why? Like what is an example of how a hacker with malicious intent could exploit these rules to gain unauthorized access to user information and/or somehow modify the database in a way that the API provided in my application does not allow?
Thank you.
as long as they are only using the API provided to the them in the application
This is precisely the problem.
Your app contains all the configuration needed to connect to the database (and other resources in your Firebase project). A malicious user can take this configuration data, and call the API themselves - thus bypassing any of your client-side logic.
While you can configure Firebase App Check to help only allow access to the database is coming from your code, that is no guarantee and somebody else's might still use their code with your configuration data.
That's why it's crucial that you also encode your business logic in your security rules. Say that your application code only allows the user to delete their own account from the database, you'll then also want to encode that logic in your security rules so that they're enforced on the server. This is a variation of what the Firebase documentation on securing your database describes as content-owner only access.

Security of Firestore Database - SwiftUI

I have a very simple Firestore database for a game I creating. I have a User collection which has documents, each of which specifies a user's username, their email, and their high score.
I would like everyone to be able to read the high score and username's of everyone in the database, since I have a list that lists every user's high score and username.
However, I would only like individuals to be able to write the database (i.e. submit their own high score), if they are logged in.
Thus, I have the following security rules:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
match /Users/{document=**} {
allow read: if true;
}
}
}
My question is, is this secure? I guess this means that technically a user with malicious intent could read the emails of every user. Is there a way to prevent this by somehow specify that only everyone should be able to read the highscore and username properties of each User document?
Also, this set up does prevent malicious users from writing to the database, correct (edit here: I guess this doesn't - I'm looking into this now by reading the docs here https://firebase.google.com/docs/firestore/security/rules-structure)
I'm not new to Firebase but I am new to it's security rules, since I haven't pushed an application to production before and would like to make sure I don't leave anything vulnerable, so any feedback/guidance here is appreciated.
As I explained on your previous question, anyone can take the configuration data from your app, and call the Firebase APIs with that data.
is this secure?
Only you can determine whether your rules are correct for your use-case.
These rules allow anyone to read all documents in the /Users collection. In addition they allow any authenticated user to read and write all documents. If that is the use-case you want to support, the these are the correct rules for you.
So if you've enabled the anonymous authentication provider in Firebase Authentication, anyone can take you configuration data, write a minimal web page and call firebase.auth().signInAnonymously() and then read all user data with firebase.firestore().collection("Users").get().
Securing your database is going to be hard to learn in this question and answer style. I instead recommend you:
Read the Firebase guide on security rules.
Doug's video introduction to security rules.
Watch the series Getting to know Cloud Firestore, and pay special attention to the episode on security rules.
The video Unit testing security rules with the Firebase Emulator Suite and its follow up Intermediate topics in Firebase Security Rules.
The pro-series episode How to build a secure app in Firebase.
The article Patterns for security with Firebase: combine rules with Cloud Functions for more flexibility

Is it possible to access Firebase data before creating a new user? (Swift)

Before creating my new user, I would like to check Firebase to see if the username already exists in the database. I would like to do this right after the user has finished editing the username textfield (the rest of my form will not be complete). I've attempted to access the Firebase DB, but I get the warning "Listener at /Users failed: permission_denied". From what I understand, in order to read/write to/from the Firebase DB the user must be authenticated, and obviously a user signing up isn't authenticated before they've signed up. Is there any way to access the database before running the createUserWithEmail:password:completion: method?
To be clear, let me say up front that I do NOT recommend you do this for your use case. But in general, you can allow unauthenticated users to access parts of the database by setting your security rules for that path to true:
{
"rules": {
".read": true,
".write": true
}
}
You would not want to do something like this because you don't want to give the public access to everyone's usernames.
Instead, I'd recommend using Cloud Functions for Firebase. You can create a Cloud Function that is triggered when a user chooses a username, perhaps by creating a temporary path in the database and using a database trigger. Now if you're not familiar with Cloud Functions or Node.js, there will be a lot of new information to learn up front, but you will discover that there are many use cases for Functions, so it's worth learning.
Here are some resources to check out:
Get Started
Cloud Functions Database Triggers
Cloud Functions Documentation