Is it safe if I turn all my security rules of firebase storage to read and write by all? - node.js

I have been trying for quite some time to develop an authentication system using firebase/auth, however this has yielded unsatisfactory results and I have noticed then whenever I log a user in the website, then I access the website from another device I can see all the data of the previous user, without needing to logIn at all. I have researched online on how to solve this however even after having done everything the firebase docs are saying, I still encounter the same problem. I can't leave it like this since it is of course a HUGE security risk. So I took the matters to my own hands and created an authentication system with json-web-tokens, this works very well, however due to my configurations of the firebase storage security rules It is impossible for me to access the data since I am not logged in with firebase/auth.
I have done my best not to show any links or configuration to my account in firebase, all images are fetched and converted to base64 in the server-side then later rendered on the page, so if I keep my firebase configurations hidden and I dont show any firebase storage links on my website is it safe for me to allow read and write without checking for the user to have been logged in using firebase/auth
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}

If all access to the files in Cloud Storage comes from the Node.js SDK, it bypasses the security rules that you set anyway. So in that case, you might as well disallow all access:
allow read, write: if false;

Yes, this can be very dangerous.
To find your configuration is easily done, since they need to be public for your connection to even work on your frontend.
If someone wants to find your config, they can. This is why security rules are very important and you should not allow everyone to access your database.
Based on your current security rules:
If someone gain access of your config, They can simply register an account and then delete your entire database with a few lines of code
If you only communicate with Firebase via a service account on a server. i.e. you are not using the web SDK, you can disable it like this:
Go to Firebase console > Project settings > General
At the bottom of the page you will see your active web apps.
Select the on you want to disable and choose Remove this app
Now noone can access your app via the web SDK

Related

Is it safe to put in secrets inside Google App Script code?

I'm creating a Google Workspace Add-On and need to make some requests using OAuth. They provide a guide here explaining how to do so. In the sample code, it's suggested that the OAuth client secret be inline:
function getOAuthService() {
return OAuth2.createService('SERVICE_NAME')
.setAuthorizationBaseUrl('SERVICE_AUTH_URL')
.setTokenUrl('SERVICE_AUTH_TOKEN_URL')
.setClientId('CLIENT_ID')
.setClientSecret('CLIENT_SECRET')
.setScope('SERVICE_SCOPE_REQUESTS')
.setCallbackFunction('authCallback')
.setCache(CacheService.getUserCache())
.setPropertyStore(PropertiesService.getUserProperties());
}
Is this safe for me to do?
I don't know how Google App Script is architected so I don't have details on where and how the code is being run.
Most likely it is safe since the script is only accessible to the script owner and Workspace Admins if it is for Google workspace (which may or may not be an issue).
Well, you can add some security/safety by making use of a container, by using Container-bound script which makes use of Google Spreadsheet, Google Doc or any other that allows user interaction. Or a standalone script but also makes use of other way to connect to UI for interaction. Refer to this link for more detailed explanation on that: What is the appropriate way to manage API secrets within a Google Apps script?
Otherwise, the only way I see that you can do is store the keys and secrets in User Properties. Here's how you can do it: Storing API Keys and secrets in Google AppScript user property
Also you can refer to this link below for more general information on how you can manage or add some security: https://softwareengineering.stackexchange.com/questions/205606/strategy-for-keeping-secret-info-such-as-api-keys-out-of-source-control

How could I secure this API?

I'm building a full-stack application with Next-JS. I'm building an API that works with Firebase. I was wondering if there is a way to make this API secure.
Let me elaborate. There is an option to your account called Premium. This variable is stored in the Firestore and will determine if you have purchased a Premium membership. This will determine whether or not you have access to certain features. I will use an API to change this variable.
I had the following in mind:
Have a button on the page to upgrade account.
Button pressed? Call to the API with the following params: email, upgrade to. This is because the same function can also be used to downgrade an account, for example when the user doesn't pay for the upgrade.
That API function changes the variable in the Firestore. It returns a status and a message.
I want to make option 2 more secure because otherwise, it would allow anyone to change the premium variable. That is obviously not what I want. Is there anything I can do about that? For example, a token system, the thing with that is that I have been thinking about that and I don't really know how to implement that and how it would work exactly.
For anyone wondering why I am using an API: I will also be creating an app, probably with react-native. The user will also be able to change their account status and interact with the API to do other stuff in that app.
Thanks for reading and responding! I hope this is at least a bit clear. If you have any questions, please comment them.
I do similar things in my app. I use Cloud Functions (which operate in a secure environment) to both save settings in Security-Rules -protected tables, as well as setting Custom Claims in the users Auth profile. All authorizations are then verified in the Cloud Functions before any changes are made - You may need to "seed" some values in a protected collection/document from the Console to get the process started.

Generating download URLs for storage

I have a few questions regarding firebase storage?
I am generating download URLs for firebase storage objects using and admin account (has custom claims) and storing the URL on Firestore.
Users can read the Firestore document to get the URL instead of having to call getDownloadUrl on the client side code.
Q1) I noticed there is a token at the end of the storage URLs. Is this specific to my admin account and is it safe that none admin users can now read this token?
Q2) Furthermore if a non admin user called getDownloadUrl on the same storage path would they receive the same URL as the admin account or a different one?
Q3) If I switch to using getDownloadUrl on the client side would this increase my cost when using firebase storage?
Q4) If i am caching the content by URL and the URL changes it will redownload and not use cache.. Are these download links unique or can getDownloadURL return different URLs on subsequent calls?
Thanks a lot
Edit ---
Sorry I have an additional question
Q5)To move files on firebase storage I currently download them to my local pc and reupload them to another location -- seems very inefficient.
I have seem people using file.move() (as can be seen here.)
Would this be possible to call in a firebase function (as they talk storage rules being an issue in the comments, although its from 2016) and if so how would this be cheaper than my manual download and upload?
Sorry for many questions :)
Q1) I noticed there is a token at the end of the storage URLs. Is this specific to my admin account and is it safe that none admin users can now read this token?
This token is a a random ID generated for this specific file. It won't change, unless you change it intentionally (you can "revoke" the token from the Firebase Console, which will replace it with a new token). Everyone who possesses the URL can view the file whether they are authenticated or not. However, the URL is "hard to guess", so unless you share it with anyone, it will stay secret, practically speaking.
Q2) Furthermore if a non admin user called getDownloadUrl on the same storage path would they receive the same URL as the admin account or a different one?
The returned URL will always be the same, unless you invalidate it in the Firebase Console. If you don't want clients to call getDownloadURL on the files, add a Storage Security Rule that denies reads:
match /path/to/{file} {
allow read: if false;
// Or, if only authed users should be able to call getDownloadURL:
allow read: if request.auth != null;
}
Q3) If I switch to using getDownloadUrl on the client side would this increase my cost when using firebase storage?
A call to getDownloadUrl() does utilize some Google Cloud resources that you will have to pay for, whether you do it server-side or client-side. It's a "Class B" operation (check Google Cloud pricing), and a bit of data transfer.
Q4) If i am caching the content by URL and the URL changes it will redownload and not use cache.. Are these download links unique or can getDownloadURL return different URLs on subsequent calls?
The same URL is return each time, unless you manually invalidate the token. (By the way, the caching policy that sets the Cache-Control header is set on the object as metadata when you upload it.)
Q5) To move files on firebase storage I currently download them to my local pc and reupload them to another location -- seems very inefficient. [..] Would this be possible to call in a firebase function
Yes, you can move files in a Firebase Cloud Function. The Firebase Admin SDKs bypasses security rules.
1) I noticed there is a token at the end of the storage URLs. Is this specific to my admin account and is it safe that none admin users can now read this token?
Depends on what you have at the moment since you can integrate Custom Authentication with Firebase which will allow you to create custom tokens that can be used to sign into the Firebase Authentication service on a client application and assume the identity described by the token’s claim. This can be used when accessing other Firebase services, such as Cloud Storage, etc.
In general your server should create a custom token with a unique identifier.
2) Furthermore if a non admin user called getDownloadUrl on the same storage path would they receive the same URL as the admin account or a different one?
Depends on how you are setting the permissions for the getDownloadUrl. If you have a customized one they can receive a different one but usually it returns a new instance that points to the current reference.
3) If I switch to using getDownloadUrl on the client side would this increase my cost when using firebase storage?
I am not sure about this, I have checked the documentation and there is nothing that would indicate a quota or pricing on this specific method so I would go ahead and assume that it would not do it but I might be wrong on this one.
4) If i am caching the content by URL and the URL changes it will redownload and not use cache.. Are these download links unique or can getDownloadURL return different URLs on subsequent calls?
As specified before, it returns a new instance that points to the current reference so these download links are unique.
5) To move files on firebase storage I currently download them to my local pc and reupload them to another location -- seems very inefficient.
For this question and the last part of your initial post I would suggest you to create a support ticket and ask more details to the Firebase Support Team where you can get more information regarding this since it is more suited for them than to StackOverflow. (https://firebase.google.com/support)

Azure Download for specific Users

Project ASP.NET
I will use Azure for my storage. Questions (requirements):
In my project I let my registered users download files. But I don't want the user to share this download link to unregistered people (example : the download link what I gave the registered user shall only be downloadable on their computer) .
I show only for registered users the download link, the registered users can download the files that I gave them
No one can delete my files
Question 1: This is really up to your app but... if you're giving direct links to blobs in Azure Storage, you would need to protect them with a Shared Access Signature (or policy). This way, you can give someone a link that expires (for example, 10 minutes after you issue the link). Then, if someone gives away the link, it won't work for very long. There's no way to limit a link's use to a specific computer. Now, if you simply stream content from blob to your app, and then from your app to the user, you will probably have a bit more control, since you wouldn't really be generating a reusable link. But this will have downsides (such as running all content through your web tier, requiring more resources in your web tier).
Question 2: This is completely up to your app, how you manage assets and present them to a registered user. No way to answer this for you, since we know nothing about your app.
Question 3: Azure Storage is accessible by a secret key, which should stay secret, and only you should ever have access to it (for example, it would be used by your code on the server). As long as you don't publish this key anywhere, then nobody would be able to delete your content.

Is it okay to store database creds in Angular files for production apps? [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

Resources