I written rules for my firestore documents and using admin sdk credentials, that bypasses rules.
How to make rules work on python?
Python code
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
cred = credentials.Certificate('key.json')
firebase_admin.initialize_app(cred)
db = firestore.client()
try:
doc_ref = db.collection('users').document('test')
doc_ref.set({'password':'testPass','shadow':'testShadow'})
print('success')
except:
print('failed')
Firestore rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, write: if request.auth.uid == userId;
}
}
}
The Firebase Admin SDKs run with administrative privileges and bypass the security rules for Firestore. There is no way to change that.
If you want your code to follow the security rules, you'll have to use one of the client-side SDKs, but none exists for Python at the moment.
Related
Im trying to connect my python script to a Firebase database.
Here is the code:
import firebase_admin
from firebase_admin import credentials, db
cred = credentials.Certificate("irebase-adminsdk-ofcmd-bwd7fbcz2c.json")
firebase_admin.initialize_app(cred, {'databaseURL':'https://company.firebaseio.com/'})
ref = db.reference('/users').get()
The ERROR Im facing looks like this:
requests.exceptions.HTTPError: 404 Client Error: Not Found for url: https://company.firebaseio.com/users.json
I did a lot of research and everyone says that I have to find the right URL in the 'Realtime Database' Section. I wonder if there is any way to access the Firebase db without having realtime one enabled.
if you are looking to access the Firebase Database without having the realtime one enabled, you can try the Cloud Firestore which is a different database service provided by Firebase which doesn't require realtime database to be enabled but you may need to change the way you are accessing the data
import firebase_admin
from firebase_admin import credentials, firestore
# Initialize the Firebase Admin SDK with your service account credentials
cred = credentials.Certificate("firebase-adminsdk-that-cred-file.json")
firebase_admin.initialize_app(cred)
# Create a reference to the Firestore database
db = firestore.client()
# Read data from a specific document in the 'users' collection
doc_ref = db.collection('users').document('user1')
doc = doc_ref.get()
# Print the data from the document
print(doc.to_dict())
I created a firebaseconfig.json file with my apikey, authodomain, databaseurl, projected, storagebucket, messagingsenderid, appid and measurementid. this comes standard in the SDK setup and configuration section of the yourapps section in project setting. but when I try running my python code.
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
import os
print(os.getcwd())
if not firebase_admin._apps:
cred = credentials.Certificate('src/firebaseconfig.json')
default_app = firebase_admin.initialize_app(cred)
db = firestore.client()
users_ref = db.collection(u'users')
docs = users_ref.stream()
for doc in docs:
print(f'{doc.id} => {doc.to_dict()}')
I get the Error: ValueError: Invalid service account certificate. Certificate must contain a "type" field set to "service_account".
The Firebase Admin SDK requires a service account for authentication, as opposed to a configuration file with the project keys (which is primarily used for web/iOS/Android clients).
If you have not used a service account, you need to generate a key file to use within your application through the Firebase console (Settings -> Service Accounts -> Generate New Private Key).
Afterwards, you can initialize the firestore client within your code as follows (relevant doc):
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
# Use the json key generated from the Firebase console
cred = credentials.Certificate('path/to/serviceAccount.json')
firebase_admin.initialize_app(cred)
db = firestore.client()
Let me know if this information was useful.
I'm trying to connect using python 3.8 to the firestore emulator 8.12. I'm having difficulty finding a way to connect. I've downloaded my key from Firestore in the cloud. But I'm trying to connect locally. What does local.json file look like to connect to the emulator locally?
import os
import firebase_admin
from firebase_admin import firestore
from firebase_admin import credentials
cred = credentials.ApplicationDefault()
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "local.json"
firebase_app = firebase_admin.initialize_app(cred)
db=firestore.client()
data = {
u'name': u'Los Angeles',
u'state': u'CA',
u'country': u'USA'
}
# Add a new doc in collection 'cities' with ID 'LA'
db.collection(u'cities').document(u'LA').set(data)
From this issue on the repo, it seems the Python Admin SDK also needs to the FIRESTORE_EMULATOR_HOST environment variable to be set.
os.environ["FIRESTORE_EMULATOR_HOST"] = "127.0.0.1:8080"
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "emulator_config.json"
docs = db.collection(u'insights/venues/queue').stream()
You can use anonymous credentials. From google-auth docs:
These are useful in the case of services that support anonymous access
or local service emulators that do not use credentials.
If you don't provide credentials, then it will use default credentials like you do and describet here
from google.auth import credentials
from google.cloud import firestore
client = firestore.Client(credentials=credentials.AnonymousCredentials())
FIRESTORE_EMULATOR_HOST needs to be set
I'm writing a simple Google Cloud Function to learn, with the new Python3.7 option, and I would like to read/write some data to Firebase Realtime db.
I found some information to use Firestore that worked, but now I need to use the realtime Database.
# global
import firebase_admin
from firebase_admin import db
# from firebase_admin import firestore
default_app = firebase_admin.initialize_app()
def check_prices_updates(request):
"""Responds to any HTTP request.
Args:
request (flask.Request): HTTP request object.
Returns:
The response text or any set of values that can be turned into a
Response object using
make_response
"""
collection = 'pricelist'
mybase = db.reference(collection)
....[other code]
return "OK"
This is an excerpt of my code, the documentation says that the initialize_app() must be left empty to collect the project default credentials.
The line where I call db.reference(collection) give me the exception:
ValueError: Invalid databaseURL option: "None". databaseURL must be a non-empty URL string.
as if the configuration parameters did not show the requested key 'databaseURL'. With Firestore, as example I could call firestore.client(), after the import from firebase_admin, adding 'google-cloud-firestore in requirements.txt.
Now, for firebase, what should I fix to read and write on the db?
PS. on my db the ".read" rule is true for all so I haven't trouble on auth!
UPDATE:
After a good sleep I realized that to access the realtime db I need to pass some options to initialize_app, as follow:
firebase_admin.initialize_app(options={'databaseURL': 'https://[PROJECT-NAME].firebaseio.com'})
Cheers
Initiliase the Firebase Admin SDK
This will access the db, even if you put permission restrictions on read, write, as your python will have admin access
If you have multiple database instance (Only available for blaze plan)
Initilise them with different app name inside single python script
#Firebase Admin Imports
import firebase_admin
from firebase_admin import credentials
from firebase_admin import db
#Firebase admin sdk Key - Save it as secret
firebaseval={
"type": "service_account",
"project_id": "<project_id>",
"private_key_id": "<private_key>",
"private_key": "-----BEGIN PRIVATE KEY--xxxxxxxxxxxxxxxxxxxxxxxxxx\n-----END PRIVATE KEY-----\n",
"client_email": "firebase-adminsdk-ipcf5#<project_id>.iam.gserviceaccount.com",
"client_id": "<clinet_id>",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-ipcf5%40<project_id>.iam.gserviceaccount.com"
}
cred = credentials.Certificate(firebaseval)
print("\n---------------------------")
print("Initialising Firebase...")
#Initilising Database 1- fetching stock and option details
firebase_admin.initialize_app(cred, {
'databaseURL' : 'https://<project_id>-<instance_id1>.firebaseio.com/'
})
# Initilising Database 2- Different instance ID
app2 = firebase_admin.initialize_app(cred, {
'databaseURL': 'https://<project_id>-<instance_id2>..firebaseio.com/'
}, name='app2')
# Initilising Database 3- Different instance ID
app3 = firebase_admin.initialize_app(cred, {
'databaseURL': 'https://<project_id>-<instance_id3>..firebaseio.com/'
}, name='app3')
print("Initialised Firebase")
print("---------------------------\n")
Accessing the different database Instances
# database instance_id2
mainref2=db.reference("PATH",app2)
# database instance_id3
mainref3==db.reference("PATH",app3)
# Reading whole data from
mainref2.get()
# Reading inside child node from db instance_id2
mainref2.child("child_name").get()
# Setting json data to db instance_id3
mainref3.set({"data":"something"})
I have the following database entry: "companies: 8":
I have the following database rules, which do not allow a simulated write of "companies: 8" to the database.
{
"rules": {
".read": "auth != null",
".write": "auth != null",
"companies": {
".validate": "(data.exists() && (newData.val() === data.val() + 1)) || (!data.exists() && newData.val() == 0)"
}
}
}
However, when I try to write "companies: 20" to the database with the Firebase Python SDK, which also is not allowed under these rules, it works:
In [1]: import firebase_admin
In [2]: from firebase_admin import credentials, db
In [3]: cred = credentials.Certificate('serviceAccountCredentials_dev_async.json
...: ')
In [4]: firebase_admin.initialize_app(cred, {'databaseURL': 'https://async-testi
...: ng.firebaseio.com/'})
Out[4]: <firebase_admin.App at 0x7fc50c00c080>
In [5]: ref = db.reference()
In [6]: ref.update({'companies': 20})
What am I doing wrong?
You are using the Firebase Admin SDK and it looks like you are initializing with the credentials for a service account. In this case, no security rules are applied, I think not even validation rules.
If there is a reason you must you the Admin SDK and want validation rules to be performed, authenticate with limited priveleges:
As a best practice, a service should have access to only the resources
it needs. To get more fine-grained control over the resources a
Firebase app instance can access, use a unique identifier in your
Security Rules to represent your service. Then set up appropriate
rules which grant your service access to the resources it needs.