I need help understanding the correct and secure way to handle wallet updates in a Kodular app using Firebase Realtime Database. I believe my current approach works functionally, but I also understand that all clients are untrusted, so I want to redesign this part properly.
Please assume I am not yet experienced with role-based security, and I want to learn the right architecture.
My Current Situation
Backend: Firebase Realtime Database
Auth: Firebase Authentication
Networking: Web component (REST API)
Everything runs from the client side
As of now
A user makes a deposit using a payment aggregator API
The API responds with success
The same user app then updates their own wallet balance in Firebase
This works, but I now realize this is not secure, because,
The client can be modified
API responses can be replayed or faked
Users should not be allowed to update their own wallet
What I Want to Achieve
I want a much more secure model, where,
Users,
Can sign up and sign in
Can submit a deposit request
Can see their wallet balance
Cannot update wallet balance
Admin,
Uses a separate Admin App (same Firebase project)
Reviews pending deposit requests
Confirms deposits
Updates user wallet balance
Wallet:
Is read-only for users
Is writable only by admins
What Confuses Me
This is where I’m stuck conceptually,
If I set Firebase Rules so that wallet is read-only, then:
How does the admin update the wallet?
If both apps use the same Firebase project, how does Firebase know who is a user and who is an admin?
How do I separate permissions without trusting the client app?
I’ve seen mentions of,
users/{uid}/role = "admin" | "user"
But I don’t understand,
How this role is assigned securely
How can I add automatically user role when user is signed up
How Firebase Rules use this role
How admin can write while user cannot
What I Am Looking For
I am asking for,
A simple explanation of how to separate user vs admin roles
The correct data structure for:
wallet
deposit requests
An example of Firebase Realtime Database rules where,
Users submit deposit requests
Admin updates wallet
Users cannot change wallet or role
Confirmation that this approach works with Kodular Web component
As of now
I am not using Cloud Functions for now
I understand that hiding URLs or UID is not security
My main concern is wallet manipulation
This is an MVP, but I want to avoid dangerous mistakes
Summary (My Core Question)
How do I design Firebase rules so that users can deposit and create pending requests, but only admins can update wallet balances, even though both apps use the same Firebase project and REST Web component?
Any guidance, examples, or explanations would be extremely helpful.
I believe everything can be solved by setting the correct rules for your RTDB.
(I should mention that I don’t know if this is the most efficient method, but I used it before in an old project and it works well)
You could create an admins node containing a dictionary of admin UUIDs and set rules that allow only them to modify a specific node, while making it read-only for everyone else.
With these rules, only an admin with boolean true in “admis” can write in the deposits nodes,
while a logged-in non-admin user can only read their own node.
In this case, the user with UUID nvkdd7lD4IQJCvNo9cYyWoDtt8c2 is an admin and can read and write in all deposits nodes.
The user EP6Rmmr874eyv4Ak3RZ7D88XhFh2 can only read from its own node deposits/EP6Rmmr874eyv4Ak3RZ7D88XhFh2.
It’s not everything you asked for, but you can easily adapt it to what you’re trying to do.
Obviously, you’ll need to use an extension or the Web component to handle authenticated requests.
I understand, though am still not getting something at the moment, how must I differentiate user and admin when signing up? Must I stored the UUID’s in different nodes?
Is this structured generated when signing up?
Am using web component, is there any extension or any other way to hide my Firebase database URL? Most when user is performing any activities, eg there’s some tools available out there that can see how the app handle/send out going process and see the real URL.
How do you intend to grant permissions to a user to create an administrator account?
The idea in my old project was that an administrator had to be added manually in the admins section with a UUID = true pair.
You could use Cloud Functions that, by passing a password, automatically insert the UUID into the admins list, but that’s not very secure, it should be a step handled on the backend, not the frontend.
Why do you need to hide it? If your database has solid rules, you could even write it on the station walls
That’s where i still thinks its not more secured,
At first, my idea was this,
Let’s assume there are two apps,
App A → Client (user) app
App B → Admin app
My initial thought was that when a user registers from App A, the app would automatically assign the role user, and when someone registers from App B, the app would automatically assign the role admin. Is this possible?
There some network traffic interceptors these capture all HTTP/HTTPS requests that my app makes. Eg Charles Proxy, Burp Suite, MITMproxy, Wireshark etc,
It really depends on how you want to proceed,whether you want to do it the correct way or if you just need something that works.
You could use my method and, with the admin app, register the new account retrieve the uuid, log in with a service account that is already an admin, write the pair uuid = true, then log in again with the new account, which will now be recognized as an admin.
Realtime Database works through rules or custom tokens, I don’t think it’s possible to distinguish access just via appId, and implementing access with custom tokens makes things quite a bit more complicated.
With the rules set correctly, it won’t be possible for you, since to write you will need to be an admin and when you try to register as an admin, the account will not yet exist.
Ideally, one administrator should be able to register another, so you’ll need at least one admin.
You can expose your URL and API key; that’s not a problem if the rules are correct (a user will need to be authenticated and have a token); otherwise, they won’t be able to do anything.
Hey @Joe90 can you explain more, maybe I didn’t explain well, but at least u get what I want. I have tried different ways but still nothing seems done so far. Maybe i should add them manually.