I am developing a website that has a booking option. Users can look at the availability on my calendar and pay for a timeslot.
Here is my concern: Let's suppose the website uses PayPal, and I get verification for when the payment goes through... then the website will populate the database with the clients booking information and close that time slot on the schedule. Now, what if I were to just send information to the database. Suppose I modify the code on the client side and just send booking info to the database. Nothing is stored in the database to authenticate this update and so an appointment could be booked without payment. I believe this is possible and so I was wondering how I could secure it as to prevent this from happening.
I know this is a long question, but I really hope you understand what I am asking. If you have any suggestions please let me know!
Any security should always be done on the server. In the case where you have the client code write directly to the Firebase Realtime Database, you'll rely on security rules.
Typically you'll write a record about each verified payment into the database. E.g.
payments
user1: 15
user5: 25
The user1 and user5 keys above are the IDs of the users whose payment you recorded. Your users get this ID from Firebase Authentication.
Note that this write operation should be performed by a trusted our, so typically you yourself, a script that runs on a server you control, or on Cloud Functions.
Then when a user tries to write a booking to the database (say in /bookings/book123) you only allow the write if there is a payment from that user:
{
"rules": {
"bookings": {
"$bookingid": {
".write": "root.child('payments').child(auth.uid).val() > 10"
}
}
}
}
The auth.uid is the ID of the user performing the write. Firebase ensures that this is the actual user, and cannot be spoofed by someone (unless they know your Firebase Authentication private keys). The rules above this only allow a write from a user if they have a payment (or of more than 10).
Note that this is just a simple example. You may want to instead track payment/transaction IDs (from Paypal), and use those to synchronize up with writing of a booking with the receipt of a payment.
Related
I have this security concern with Firestore. The issue is could a malicious user for example inject data in to his document? Or even Worst having access to different collections? I know rules play a major part in here, but since I am creating docs/updating docs/deleting docs from front end could an abuse for crud happen in the context of the single user?
Also there is another part; I want to create a userSub collection (from front end) it will have a subscription info.
UserSub/uid
Premium: true
Enddate: 2 days form now
Could a malicious user get the uid from authContext and make crud ops to modify the mention doc in the collection to let’s say 10 days from now extending his sub? Since he knows what doc I am creating for those values (from source code in chrome)?
You must not allow users to update their subscription information from client. This should be done from backend only for example, if you use Stripe for payment, you should use their webhooks which would send subscription information to your backend/Cloud function that would update users subscription in your database or Firebase Auth custom claims.
You must ensure that this data is read only from users side using security rules if using database.
I build an event registration app which add all the participants in the a real time database.
The Database:
To secure my app I have used the security rules which only allow pushing data to the "participants",
I use JSON in order to create the register process.
I want to return some feedback to the client if she/he enter an email that has already been registered.
Can I do it without open a reading option on the "participants"?
So if I have an E-commerce App that doesn't require Login/Auth, and my users buy in the store, then after verifying the transaction the backend writes the order in the database.
The thing is that my Realtime Database just relies on Stripe transaction key (i.e, someone has paid for an item) to be able to write on the DB, because my rules are set so anyone can write, otherwise I would need every user to log in, but that's not what I want.
Firebase recently notified me that my rules are weak.
How can a make sure my users are able to write to my database in a secure way for my app, without log in/Auth?
There are many different security models you can use with Firebase, and it's important to understand the level of security each provides.
One thing to look into is anonymous auth which lets you "authenticate" a user without actually requiring them to provide any credentials. This provides a way to guarantee that the same device is being used between multiple reads/writes.
In your specific case, it sounds like you might be looking to rely on unguessable tokens. This can be a valid security model for some use cases so long as the key is sufficiently complex as to be unguessable.
At its most basic, the way you'd structure security rules for unguessable URLs is something like:
{
"rules": {
"transactions": {
"$key": {
".read": true,
".write": true
}
}
}
}
This allows users to read/write specific nodes at e.g. transactions/abc123xyzunguessable but importantly does not allow reading/writing to the parent transactions node. Security comes from the fact that only the person who originally got the unguessable token will be able to provide it again in the future.
A better implementation would gate writing on the $key matching the expected unguessable format, adding validation and other read/write rules to ensure that the data is formatted appropriately, and probably also prevent modification of key fields.
These are just some pointers but should help you on your way. The important thing is to make sure that you never leave important information in a place where it can be read through easily guessable URLs.
There is no "secure" way to allow writes to Realtime Database without Firebase Authentication. Without Firebase Auth, either there is full public access, or there is no public access at all.
If you can't use Firebase Auth, what you will need to do instead is make your security rules disallow all direct access to the database from client applications, then create backend APIs to manage access to the database. Your backend APIs will need to somehow validate that the person making the request should have the ability to make the required changes. Then, it will have to use the Firebase Admin SDK to commit those changes to the database.
Our app allows authenticated users to send and receive digital coins from each other in the app. Each user has a coins field which stores the current coin balance of a user. To transfer coins, we use firestore transactions at the sender's end to subtract the value of coins from the sender and then add the value to the receiver's balance. Hence, while the sender is logged in, they have to make writes to the receiver's document. This approach is insecure since we only check if the sender is logged in. This enables any authenticated user to have write access to another user's document.
Is there a much better/secure approach to implement such kind of transactions between users and is it possible to handle the problem only using firestore security rules in this situation?
In this scenario, you wouldn't want to give users write access to each other user's documents, or even their own "wallets". Doing this type of transaction all in the client side (e.g. using Firestore iOS/Android/Web SDK) will likely cause security issues down in the road. Of course, not many users will be aware of it, but tech savvy users who finds out that they have write access to other users' Firestore documents as long as they are signed in, will start deducting and taking coins from other users' wallets.
You will probably need to setup a server, or a script which will use Firebase Admin API to run transaction that you are talking about, so that it will be done in a black box according to your users' point of view.
Once you have the server up and running, client side app will then need to make calls to the server, preferably with auth tokens (e.g. Firebase Auth User's token), and ask for the transaction to run.
I am integrating a payment gateway; this is the first time I am integrating payment gateway functionality to my system, I am using Authorised.Net for the payment gateway.
As I have successfully integrated it but I see the user has to enter the following values to purchase his item, and the transaction id is returned.
//post_values.Add("x_card_num", "4111111111111111");
//post_values.Add("x_card_num", CreditCard);
//post_values.Add("x_exp_date", "0115");
////post_values.Add("x_amount", "19.99");
////post_values.Add("x_amount", );
////post_values.Add("x_description", "Sample Transaction");
//post_values.Add("x_amount", txtAmout.Text);
//post_values.Add("x_description", txtDesc.Text);
////post_values.Add("x_first_name", "John");
////post_values.Add("x_last_name", "Doe");
////post_values.Add("x_address", "1234 Street");
////post_values.Add("x_state", "WA");
////post_values.Add("x_zip", "98004");
//post_values.Add("x_first_name", txtFName.Text);
//post_values.Add("x_last_name", txtFName.Text);
//post_values.Add("x_address", txtAddr.Text);
//post_values.Add("x_state", txtState.Text);
//post_values.Add("x_zip", txtZip.Text);
These values just fix his transaction and purchase of item, so my confusion is that if the web site owner put all this information into his database and made more transactions using his details, then what? Is it safe and secure, or something else happens that I could not figure out?
Here are some basic guidelines to follow:
Keep all information in your database except for the credit number. Never keep the credit number unless you feel that your encryption systems are safe.
Store Authorize.net successful or failed transactions
You need to create a transaction table where you will create a new line for each transaction, regardless of being the same user, or transaction result.
Encrypt some portions of the transaction: Address is good thing to encrypt. This will avoid identity theft if you ever get hacked.
Make sure all user passwords are hashed
Store the Web Site Database connection encrypted as well
Communicate with the database using only stored procedures. This should avoid SQL injection, if the stored procedures are built correctly.
This is how it is, website owner can put all the information into his database, if the transaction mode is present on the website, thats why I and I think most of others either do transactions from trusted sites or sites that redirect to some trusted gateway like paypal or authorize.net for financial transactions.
Thanks for the clarification. I'm currently working on a project that is using PayPal in this same manner. We store only the authorization code and transaction ID in our database.
In my opinion, the 30 seconds or so that the user will save by having their information stored isn't worth the risk associated with storing their information. If you're doing recurring transactions, the vendor will store the information securely for you (at least PayPal does) so there's no real reason to store the credit card information in your system.
[EDIT] As Imran pointed out, storing the last 4 digits of the number would be fine for display on a report.
You can do nothing to prevent the DB owner from misusing the information if they're storing it aside from contacting your credit card company and reporting fraudulent charges. The payment gateway has no idea who is inputting the payment details, other than ensuring the transaction is coming from one of their authorized customers (i.e., the customer authorized to use the payment gateway).