Access URL Parameters In Firebase RTDB Security Rules - firebase

I want to read data from Firebase:
firebase.database().ref('videos/' + $videoId + '/data' ).once('value')
But in security rules I don't want to make this readable by anyone. Aka I do not want to use:
".read" : true
I want non-authenticated users to be able to read data if they have a special token, that they pass in the url.
firebase.database().ref('videos/' + $videoId + '/data?token=secretToken').once('value')
My video data looks like this:
{
vidoes: {
$videoId: {
data: {
...
}
tokens: {
secretToken: true
}
}
}
I imagine security rules would look something like this:
{
vidoes: {
$videoId: {
data: {
".read": "data.parent().child('tokens/' + auth.urlQuery('token').val() ).exist()"
}
}
}
Is there anyone I can access query string/ url parameters in Firbase security rules? I could use Firebase functions to create an api, but that is an extra step and network request.
Essentially it would behave like a "token" for Firebase storage:
https://firebasestorage.googleapis.com/v0/b/columbus-c4de8.appspot.com/o/richContent%2F1-min.jpeg_-LPgLxBMt1tBR0dDdNzH?alt=media&token=dfe24c92-e0c2-484a-81df-c09a710b3d34
If the token is correct, then user can read the data.
Note: It's technically possible to use tokens for ".write" security rules. See: Using newData on Updates in Firebase Security Rules

This is not possible, and is also not inherently secure. Firebase security rules would not be secure if anyone had a simple password that let them access data. It's pretty easy to reverse engineer a mobile client to extra the password that allows the query.
If you want to grant access to a query to a user, the only secure way to do that is in tandem with Firebase Authentication, which validates the identity of the person performing the request.

Related

connecting firebase Realtime database with chrome extension

I'm beginner and I'm developing a chrome extension that shows data received from my firebase realtime database. It does not need Login, or any personal information.
I'm trying to use REST API. Until now I have been in a test mode so I opened access to data for all. But Google keeps mailing me that I have to change the access rule because it is dangerous.
My present access rule is this:
{
"rules": {
".read": true,
".write": false
}
}
Now, I fetch data from https://<project name>.firebaseio.com/<database name>.json. But if I change the rule, the access will be denied.
So I want to add some key to the url and change access rule according to it so that I can fetch data from the url. For example,
https://<project name>.firebaseio.com/<database name>.json?some_key=<some_key>.
I do not need personal keys so I want only one key just like when we get information from open APIs. For example, when I use weather api, I get my api key from the host and adds the key to url.
Is this possible? If it is, I wonder two things.
the key that I can use (for example, realtime base wep API key)
access rule of realtime database
You can't pass parameters to the Firebase database like this:
https://<project name>.firebaseio.com/<database name>.json?some_key=<some_key>
But if you change the order of the values, it suddenly becomes possible:
https://<project name>.firebaseio.com/<some_key>/<database name>.json
We then change the security rules to only allow access when somebody already knows the secret key:
{
"rules": {
".write": false,
"$some_key": {
".read": true
}
}
}
Now the secret key is part of the path of the data, and only a user that already knows the key can read the data for that key.

Firebase validate rule. How to make the rules work?

Data in Firebase has the following structure:
emailsLending
|___-LqQFYK-iI8a8qe2msVk
|___email
|___serverTimestamp
I wrote the following rules checking the entry in the email field:
{
"rules": {
"emailsLending": {
"$emailsLending_id": {
".indexOn": "email",
"email": {
".validate": "newData.isString() && newData.val().matches(/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\\.[A-Z]{2,4}$/i)"
}
}
}
}
}
But when I write data to the email field using the Cloud Function, the rule does not apply and I can write anything, for example, "123".
What am I doing wrong?
Cloud Functions run with administrative privileges, and by default bypass the security rules of your database.
The logic here is that rules are to protect against malicious behavior from untrusted users, while Cloud Functions are authored by the most trusted users: collaborators on your app. To catch mistakes made by these types of users, you'd typically use unit tests instead of security rules.
If you have a case where this logic doesn't apply and you're using the Realtime Database, you can set databaseAuthVariableOverride to the UID of the user to run the code as. For an example of this, see the Firebase documentation on accessing user authentication information.

Best design pattern for public/sharable routes containing some sensitive data

A manager needs to make the team's schedule live/public. The main challenge I'm running into is my firebase db security rules require users to be logged it in order to read data from it. They sort of look like this:
{
"rules": {
.read:true,
.write:true
}
"profiles":{
".read": true,
".write": true
},
"$clinicId":{
".write":"root.child($clinicId).child('permissions').child('admins').child(auth.uid).val() == true",
".read": "root.child($clinicId).child('permissions').child('members').child(auth.uid).val() == true"
}
}
}
What comes to my head is the following:
1- When the manger publishes the schedule, I would generate a token, add it to my permissions rules, and embed the token in the shared url as a param.
2- Then when an employee tries to access the url, I would use the token to sign in the user into the app.
I have explored claims and tokens in Firebase and I'm not quite sure which one would be the best neither this is a correct approach.
I would appreciate any insights.
Thank you in advance!
So it sounds like you want to make the data public, but harder to access.
Why don't you just include the id of the public doc in the url ? It is already a big-hard-to-guess hash. Which is all you'd be doing.
Additional security might include:
keep public docs separate from private ones, different collections
or use a flag on the doc that you can check the "visibility" of before returning to the client

does the firebase database online editor ignore security rules

I have rules set up that ensure a foreign key like constraint: when I put data at a certain path, the key is validated to exist at another node.
Rule snippet:
"app": {
"freebies": {
"$provider_id": {
".validate": "newData.parent().parent().parent().child('app').child('providers').child($provider_id).val() != null"
}
}
}
If I run a simulation with these params
Write to /app/freebies
width data: {"totally_fake": 1}
This fails, which is CORRECT.
On the other hand, if I just go to the online editor and add a node to the same location with the same data, it writes the DB without errors.
My question is: does the online editor bypass the security rules ?
Yes, it does. The Firebase console, as well as the Admin SDKs, bypass security rules and have "administrative" access to the Realtime Database.

Fetching custom fields from auth object in Firebase

I am trying to invalidate/revoke client's auth token when they sign on a different device. Initial auth-token is supplied through our server and not firebase (but uses the same secret key, hence works with firebase too).
For each user we save an associated password which gets passed as part of auth-token, when user switches the device - we issue a new password from the server and compare password to invalidate token on server. Firebase connection however still persists.
I am trying to store passwords on firebase for each user. This can then be updated every time we change the password at the backend and use it to invalidate the firebase token as well. However, I am not able to extract password from the auth object. Any ideas?
This is my firebase security rule.
{
"rules": {
".read": root.child('passwords').child(auth.uid).val() == auth.password,
".write": root.child('passwords').child(auth.uid).val() == auth.password
}
}
Surprisingly, none of the custom field in auth object are present.
Whatever you put in the custom auth object would be available in security rules and would be part of the authData returned after authenticating on the client. When you're creating the JWT, you have to follow Firebase's specific rules, which are outlined here. The important part being that a d key contains the authentication data you want to make available. Here's basic example of what the payload might look like.
{
"v": "0",
"iat": 1448391639,
"d": {
"uid": "user1234",
"password": "mySecretPassword"
}
}
http://jwt.io/ is a great tool for quickly creating JWTs for testing. If you use the payload above in conjunction with your Firebase secret, you should see the same payload within your auth data and security rules.
f.authWithCustomToken('eyJhbGciOiJIUz...', function(err, data) {
if (err) {
// Handle error
} else {
console.log(data.auth); // {uid: "userId1234", password: "mySecretPassword"}
}
});

Resources