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

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.

Related

socket.io client doesn't set sid in requests

I'm trying to build a nodejs script to communicate with a socket.io server.
const io = require('socket.io-client');
const socket = io('http://192.168.144.249');
socket.on('connect', () => {
console.log('connected');
})
Using wireshark to follow traffic I can see the following:
So the browser sends me a sid, both in the response body and in the cookie.
Unfortunately, my following requests do not include this sid and I received a 400 Bad Request error:
When I try to build the same client from a browser windows I can see that this cookie is indeed set, both as cookie and as a query parameter:
I don't want to use a browser, I want to use a standalone node script. As far as I understood the parsing of the response and the inclusion of the session id should be done automatically by the socket.io-client. Am I wrong? If so, how can I intercept this event so that I can send the sid with following requests?
Am I supposed to first do a simple http request to the server, get the sid from there and then add it to the socket.io client when creating it using custom cookies or custom query parameters?
I can also see that the node standalone script is using engine.io version 4 (EIO=4 in the GET requests), while the browser is doing it with engine.io version 3, but the respose received seems to be exactly the same so I don't really think this is what is preventing my script from automatically completing the handshake with the server.
Well, I was wrong. It was indeed a protocol mismatch problem.
I was able to make my script working using socket.io-client#1.0.2. Install it with:
npm install socket.io-client#1.0.2

Firebase Server NodeJS failing to connect with Service Account

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.

wss letsencrypt UNABLE_TO_GET_ISSUER_CERT

using node.js and a letsencrypt.org certificate
var hardhttps=require('hardhttps');
hardhttps.globalAgent.options.ca=require('ssl-root-cas/latest').inject().addFile('/etc/letsencrypt/lets-encrypt-x3-cross-signed.pem');
var pem={
key:require('fs').readFileSync('/etc/letsencrypt/live/mysite.com/privkey.pem','utf8')
, cert:require('fs').readFileSync('/etc/letsencrypt/live/mysite.com/fullchain.pem','utf8')
, ca:require('fs').readFileSync('/etc/letsencrypt/lets-encrypt-x3-cross-signed.pem','utf8')
, pass:'xxxx'
}
var server=(hardhttps.createServer({key:pem.key,cert:pem.cert,ca:[pem.ca],passphrase:pem.pass})).listen(port);
var wss=new WebSocketServer({server:server});
My second server that is trying to connect has exactly the same setup with its own certs and code
When I try to connect sever-to-server It just errors with [Error: unable to get issuer certificate] code: 'UNABLE_TO_GET_ISSUER_CERT'
Googled the hell out of it! Nothing even comes up in letsencrypt.org and the error message shows no clue!
I can test on each file that I can access it:
var test=require('fs').readFileSync('/etc/letsencrypt/lets-encrypt-x3-cross-signed.pem','utf8');
console.dir(test);//I see the pem!!!
It could be this line because, if I remove it then I get the same error:
hardhttps.globalAgent.options.ca=require(__dirname+'/../node_modules/ssl-root-cas/latest').inject().addFile('/etc/letsencrypt/lets-encrypt-x3-cross-signed.pem');
I've linked it to this as no doubt other people may need a solution https://community.letsencrypt.org/t/error-unable-to-get-issuer-certificate-code-unable-to-get-issuer-cert/15342/3
(pfg Community Modorator said)
benzmuircroft:
pem:{
key:require('fs').readFileSync('/etc/letsencrypt/live/mysite.com/privkey.pem','utf8')
, cert:require('fs').readFileSync('/etc/letsencrypt/live/mysite.com/fullchain.pem','utf8')//was chain.pen
, ca:require('fs').readFileSync('/etc/letsencrypt/lets-encrypt-x3-cross-signed.pem','utf8')
, pass:'xxxxxxxxxxx'
}
var ws=new require('ws')('wss://mysite:8004',{key:pem.key,cert:pem.cert,ca:[pem.ca],passphrase:pem.pass,requestCert:true});
There's no need to set any of that. Server 2 is just a TLS client requesting Server 1, it does not need the server's key or certificate file. You probably just want:
var ws=new require('ws')('wss://mysite1:8004');
Not sure if that's the fix - give it a try.
FIXED!
The server that connects to the listening server does not need to send pem stuff but the listening one does need to have the pem available.
https://community.letsencrypt.org/t/error-unable-to-get-issuer-certificate-code-unable-to-get-issuer-cert/15342/3

Socket.io failing to connect because of nsp

I have a problem with socket.io#^1.0. The setup is fine because it works locally, the server is correctly configured and when i try to connect to the server from my Angular APP it works fine with this:
io.connect("localhost:8080");
The connection is established and i can send and receive event. Now in the production environment, "locahost:8080" is replaced with the address of the server Launched:
io.connect("https://domain-name.com/api");
I know that the problem here is the /api, since socket.io is considering it as a namespace and it's trying to connect to it, in my network console I see 500 Internal server error with the address https://domain-name.com without the /api when i replace the request url to add the /api I get a 200 OK with type octet-stream.
So the question here is: how do I connect to the correct path without consideration of the namespace?
Thanks in advance for any help :)
I think you want to use the path option (documented here):
// client
var socket = io.connect('https://domain-name.com/', {
path : '/api/socket.io'
});

Websocket server running fine but cannot connect from client (what url should I use?)

OK this is very simple to anyone who's used websocket and nodejs.
I have created a websocket server named ws_server.js and put it in C:\Program Files (x86)\nodejs where I have installed the nodejs framework. I started the server and it is running and it says it's listening on port 8080. So far so good, I have the server running.
Now I simply want to connect to it from client code so that I can do all that lovely stuff about capturing events using event listeners etc. The problem is, embarassingly, I cannot figure out what URL to use to connect to my websocket server.
function init() {
testWebSocket();
}
function testWebSocket() {
websocket = new WebSocket("ws://localhost:8080/"); // WHAT URL SHOULD BE USED HERE?
websocket.onopen = function(evt) { alert("OPEN") };
websocket.onclose = function(evt) { alert("CLOSE") };
websocket.onmessage = function(evt) { alert("MESSAGE") };
websocket.onerror = function(evt) { alert("ERROR") };
}
function doSend(message) {
// this would be called by user pressing a button somewhere
websocket.send(message);
alert("SENT");
}
window.addEventListener("load", init, false);
When I use ws://localhost:8080 the only events that trigger are CLOSE and ERROR. I cannot get the client to connect. I must be missing something very simple. Do I need to set up my nodejs folder in IIS for example and then use that as the URL?
Just to reiterate, the websocket server is running fine, I just don't know what URL to use to connect to it from the client.
EDIT: The websocket server reports the following error.
Specified protocol was not requested by the client.
I think I have got it working by doing the following.
var websocket = new WebSocket("ws://localhost:8080/","echo-protocol");
The problem being that I needed to specify a protocol. At least now I get the onopen event. ...if nothing much else
I was seeing the same error, the entire web server goes down. Adding the protocol fixes it but leaves me wondering why it was implemented this way. I mean, one bad request should not bring down your server.
You definitely have to encase it a try/catch, but the example code provided here https://www.npmjs.com/package/websocket (2019-08-07) does not. This issue can be easily avoided.
I just wanted to share a crazy issue that I had. I was able to connect to a websocket of an old version of a 3rd party app in one computer, but not to a newer version of the app in another.
Moreever, even in new computer with the new version of the app, The app was able to connect to the websocket, but no matter what I did, when I tried to connect with my own code, I kept getting the error message that the websocket connection failed
Long story short, They changed an apache configuration that allowed connecting to the websocket via a proxy.
In the old version, apache config was:
ProxyPass /socket/ ws://localhost:33015/ retry=10
ProxyPass /socket ws://localhost:33015/ retry=10
In the new version, apache config was changed to:
ProxyPass /socket/ ws://localhost:33015/ retry=10
By bad luck, I was trying to connect to ws://localhost/socket and not to ws://localhost/socket/. As a result, proxy was not found, and connection returned an error.
Moral of the story: Make sure that you are trying to connect to a websocket url that exists.
For me, the solution was to change the URL from ws:// to wss://. This is because the server I was connecting to had updated its security, and now only accepted wss.

Resources