At first, I thought the advantage was being able to call HttpsCallables, but now I know that you can call these with some special format and parameters from Postman (and it is also possible using UnityWebRequest, and if not, could just change them from onCall to onRequest).
Then, I thought that it might include some special authorization info from the client to the server. But context.auth (from https.onCall(data, context)) appears to be undefined. Plus, I can still call the functions from Postman.
Important note: I am not registering users, so I don't need Firebase Auth specifically. But I imagined Firebase added something to verify that the function call was coming from an authorized client (e.g. the app).
I am still using the Functions SDK, but I am wondering, what are the advantages of using this SDK for Unity, when UnityWebRequest exists? Why should I have an package when I can perform the same call using a UnityWebRequest? Am I missing something too obvious?
Additional information of how I am using Firebase Functions:
I have a level editor where people can contribute with levels. I use a function to add these levels to Firestore.
When these levels are created, a database trigger runs and checks if that level was already created.
Getting levels from the database to replay.
Finally, in the future I plan to create a voting system to help me curate the levels.
Auth state should be passed along from the Firebase Functions client to your callable Cloud Functions automatically. If that is not the case, I'd report that as a bug.
But outside of that: there's indeed nothing the SDK does that you can't also do yourself. Using it is a matter of choosing between greater convenience and more fine grained control.
If you use the Firebase-provided SDK, you won't have to build anything yourself. But on the other hand, if you build your own client-side implementation of the wire protocols, you have full control over what you do, and don't, implement.
Related
Firebase Analytics question: is it possible to duplicate events/payloads to another endpoint besides the Firebase's own? Let's say GTM server side or something completely custom.
I know it can be done with the Measurement Protocol-based implementation but what about any of the SDKs?
Thanks!
It can be done easily with wrappers. Wrapping compiled SDKs is a very simple way to extend their functionality. The idea here is that you don't use your SDKs directly from the code. Instead, you're making quick wrapping classes that import the SDKs in question and mirror the SDKs' functions with their own. Now, from the code, you only use the mirrors and you only import your class rather than the SDK.
Then, you can extend your wrapper to a great extent, making your .send() function to also sanitize payloads, normalize data, send it to wherever else you want it in.
There's just no need for the core sdk to allow something that is so easily achieved with wrappers, especially considering that wrappers usage is considered a very good practice and I often see them in place with various analytics SDKs even when analysts failed to request them.
Again, if MP is implemented via a compiled SDK, then you're facing the same problem.
I already use ReCAPTCHA for Android apps client-side (I've also implemented, of course, its server-side verification).
However, this ReCAPTCHA is implemented only in one activity. But, of course, hackers can modify the app. For example:
they can simply remove ReCAPTCHA from all activities,
or start another activity that would not have ReCAPTCHA implemented; it's the case btw: I didn't implement ReCAPTCHA in each activity because it's useless according to the first problem I've just mentioned.
So I would want to detect bot and spam requests in Cloud Functions, then in Cloud Firestore, then in Cloud Storage, for the following accesses: read, write, function call. It'd allow me to prevent unwanted contents from being saved in Firestore for example (spamming messages, etc.), and to avoid overreaching my monthly billing quota (because of spam requests to Firestore for example).
Is it possible? How?
There is no "spam detection" for these products. Your security rules will determine who can access what data. If you don't have security rules in place, and allow public access, then anyone will be able to get that data, and you will be charged for it when that happens. This is the nature of publicly accessible cloud services.
If you want more control over the data in these products, you could stop all direct public access with security rules, and force clients to go through a backend you control. The backend could try to apply some logic to determine if it's "spam", by whatever criteria you determine. There is no simple algorithm for this - you will need to define what "spam" means, and reject the request if it meets you criteria.
Google does have some amount of abuse detection for its cloud products, but it will likely take a lot of abuse to trigger an alert. If you suspect abusive behavior, be sure to collect information and send that to Firebase support for assistance.
Just thought I'd add that there is another way to restrict access to Cloud Functions.
Doug already described Way 1, where you write the access logic within the cloud function. In that case, the function still gets invoked, but which code path is taken is up to your logic.
Way 2 is that you can set a function to be "private" so that it can't be invoked except by registered users (you decide on permissions). In this case, unauthenticated requests are denied and the function is not invoked at all.
Way 2 works because every Firebase project is also a Google Cloud Platform project, and GCP offers this functionality. Here are the relevant references to (a) Configuring functions as public/private, and then (b) authenticating end-users to your functions.
I want to migrate my iOS app from CloudKit to Firestore. Most of the architectural changes are simple, but there is one caveat that I do not understand how to overcome.
In CloudKit, I can save a change token on the client and pass it to CloudKit functions when fetching or saving data. During fetch, it ensures that I receive only those updates, which I did not previously receive. During save, unless my change token corresponds to the latest available one, the operation fails until I perform a fetch first. In my case, this design is ideal.
Unfortunately, it seems like such functionality is not available out of the box in Firestore. For example, when attaching a listener to document snapshot, there is no way to tell Firestore "Here is a token X corresponding to the last update which I have and I want to receive all updates following it".
I could theoretically implement the change token functionality myself using cloud functions. The issue, however, is that two devices can try to perform an update simultaneously and I would need to find a way to ensure that one of these updates is executed in full before the other one starts (so that one of them fails with "invalid change token").
It sounds to me like a common design pattern, but I am struggling to find any ideas as to how to implement it correctly in Firebase.
Hence, I would like to ask you for suggestions on how I should proceed with migrating the "change token" functionality from CloudKit to Firestore.
Note, I am making my first steps in backend development, so my terminology is far from perfect.
I've looked at a few places, Including this post and the firebase panel
Is there no way to use these api's to secure these endpoints using an api key you create per client who uses your cloud functions?
I'm able to block every one putting a restriction on the Browser key, but I would like to create a new api key, and use that as a way to authenticate my endpoint for various clients.
Creating a new api key, and using that as a parameter in my query doesn't work (don't now if I'm doing anything wrong)
Is there a way to do this?
Option 1: handle authentication within the function
https://github.com/firebase/functions-samples/tree/master/authorized-https-endpoint
Adapt above to use clients/keys stored in firestore
Option 2: Use an an API Gateway
Google Cloud Endpoints (no direct support for functions yet, need to implement a proxy)
Apigee (higher cost, perhaps more than you need)
Azure API Management (lower entry cost + easy to implement as a facade for services hosted outside Azure)
there are more..
The above gateways are probably best for your use case in that the first two would let you keep everything within Google, albeit with more complexity/cost -- hopefully Endpoints will get support for functions soon. Azure would mean having part of your architecture outside Google, but looks like an easy way to achieve what your after (api key per client for your google cloud / firebase functions)
Here's a good walkthrough of implementing Azure API Management:
https://koukia.ca/a-microservices-implementation-journey-part-4-9c19a16385e9
Not to achieve what you are after, as far as firebase and GCP is concerned your clients is your specific business problem.
One way you could tackle this (with the little information that is provided);
You need somewhere to store a list of clients + their API key (I would use firestore)
For the endpoints you want to secure with a client-specific API key you can include a check to confirm the header exists and also exists in your firestore client record.
Considerations:
Depending on your expected traffic loads and the the number of firestore reads you'll be adding, you might want to double check this kind of solution will work for your budget.
Is the API-key type solution the only option you must go for? You Could probably get pretty far using the https://github.com/firebase/firebaseui-web and doing user checks in your function with no extra DB read required. If you go down this path most of the user signup/ emails / account creation logic is ready to go.
https://firebase.google.com/docs/auth/web/password-auth#before_you_begin
Curious to see what some other firebase users suggest.
I'm writing some Firebase Cloud Functions but I have need to hide a private key, including from Firebase project admins.
If I embedded this key into my source code and uploaded the code myself, would it be possible for anyone to retrieve the source code and thus the key? Either via Firebase or Google?
Many thanks
The code for your Cloud Functions is never accessible to users of your app.
It is however accessible for the collaborators on your Firebase project. See Get code from firebase console which I deployed earlier
I don't think there's any way to hide such configuration values from collaborators. Since they can see/deploy code, and the code needs access to this private key, they by definition have access to the key too.
Answering precisely to your question: Yes, they can.
The step by step to achieve that is relatively simple
Go into the GCP Functions page
Select the function you want to inspect
Click on source (From there you should be able to see all the files and the code used by that function), or;
Click on variables (From there you should see all environment variables used by your function)
If people being able to see env variables is problematic to you, here's a way to make things more secure:
You can build on what you already and start encrypting those keys before adding them to the codebase or the environment variables. After that, you can use an encryption service such as KMS to decrypt those keys at runtime. In KMS itself you can have a stricter policy in there, only allowing yourself and the function to access that service.
Another great service from GCP is Google's Secret Manager
Maybe setting an environmental variable:
Oficial Doc