I have made my mobile app using firebase on iOS & I use callable functions to communicate with database.
When I try to perform a “man in the middle” attack/move using a simple app as Charles, I can see all my calls with the data I send, in plain text. When I use a well know app like iTunes I cannot decrypt anything (which I think is what we call ssl pinning)
I have 3 questions:
does firebase cloud functions (https.callable) handle ssl pinning ?
if not how can I protect from this ? Using node for my function, is it possible to request a ssl certificate from firebase and link it to functions ?
Does the mobile Sdk request are pinned ? I cannot see anything about read calls on my sniffing app.
Thank you all.
As per this post here by Doug, all data in and out of Google is encrypted (including the client SDKs). There is simply no way around this.
Now, you can take this a step further and prevent abuse by configuring App Check which, according to the documentation, provides an additional layer of security against billing fraud and phishing.
However, you will still need to check the authentication token (automatically passed in with onCall functions) to make sure the user is authorized to execute the functions they are calling.
Related
Disclaimer: I am new to mobile app development and have little to no knowledge on authentication systems
Normally, when my mobile app makes https calls to my backend server, I know that I cannot trust that these calls to my server came from my app, as anyone can make https requests to my backend server. Even if I give the app a secret key, it is still possible for a hacker to obtain the key and include it in https requests. Therefore, I will not allow https requests to accomplish whatever it wants on the server; rather, I will limit the request to doing only what a user can normally do with their own data – delete their OWN posts, edit their OWN profile, and so on.
Does Firebase work the same way? I saw this StackOverflow thread regarding OAuth consumer secrets, and how they can be compromised and used to imitate a mobile app.
Is this also the case for Firebase?
Can a malicious user theoretically obtain whatever keys/secrets Firebase gave to my mobile app, and use that to emulate requests from my app to Firebase? For example, could they create new users and cause de-syncing issues with my own backend database?
If so, how can I prevent it?
Thanks.
Does Firebase work the same way?
Firebase works in whatever way you program it. Normally you do not put private keys in software that you distribute to end users. The recommended approach is documented very well - use Firebase Auth ID tokens to indicate who is making the call, and use code on your backend to figure out if they should be able to do the work they are requesting. This is what happens with direct database access from your app, but you have to write security rules to protect data according to your requirements.
If you are passing tokens yourself to your own backend, it is up to you to revoke any refresh tokens that you find to be compromised. You cannot fully stop hackers from compromising a system that stores user tokens on devices that you don't control. All you can do is make it hard for them to do so.
Can a malicious user theoretically obtain whatever keys/secrets Firebase gave to my mobile app
Yes, that's why you don't put secrets in code that you distribute to end users. The Firebase config that you're asked to add to your app is not considered private.
See also:
Is it safe to expose Firebase apiKey to the public?
I have a desktop app that will be distributed to users, and part of its code (which the user might be able to access) has to perform an API call to a third-party web service. However, this requires the API keys to be embedded into the source code, which causes some obvious security issues.
The main solution I've found while researching on the subject is to have a backend server between the user and the third-party API endpoint. So, I've been looking into Firebase for a while and it seems that this solution can be implemented using Firestore and Cloud Functions.
But, I wasn't able to find any clear examples that achieve something like this, and since I have no previous experience with Firebase or just backend programming in general, I would like to know if I'm on the right track and get more details about how to get it done, or if there are better alternatives for solving this issue. Any input is appreciated, thx.
You can use the firebase cloud functions as you mentioned. Your desktop application will be communicating with the cloud function - simple API call. Here you can find examples how to implement and deploy functions and test it locally https://firebase.google.com/docs/functions/get-started. Your cloud function will hold the API keys (it is backend so it will be secure if you dont expose it explicitly. Also the backend to backend communication is considered as secure). Finally, this cloud function will call the third party service and return some data back to the desktop app if needed. So you are on the right track, that is how the design should look like. If you need some help with cloud functions, you can also contact me directly.
I need to implement a scenario where, after a file is uploaded to Google Cloud Storage, a function is triggered and processes the file. In this case, processing basically means sanitizing the file, storing it into Firestore and making it accessible via another HTTP-triggered function (a REST API of sorts).
Both user-facing ends of this process (a file upload and HTTP function) need to be secured. The process will be used in server-to-server scenario: one side is going to be a backend written in either Node.js or .NET, the other will be my Firebase solution (Cloud Storage and HTTP-triggered function as per above). In Firebase, I am going to maintain a custom set of users that should have access to the system - my idea was to use a simple system where each user will have a client id and a client secret (basically an oAuth client credentials grant type).
Based on what I read online, an only option to implement this is to use [Firebase auth with custom tokens][1]. I found lots of examples online on how to do that, but it was always about client-to-server scenarios (e.g. a Javascript web app talking to REST API). Server-to-server scenarios were not mentioned anywhere and indeed, I am unsure how to go about implementing it - I can call auth.createCustomToken(uid) just fine in my HTTP Firestore function, but there seem to be no server-side libraries I could use to call auth.SignInWithCustomTokenAsync(customToken).
To sum it up:
How can I use Firebase auth with custom tokens in server-to-server
scenario, where I need to sign in using a previously generated
custom token from a server environment?
If it is not possible,
what's the other alternative to securely implement the
above-described architecture?
I've contacted Google Support and if anyone else is struggling with this, in server-side scenarios, recommended approach is to call signInWithCustomToken endpoint in Firebase Auth REST API.
So now that we can call HTTPS functions directly from client side, I'm wondering if I can use it for sensitive transactional requests and if it's safe. Before I was using forms with POST method but this could make things much simpler.
Is the call from the beginning to the end encrypted?
It may not be obvious at first, but you're asking a lot of questions here. It may take some time to unwind your concerns
First of all, both Cloud Functions HTTPS functions and callable functions are encrypted. In fact, all traffic in and out of Google is encrypted. That is the norm, and you can't even disable that if you wanted to. However, encrypted traffic doesn't necessarily mean that it's "safe". Encryption just guarantees that there can be no man-in-the-middle attacks that are eavesdropping or changing the content on the way in or out.
Encryption doesn't prevent someone from simply invoking the function directly from their own code. For HTTPS and callable functions, it's very much possible for anyone to invoke your function directly. There are no requirements that the call must be coming from your app or your web site. If this is a requirement for you, you need to perform some checks in your function itself to ensure that the call is valid.
With HTTP type functions, you can require that the caller send an authentication token with the request. Then, you can validate the token in your function, and proceed only if everything looks OK to you. There is an example of this in the official samples.
With callable type functions, an authentication token is automatically added if the user is logged in with Firebase Auth. The token is automatically validated as well. All you have to do is check to see if the user is allowed to do whatever it is the call wants to do.
"Safety" is not just about encryption. It includes both authentication and authorization as well.
The documentation you refer to explicitly mentions that Callable Functions are HTTPS ones, so yes the call is encrypted from end-to-end.
The Cloud Functions for Firebase client SDKs let you call functions
directly from a Firebase app. To call a function from your app in this
way, write and deploy an HTTPS Callable function in Cloud Functions,
and then add client logic to call the function from your app.
I'm building a React+Redux app, and using some firebase cloud functions which I call in an action creator. I was wondering, if I should save the cloud function url as an environment variable, since this code is on the client side? I already have cors implemented to only allow requestsfrom my domain.
Thank you
In general, you should always make sure that endpoints that can be called from a client are robust enough to be secure if publicly disclosed. Browser, Android, and iOS apps can all be inspected and disassembled to discover outgoing request URLs.
"Security through obscurity" can buy you time, but is not in and of itself a real means of protecting your application. Instead, you should make sure that the endpoint requires sufficient authorization (e.g. by using the Firebase ID token as per this sample).
In other words, there's no need to hide it because at the end of the day, you can't!