Firebase Server NodeJS failing to connect with Service Account - node.js

I have a pretty simple NodeJS server that I'm using to monitor our Firebase Database. My code is basically identical to the sample on the Firebase documentation:
var firebase = require("firebase");
firebase.initializeApp({
databaseURL: 'https://myurl.firebaseio.com/',
serviceAccount: 'path/to/json.json'
})
Now the issue I'm having is when I run this code from within our network, it doens't seem to be connection as a have a block of code right after to read some data and it never gets ran:
var nodeRef = this.db.ref("node");
nodeRef.on("child_added", function (snapshot, prevChildKey) {
// ...
}, function (error) {
console.log(error);
})
If I give everyone write access to the database, I can take out the serviceAccount setting on the initializeApp call, and everything works perfectly. I've tried running Fiddler to see what it might be making a request to that is failing, but I'm not seeing any requests pop up in Fiddler at all. Any ideas what this might be calling that our proxy would need to allow?

Our IT team found what the problem was, I had asked them to open accounts.google.com in our proxy server. It got set to "allow" instead of "tunnel".
According to them, the HSTS headers were causing the SSL decryption on the proxy unless it was set to tunnel, which was causing the "self signed certificate" error I mentioned above in the comments.

For me, disabling Kaspersky got it to work. You can try that.

Related

Heroku postgres timeout and SSL issues on API calls with Node

I'm trying to put my REST API built in Node and with PostgresSQL to Heroku. So, I created my application to Heroku, and created his own database. At this point, I tryied to commit, and the build worked corretly. This until I tryied to make some calls to the API. If the api calls I do has the uncorrect method, or doesn't exists, it gives me the correct error, but when the call is correct, there is a 503 error, with code H12, and description that is timeout error. Here is the code of one of the calls to the database that I'm testing:
router.get('/allpoints', async (req,res) =>{
try {
const points = await pool.query(
`SELECT nome, latitudine,longitudine
FROM luogo`);
res.json(points.rows);
}catch(err){
console.error(err.message);
}
});
Here there are the information about how I connect to the database.
const pool = new Pool({
connectionString: process.env.DATABASE_URL || 'postgresql://postgres:psw#localhost:5432/campione',
ssl: process.env.DATABASE_URL ? true : false
})
module.exports = pool;
The build on Heroku seems to work properly.
I read this question: Heroku h12 Timeout Error with PG / Node.js
It says that you have to put res.end() where there is not res.json(), but here there is the res.json(). So, I thought that the issue could be that there is an error that the route manage, and can't give back anything. So, I changed from console.log(err) to res.json(err), and the API response with `ssl self signed, as an error. At this point, in the second file, I put ssl as false by default, but it gaves me error because there is no SSL. I searched for a really long time for a solution, but I have not been able yet to fix the issue.
Someone thinks he knows what should I change? Thank you in advice
this option in databse config maybe useful
ssl: {
rejectUnauthorized : false,
}

Deploying firebase cloud function fails when I initialise firebase with a service account key

so very recently I started using google's firebase cloud functions, and loved it immediately! I very quickly restructured a project I was going to work on, and included firebase in it, so I could use the cool features of firestore, in combination with cloud functions.
Up until today, everything went on smoothly; pretty much, until I decided to play with google's FCM (Firebase Cloud Messaging) to send notifications via node js. Before this, I had created some really dense functions and already deployed to my console which were working seamlessly.
The tricky part is, at the time I created and deployed these functions, I initialised my firebase app in node js with admin.initalizeApp().
With this, everything worked fine(both locally & deployed) until I tried to use admin.messaging().sendToDevice... which resulted in a very nasty error, that basically told me I couldnt send notifications if I wasnt authenticated..
The error
(Error: An error occurred when trying to authenticate to the FCM servers. Make sure the credential used to authenticate this SDK has the proper permissions. See https://firebase.google.com/docs/admin/setup for setup instructions. Raw server response: "<HTML>
> <HEAD>
> <TITLE>Unauthorized</TITLE>
> </HEAD>
> <BODY BGCOLOR="#FFFFFF" TEXT="#000000">
> <H1>Unauthorized</H1>
> <H2>Error 401</H2>
> </BODY>
> </HTML>
> ". Status code: 401.)
Following the error, I used a few tips from some other users on stack overflow who had faced this error, and most of them suggested that I download a service key from my console, and initialise my firebase app with admin.initializeApp({credential:admin.credential.cert(serviceAccount)})
This solution worked beautifully, as it allowed me to test my notification without seeing the above error ever again.
However, when all my tests were done, and I was ready to deploy, the new function I had just created to work on notification, as well as all my previously deployed functions could not get deployed. All of a sudden, the old working functions in my console had a red exclamation mark beside them, and I had to get rid of them. Even after I cleared out all of my console and tried to redeploy all my functions, it failed, and failed and failed with no errors(context: I wasted the whole day!!! lool!) Every tip on the internet failed for me, until I reverted back to my old way of initialising my firebase app admin.initializeApp(), then booom! all my functions uploaded successfully, and then again, the authentication error appeared again when I tried to retest my notification function.....
I guess my question is: is there anything I don't know about deploying functions to the firebase console with my app initialised with a service account key I downloaded from my console?
Is there something else I need to do to get my functions to deploy properly every time I init my firebase admin app with a service account key?? Because initialising the app with just .initalizeApp() works fine for all other purposes both locally and when deployed, except when using FCM. Can anyone please help with what is happening here??
I think it can be solved by initializing two apps and using them as objects described here. One with credentials that work for other functions and one for messaging.
If you need it only for one function you can do it even inside it. I have tested it like this:
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp({
credential: admin.credential.applicationDefault()
});
exports.first_app = functions.https.onRequest(async (req, res) => {
res.json(admin.app().name);
})
exports.other_app = functions.https.onRequest(async (req, res) => {
var otherApp = admin.initializeApp({
credential: **<< different credential here >>**
}, "2nd_app");
res.json(otherApp.name);
})
as already mentioned, you should initialize a second app just for the new function you are creating. You should put the initialization code inside the new function like this
export const saveMap = functions.https.onRequest(async (req, response) => {
const serviceAccount = require("./../serviceAccountKey.json");
admin.initializeApp({
projectId: "serviceAccount.project_id",
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://your_project_id_here.firebaseio.com", //update this
storageBucket: "your_bucket_name_here.appspot.com" //update this
}, "2nd_app")
I had the same issue and once I put the second initialization code into the new function, it worked. Note that in this code the serviceAccountKey.json is in the same folder as src and lib.

No longer captures the event from firebase by Admin SDK

I have installed and run firebase admin on my node server, it has been running well until today, there is no given error to tell what happened, it simply stops working.
var admin = require("firebase-admin");
var serviceAccount = require("mycom-firebase-adminsdk-d1ebt123456.json");
var app = FireBaseAdapter.admin.initializeApp({
credential: FireBaseAdapter.admin.credential.cert(serviceAccount),
databaseURL: "https://xxxx.firebaseio.com"
});
var db = app.database();
var ref = db.ref("messages"); // this node actually exists in my db.
ref.on("value", function(snapshot) {
// this will never be called - which has been working before.
console.log(snapshot.val());
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
});
I even wrap it in the try catch to print out the error, but there isn't any. I can log into the firebase console in the account and see my database with no change (small database) (although it seems be slower than normal).
Is there something wrong with firebase Admin SDK? Any help is appreciated.
After spending many hours to find out the cause, I found the problem.
Since I couldn't find any way to enable log of firebase-admin, so it was the dead end to troubleshoot the issue while everything runs silently, so I switched to use the firebase package to have the logging
var firebase = require("firebase");
firebase.initializeApp({
databaseURL: "https://xxxxx.firebaseio.com",
serviceAccount: '....'
});
firebase.database.enableLogging(true); // <=== important
My issue is quite similar to this question
then I could see the actual error:
p:0: Failed to get token: Error: Error refreshing access token:
invalid_grant (Invalid JWT: Token must be a short-lived token and in a
reasonable timeframe)
The solution for this issue was explained on this anwser. This issue caused by a poor synchronisation of the computer's clock where the code was executed that had a lag of 5 minutes (due to a faulty battery for the internal clock).
It started working again when I manually changed the internal time of my computer to the correct one (or totally I reset my computer date-time).
In my case, after resetting the datetime&timezone, the firebase automatically works again and I do not need to re-generate another service account.

Where to add Firebase in Node

I will be making a Web App in Firebase. Problem is, I am still unsure of how a few things will work.
Eventually I will need a server (which will be in Node) for sending emails and such. One of my biggest questions though is where Firebase will actually be needed. Let me elaborate some more!
I see that in the docs (here) you can add Firebase to your server by adding the following code in Node:
var firebase = require("firebase");
firebase.initializeApp({
serviceAccount: "path/to/serviceAccountCredentials.json",
databaseURL: "https://databaseName.firebaseio.com"
});
But you can also add Firebase directly to the browser with the following code:
<script src="https://www.gstatic.com/firebasejs/3.1.0/firebase.js"></script>
<script>
// Initialize Firebase
// TODO: Replace with your project's customized code snippet
var config = {
apiKey: "apiKey",
authDomain: "projectId.firebaseapp.com",
databaseURL: "https://databaseName.firebaseio.com",
storageBucket: "bucket.appspot.com",
};
firebase.initializeApp(config);
</script>
So my question is in what circumstances would I do either of the above? When would I add Firebase to the browser, and when would I add Firebase to the server? What uses do both provide?
For instance, could I access the Realtime Database from the server without connecting to Firebase? And if I add Firebase to the server, do I then have to add it again to the Browser? Please explain, thank you!
You already have most of the parts of the answer in your question.
Say that you want the users of your web app to be able to send email. As you say, you'll typically want to do that from your server, since you'd otherwise have to rely on the email client of your users.
But even when it's your node.js server that sends the email, it's the users of your web app that determine when and where to send the email. So the users needs a way to talk to your node.js script.
You can easily let the users talk directly to your node.js server. Set up some express.js endpoints and you're in business. But then you'd need to set up security on your node.js server, ensure that you can handle cases where your users are submitting more email requests than your node.js script can handle, etc. Lot of plumbing work that has nothing to do with sending an email.
Another way to handle this scenario is to let the web clients write "email requests" into the Firebase database. Simply include the Firebase client (with the snippet you have) and:
ref.child('outbox').push({
to: 'puf#stackoverflow.com',
subject: 'nice answer!',
body: '...'
})
Now your web client is done and the user can continue.
On the node.js server you include the Firebase client (with the second snippet you have) and connect to the same database, waiting for the email requests to come in:
ref.child('outbox').on('child_added', function(snapshot) {
var msg = snapshot.val();
sendEmailTo(msg.to, msg.subject, msg.body).then(function(error) {
// if the message was sent, delete it from the queue
if (!error) snapshot.ref.remove();
});
})
This approach is covered in our classic blog post on Firebase application architectures as pattern 2.

NodeJS, Express server with ssl to use Dropbox API - 400 Bad Request

I'm currently at y-hack, hacking up an app. I've never deployed an app to a server before, but I've managed to create an AWS EC2 instance, I created ca certificates with startssl, and now I'm trying to retrieve information using the DropBox API.
My code works on my local machine just fine, but I keep getting a 400 Bad Request Error when I try to use the code on my server. Here's what my options look like:
var options = {
key: fs.readFileSync('./cred/ssl.key'),
cert: fs.readFileSync('./cred/ssl.crt'),
ca: [fs.readFileSync('./cred/sub.class1.server.ca.pem')]
}
And my server looks like:
https.createServer(options,app).listen(443, function(){
console.log('Express server listening on port ' + 443);
});
When I try authenticating I use the built-in dropbox javascript client and call:
var server = new Dropbox.AuthDriver.NodeServer(500);
All my ports are open and I'm able to access my website with HTTPS. I've verified that my SSL certificate is okay, but every time I make a request from my micro instance to DropBox, the page hangs. I tried:
curl https://www.dropbox.com/1/oauth2/authorize?client_id={client_id}&redirect_uri=https%3A%2F%2Fsimplestever.com%3A8912%2Foauth_callback/&response_type=code/&state={state}
And I get this as a response (forgive the formatting):
Error (400)
It seems the app you were using submitted a bad request. If you would like to report this error to the app's developer, include the information below.
More details for developers
Missing "response_type".
=====================
I'm very new to this all and only taught myself today. I never used curl before... If anyone has any idea why I'm having these issues with the request, it would be incredibly helpful! Cheers!
Edit: I curled with the escaped characters and it worked! ...which means the client may be broken? I'll replace it with a query and forget about the csrf variable for now to see if it works.
Edit2: I ended up writing the authentication request using the request module and it worked! Just in the nick of time. Cheers!
Edit3: I should give credit to the code I imitated. https://github.com/smarx/othw/blob/master/Node.js/app.js
I think the issue with your curl command is that it has unescaped ampersands. Try putting quotes around the whole URL.

Resources