The Hacker News API documentation says:
If you can use one of the many Firebase client libraries, you really should. The libraries handle networking efficiently and can raise events when things change. Be sure to check them out.
It doesn't specify how to do that though. How can I use the Firebase client libraries to interact with the Hacker News API, to gain more efficient networking and support for listening for events?
You can interact it with it using the Realtime Database API. Set the databaseURL to https://hacker-news.firebaseio.com, and you can make queries using the Firebase client libraries. The paths are the same as the paths in the API, without the .json file extension. For example, this would get data for the user jl using the web client:
var config = {
databaseURL: "https://hacker-news.firebaseio.com",
};
firebase.initializeApp(config);
var database = firebase.database();
console.log((await database.ref("v0/user/jl").get()).val());
Related
My company has implemented Netskope for security and it is causing issues with my Firebase web app. I have verified Netskope is the cause of problem by having our security admins disable it on my PC. When that was done, the web app performs as expected. With Netskope enabled, users are able to log in but can't retrieve documents (and I'm assuming can't edit or delete either). Instead, there is an error in the console that says
Could not reach Cloud Firestore backend. Backend didn't respond within 10 seconds. This typically indicates that your device does not have a healthy internet connection at the moment.
Some code:
var app = firebase.initializeApp(config);
var db = firebase.firestore(app);
var docRef = db.collection("/annual meeting/Events/" + selectedDay).orderBy("time").get().then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
eventIds.push(doc.id);
eventDocs.push(doc.data());
});
addEventsToList();
})
My security people are asking for specific URLs so they can investigate. I've sent them https://console.firestore.google.com/project/*project-name*/firestore, but I'm not sure what else to send them. They seem to think it's either a certificate pinning issue or Firebase not liking Netskope's egress IPs. They need specific URLs to redirect, but I'm not sure what to give them.
According to the Firestore documentation, the client libraries and APIs use the firestore.googleapis.com service to communicate with Firestore.
To call this service, we recommend that you use the Google-provided client libraries. If your application needs to use your own libraries to call this service, use the following information when you make the API requests.
If your security department is requesting URLs to investigate, you can try with the REST endpoints of this API. Inside the documentation, there is an API test app included (API Explorer). This feature lets you make requests to the service with appropriate authentication. For example the following endpoint is used to retrieve documents from Firestore:
https://firestore.googleapis.com/v1/{name=projects/*/databases/*/documents/*/**}
The request parameter name for this endpoint when using the API explorer would be:
projects/projectID/databases/databaseID/documents/documentPath
projectID = your project ID
databaseID = for Firestore use: “(default)”
documentPath = path of the document to retrieve (collection/document/...)
Additionally, I found other questions related to Firebase and Netskope in Stackoverflow and GitHub
This question already has answers here:
Is it safe to expose Firebase apiKey to the public?
(10 answers)
Closed 1 year ago.
It is very likely the case I am misunderstanding how all of this works as I am still a newer programmer, but in every course I have taken I have been told not to expose any credentials within the code.
In this Firestore documentation, it tells you to store your service account's credentials as a JSON file and include the file in the directory for the SDK to access. Am I wrong in thinking this is a security issue?
Firestore Getting Started Documentation
Under Initializing Firestore
To use the Firebase Admin SDK on your own server (or any other Node.js environment), use a service account. Go to IAM & admin > Service accounts in the Cloud Platform Console. Generate a new private key and save the JSON file. Then use the file to initialize the SDK:
const serviceAccount = require('./path/to/serviceAccountKey.json');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});
const db = admin.firestore();
Am I missing something here? Why is it okay to do this?
In fact it depends how we interpret "not to expose any credentials within the code."
Firstly, a main important rule, is to never include secrets (password, or service account keys, or any other confidential data) into the source code, and especially in source code configuration (git / github).
Secondly, in some situation, the only solution to authenticate to a service or API is to use a service account key. In this case, we must keep this file separated from source code, and provide it to app by an environment variable pointing to it.
If your code is running on Google Cloud Platform (App Engine, Cloud Functions, Cloud Run, Firebase Functions...), you can use default authentication provided directly by GCP, and avoid any service account key.
Check Firebase documentation.
In this case, you keep it just for development purpose on your local machine.
I need to be able to access (read, write) firestore from my self-hosted server (not on gcloud).
I also need to reserve write permissions to the app hosted on my self-hosted server, and allow noone else to be able to write to the server, so the security rules for write applications are denied by default.
According to this document:
https://firebase.google.com/docs/firestore/client/libraries#server_client_libraries
using a service account should allow me to be able to access all firebase products, including firestore, without any restrictions.
But, as soon as I restrict the security rules, I am unable to write to firestore from my service, instantiated with service account credentials following the steps in this documentation:
https://firebase.google.com/docs/admin/setup#initialize-sdk
I get the following error:
PERMISSION_DENIED: Missing or insufficient permissions.
What do I have to do to allow my application to write to firestore from my own servers?
Update:
I am using java for my backend applications.
Servers (or cloud functions) are secure environment which can be accessed only by you and people you have authorized. You don't actually use the Firebase Client SDKs in a server. Instead you use the Firebase Admin SDK. It uses a service account and has privileged access to your Firebase Project.
What does privileged access mean?
The documentation has explained it all but long story short it has complete access like you to the project. It does not follow any security rules.
If you are implementing the Admin SDK which will deal with API requests coming from your clients then make sure you authenticate them. To do so you would ideally pass the Firebase ID Token from your frontend to the API and verify
it using the Admin SDK which returns a decoded token object containing UID, custom claims and some metadata about that user.
I'm not sure which language you use but here's a simple getting started for NodeJS:
// Install the Admin SDK
npm install firebase-admin
// index.js
const admin = require("firebase-admin")
const path = require("path");
admin.initializeApp({
credential: admin.credential.cert("path/to/key")),
databaseURL: "https://<project-id>.firebaseio.com/"
})
const firestore = admin.firestore()
const auth = admin.auth()
// firebase.firestore() and firebase.auth() in client SDKs
Rest of the syntax is mostly the same as Client SDK.
You can create a service account from the project settings.
The issue that I was facing has already been reported here:
https://github.com/googleapis/java-firestore/issues/431
The fix was an odd one, and cannot be explained without going deep into the SDK and how it works, which I did not have time to check:
As I understood, expose the API key it is not a security risk if I add validation rules to my database as it mentioned here,
var config = {
apiKey: '<your-api-key>', // this key
authDomain: '<your-auth-domain>',
databaseURL: '<your-database-url>',
storageBucket: '<your-storage-bucket>'
};
I also understood that I can call google shortener API with the firebase API key, now it is risky, anyone can call google shortener API with my firebase API key, how I can avoid this
API Keys are generic identifiers for access across Google APIs - they're not just for Firebase. They are used for API access when you don't need to identify as a specific user (where you would use an OAuth access token).
API keys identify that your project is making a call like passing a project ID, but, importantly, can be regenerated - so if one is being used by a bad actor, you can delete it.
So how do you use these API keys without opening yourself up to someone spamming another API?
Add a domain restriction. Browser based keys can be restricted to require being on a certain domain. You can add these from the Google Developer Console:
Go to the 'Credentials' page for your project
Find your API key and select it
Select 'HTTP referrers (websites)'
Add each of your domains
Be careful with this! Make sure you cover all the domain you're running on, or you will block access (for example if you have a .com and .es version of your site, make sure both domains are whitelisted).
Don't enable the API. If you don't need URL shortener on in the Firebase project, you can disable it from the Google Developer Console. Most APIs start disabled, and several types of API can't be called with an API key any way (they require a service account which is a bit more secure).
I'm building a central module that needs to handle multiple users, subscribing them to data changes on their nests.
From what I've been searching, the Node.JS library won't allow me to do multiple firebase connections to the Google Nest API.
Is there any workaround without using REST or REST with streaming?
You can solve this in the Firebase realtime client libraries by creating a new Firebase.Context for each user. This is an undocumented second parameter to the Firebase constructor that may change in future releases, but instructs the instance to set up and maintain a new TCP connection rather than sharing the common one.
An example of its use in Node.JS would be:
var Firebase = require('firebase');
var authToken = 'some_long_auth_token';
var userRef = new Firebase('wss://developer-api.nest.com', new Firebase.Context());
userRef.authWithCustomToken(authToken, function(error) {
// Handle auth error
});
There may well be limitations on how many connections Node.JS will allow you to maintain, but I haven't tested them.