Validate email address in key of firebase database in security rules - javascript

I have a working project with wrongly configured database security rules.
Here's my current rule -
{
"rules": {
"$email": {
".read": "$email == auth.token.email.replace('.',',')",
".write": "$email == auth.token.email.replace('.',',')",
},
"test": {
".read": "auth != null",
".write": "auth != null"
}
}
}
and here's my data structure -
I am using an email as key and I am trying to limit users to their own email keys. So I am using an email in the security rules.
I am trying to replace '.' with ',' in my security rule as '.' is a forbidden character.
What's the correct syntax for this?
I am getting permission denied error.
Edit :- It seems like I can write data to database just fine. It's something else that's causing the problem.
Edit 2 :- It's the write permission that's giving me permission denied error but writing the data into database anyways. I set write permission to true and everything was working fine. But obviously I don't want that.

I can read my own node without problems with your security rules, and get rejects when reading somebody else's node.
My code:
firebase.auth().signInWithEmailAndPassword("i#puf.io", "correcthorsebatterystaple")
.then(function() {
ref.child("i#puf,io").once("value").then(function(snapshot) {
console.log("Got value from my own node: "+snapshot.val());
}).catch(function(error) {
console.error("Error while reading my own node: "+error);
});
ref.child("someoneelse").once("value").then(function(snapshot) {
console.log("Got value from other node: "+snapshot.val());
}).catch(function(error) {
console.error("Error while reading other node: "+error);
});
});
My rules
"66872665": {
"$email": {
".read": "$email == auth.token.email.replace('.',',')"
}
},
And my JSON in the database:
"66872665": {
"i#puf,io": "value"
}
Running the code gives me this output:
Got value from my own node: value
Error while reading other node: Error: permission_denied at /66872665/someoneelse: Client doesn't have permission to access the desired data.
For a working repro that you can run, see: https://jsbin.com/jomipef/edit?js,console

Related

How to improve firebase real time database rules with anonymous user

I have a simple json tree like this : https://ibb.co/Rgpznd0, and my rules are:
{
"rules": {
".read": "auth.uid !== null",
".write": "false",
}
}
I only need to read the data from the database, i retrieve the token from the user
const accessToken = await user.getIdToken();
and i do a get request with this url with axios:
https://discover-planets-to-visit-default-rtdb.europe-west1.firebasedatabase.app/${query}.json?auth=${accessToken}
this work, but i get some warning from firebase about security rules
///////////////////////////////
UPDATE
I tried to put the rules like this, in a more secure way :
{
"rules": {
"destinations": {
"$uid": {
".read": "auth != null && auth.uid == $uid",
".write": "false"
}
}
}
}
I tried changing the url like this:
https://discover-planets-to-visit-default-rtdb.europe-west1.firebasedatabase.app/destinations.json/${uid}?auth=${accessToken}
But now the axios request doesn't work even if i put the uid in the query.
I also tried on postman and the response it's seems the html of the page, I am doing something wrong.
How can i do that? And get a json response?
////////////
UPDATE 2
full url like requested
https://discover-planets-to-visit-default-rtdb.europe-west1.firebasedatabase.app/destinations.json/nQhLc86TWHeHhSP7JSuPAJdBKyk1?auth=${accessToken}
UPDATE 3
I have find a solution to my problem, you can check the answer below
I follow this guide: https://medium.com/#skytreasure/easy-way-to-secure-firebase-realtime-database-with-rules-when-you-have-anonymous-sign-in-or-already-e8ff1ddfbfc9
Inside the onAuthStateChanged i set a request to the database with the secure key
await set(
ref(
db,
`/${process.env.NEXT_PUBLIC_FIREBASE_ROUTE}/${user.uid}`
),
true
)
.then(() => {
//Fullfilled
})
.catch((error: Error) => {
throw new Error(error.message);
});
Then i didn't change the other methods to fetch.
https://discover-planets-to-visit-default-rtdb.europe-west1.firebasedatabase.app/${query}.json?auth=${accessToken}
Instead of query i put: 'destination' - 'crew' - 'technology' depends of witch pages do you go.
Now the database is secure, only who have the anonymous id can do the request

Fetch database data from firebase to my blog without auth

I've followed the guide from a documentation of firebase on how to fetch the data.
I try to play around with the:
sample of firebase here
However, to get database data need to auth. Is there anyway just only fetch like feed from firebase without auth? I need to read on my own blog to be read for public.
Please..help me to solve this issue.
Thanks.
You could set your rules to this:
{
"rules": {
".read": "true",
".write": "auth != null"
}
}
But this means anyone who has access the database can read all the data.
In your code you would do something like this:
firebase.database().ref("blogItems").on('value', function(snapshot) {
console.log(snapshot.val());
});
If your setup is like this:
firebase-database-123
|
|_blogItems
|
|_entry1
|
|_entry2
I would recommend you get familiar with Firebase Database Security Rules.
These are the ones which dictate who can read/write into the Firebase Database.
All new projects starts with the rules
{
rules: {
.read: auth != null,
.write: auth != null
}
}
This means anyone who isn't authenticated won't be able to read or write in our database.
To achieve what you might need without compromising other data you may do something like the following:
{
rules: {
.read: auth != null,
.write: auth != null
blogEntries: {
.read: true,
.write: auth != null
}
}
}
By doing this you are allowing everyone to read the data inside blogEntries, and this means ALL the data inside, while if someone wants to write data to blogEntries they should be authenticated.
I recommend watching The key to Firebase Security to further understand what can be achieved and how Security Rules work.
Yes, you can get the data without authenticating, but it's not recommended. I did the following setup in the Firebase.
Step 1
Click on Realtime Database's GET STARTED
Step 2
Click on second option start in test mode you can access data without auth
or
Add following lines in rules
{
"rules": {
".read": true,
".write": true
}
}

Firebase read permission denied when using auth security rules

Data Structure:
root:
lists:
$list:
pass: "VALU"
Rules Structure:
"rules": {
"lists": {
"$list": {
".read": "auth.token.name === data.child('pass').val()"
}
}
}
Javascript:
firebase.auth().signInAnonymously();
firebase.auth().currentUser.updateProfile({
displayName: "VALU"
});
firebase.database().ref("lists/{$SomeList}").once('value').then([...]);
// Throws error: permission denied
I'm very confused as to why the permission is denied. I made sure that the values for the displayName and the pass were the same, so I'm not sure as to why the comparison is returning false..
UPDATE: It seems that the auth variable in the security rules is not refreshing when the displayName is changed, any ideas on how to fix this?
Force token refresh on the user after updateProfile:
firebase.auth().currentUser.getToken(true)
The idToken will be updated afterwards.

Firebase - Why is it not pulling my information? [duplicate]

I'm relatively new to coding and am having trouble.
I have this code to send data to firebase
app.userid = app.user.uid
var userRef = app.dataInfo.child(app.users);
var useridRef = userRef.child(app.userid);
useridRef.set({
locations: "",
theme: "",
colorScheme: "",
food: ""
});
However, I keep getting the error:
FIREBASE WARNING: set at /users/(GoogleID) failed: permission_denied
2016-05-23 22:52:42.707 firebase.js:227 Uncaught (in promise) Error: PERMISSION_DENIED: Permission denied(…)
When I try to look this up it talks about rules for Firebase, which seems to be in a language that I haven't learned yet (or it is just going over my head). Can someone explain what is causing the issue? I thought it was that I was asking for it to store email and user display name and you just weren't allowed to do this, but when I took those out I still had the same problem. Is there a way to avoid this error without setting the rules, or are rules something I can teach myself how to write in a day, or am I just way out of my league?
Thanks for any help!
By default the database in a project in the Firebase Console is only readable/writeable by administrative users (e.g. in Cloud Functions, or processes that use an Admin SDK). Users of the regular client-side SDKs can't access the database, unless you change the server-side security rules.
You can change the rules so that the database is only readable/writeable by authenticated users:
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
See the quickstart for the Firebase Database security rules.
But since you're not signing the user in from your code, the database denies you access to the data. To solve that you will either need to allow unauthenticated access to your database, or sign in the user before accessing the database.
Allow unauthenticated access to your database
The simplest workaround for the moment (until the tutorial gets updated) is to go into the Database panel in the console for you project, select the Rules tab and replace the contents with these rules:
{
"rules": {
".read": true,
".write": true
}
}
This makes your new database readable and writeable by anyone who knows the database's URL. Be sure to secure your database again before you go into production, otherwise somebody is likely to start abusing it.
Sign in the user before accessing the database
For a (slightly) more time-consuming, but more secure, solution, call one of the signIn... methods of Firebase Authentication to ensure the user is signed in before accessing the database. The simplest way to do this is using anonymous authentication:
firebase.auth().signInAnonymously().catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// ...
});
And then attach your listeners when the sign-in is detected
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
var isAnonymous = user.isAnonymous;
var uid = user.uid;
var userRef = app.dataInfo.child(app.users);
var useridRef = userRef.child(app.userid);
useridRef.set({
locations: "",
theme: "",
colorScheme: "",
food: ""
});
} else {
// User is signed out.
// ...
}
// ...
});
I was facing similar issue and found out that this error was due to incorrect rules set for read/write operations for real time database. By default google firebase nowadays loads cloud store not real time database. We need to switch to real time and apply the correct rules.
As we can see it says cloud Firestore not real time database, once switched to correct database apply below rules:
{
"rules": {
".read": true,
".write": true
}
}
Note:
Be careful with the rules. By setting read and write to true makes database vulnerable to praying eyes.
Read more:
https://firebase.google.com/docs/database/security
Go to the "Database" option you mentioned.
There on the Blue Header you'll find a dropdown which says Cloud Firestore Beta
Change it to "Realtime database"
Go to Rules and set .write .read both to true
Copied from here.
Go to database, next to title there are 2 options:
Cloud Firestore, Realtime database
Select Realtime database and go to rules
Change rules to true.
OK, but you don`t want to open the whole realtime database!
You need something like this.
{
/* Visit https://firebase.google.com/docs/database/security to learn more about security rules. */
"rules": {
".read": "auth.uid !=null",
".write": "auth.uid !=null"
}
}
or
{
"rules": {
"users": {
"$uid": {
".write": "$uid === auth.uid"
}
}
}
}
Open firebase, select database on the left hand side.
Now on the right hand side, select [Realtime database] from the drown and change the rules to:
{
"rules": {
".read": true,
".write": true
}
}
Another solution is to actually create or login the user automatically if you already have the credentials handy. Here is how I do it using Plain JS.
function loginToFirebase(callback)
{
let email = 'xx#xx.com';
let password = 'xxxxxxxxxxxxxx';
let config =
{
apiKey: "xxx",
authDomain: "xxxxx.firebaseapp.com",
projectId: "xxx-xxx",
databaseURL: "https://xxx-xxx.firebaseio.com",
storageBucket: "gs://xx-xx.appspot.com",
};
if (!firebase.apps.length)
{
firebase.initializeApp(config);
}
let database = firebase.database();
let storage = firebase.storage();
loginFirebaseUser(email, password, callback);
}
function loginFirebaseUser(email, password, callback)
{
console.log('Logging in Firebase User');
firebase.auth().signInWithEmailAndPassword(email, password)
.then(function ()
{
if (callback)
{
callback();
}
})
.catch(function(login_error)
{
let loginErrorCode = login_error.code;
let loginErrorMessage = login_error.message;
console.log(loginErrorCode);
console.log(loginErrorMessage);
if (loginErrorCode === 'auth/user-not-found')
{
createFirebaseUser(email, password, callback)
}
});
}
function createFirebaseUser(email, password, callback)
{
console.log('Creating Firebase User');
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(function ()
{
if (callback)
{
callback();
}
})
.catch(function(create_error)
{
let createErrorCode = create_error.code;
let createErrorMessage = create_error.message;
console.log(createErrorCode);
console.log(createErrorMessage);
});
}
PermissionDenied can also appear if provided Firebase project ID is incorrect.
See this guide to check your project ID:
Firebase console: Click settings Project settings. The project ID is displayed in the top pane.
If you are attempting to reuse an old project in firebase, due to free account restrictions, then your database rules are probably outdated.
In my case, I was getting error 401 Unauthorized and it solved when I set both read and write rules equal to true.
Thanks for this great community!
Much respect from Brazil!
i was also having the same problem. make sure that you are using the real-time database instead of the cloud. then change rules to allow access to all users as follows
{
"rules": {
".read": true,
".write": true
}
}
by default the firestore database only allows admins to read and write from the database thus the read/write rules will be set to false.

Firebase Anonymous Authentication issue

I am using Firebase Simple Login (version 1.6.1) to authenticate anonymously. I start with,
var livepolling_ref = new Firebase(FIREBASE_URL);
var auth = new FirebaseSimpleLogin(livepolling_ref, function(error, user) {
if (error) {
console.log('An error!');
} else if (user) {
//Boot the App and save the user.id
//I'm able to reach this point in the code using the debugger
}
});
auth.login('anonymous');
I have checked that user has a uid and a FirebaseAuthToken in the callback, and I save the user id. So it seems that I am logged in.
However, I have the following security on my entire Firebase repo.
".write": "auth != null"
When I check the Chrome Console, it tells me "permission denied."
I realized my mistake--I was referencing the wrong Firebase Repo. Sorry for the confusion!

Categories

Resources