For the past few months I've been working on a project involving Nodejs (12.16.1).
I've created a backend API (database and other resources) and an authentication service. Im currently updating a Discord bot that uses nodejs (all using the same node version and same node-fetch).
The bot is having issues connecting to the Backend API. Using node-fetch with the following error
request to https://<host:port>/api/bot/<resource> failed, reason: write EPROTO 1988:error:1408F10B:SSL routines:ssl3_get_record:wrong version number:c:\\ws\\deps\\openssl\\openssl\\ssl\\record\\ssl3_record.c:332:\n
Im not using a Proxy, infact its a dev environment all running under localhost. Which has been running without an issue for months.
Now for the interesting part. The bot will POST fine to the authentication service but will fail when using POST or GET to the Backend. Postman will have no issue accessing the APIs. Thinking it was the certificate I made a new one (self-signed) but i still get the same error message.
So I used Wireshark and captured the traffic between the Bot the Authentication service and the Backend. When the bot talks to the Authentication services it does the Hello client / server messages in TLS 1.3. However when it talks to the backend it tries to use TLS 1.0.
Thinking any new current code was causing issues i pulled a fresh copy of the Backend and the Bot from my repo and tried again. Even the current Live builds will fail with the same error message.
I have no clue what is going, I've only been coding for a few months and this is the first wall I've hit that i can't seem to figure out. Goolge and even stack hasn't been much help as an ssl3 wrong version errors have been left unanswered or don't line up with my issue (most people seem to have this issue when using Proxies).
The only thing that has updated software wise was the latest Windows 10 updates.
KB4598242, KB4023057
Thanks.
Edit.
server.js
const port = process.env.PORT;
const key = fs.readFileSync('./server.key');
const cert = fs.readFileSync('./server.cert');
app.use(jwt());
app.use(express.json());
app.use(cors());
app.use('/api/bot', require('routes/botapi'));
const server = https.createServer({'key': key, 'cert': cert}, app);
server.listen(port, () => { console.log(chalk.green(`[SERVER]`) + `: listening on ${port}`) });
botapi.js
...requires
const botRouter = express.Router();
botRouter.post('/updatemembers', discordUpdateMembers);
async function discordUpdateMembers(req, res, next) {
let validRole = await hasBotRole(req);
if (!validRole) return res.status(400).send({err: 'Access_Denied!!'});
discord.updateMembers(req.body)
.then(members => members ? res.json(members) : res.status(400))
.catch(err => next(err));
}
Related
I am trying to connect mobile app with react native and nodeJS running with sails
I have test the connection with reactJS and the socket work fine on the browser but with react native it give me this error
The socket was unable to connect.
The server may be offline, or the
socket may have failed authorization
based on its origin or other factors.
You may want to check the values of
`sails.config.sockets.onlyAllowOrigins`
or (more rarely) `sails.config.sockets.beforeConnect`
in your app.
More info: https://sailsjs.com/config/sockets
For help: https://sailsjs.com/support
I have tried to add onlyAllowOrigin and add on it the url for connect and I have added origin in the header for the frontend part but all didn't work
this is the setup I used in frontend
let socketIOClient = require('socket.io-client');
let sailsIOClient = require('sails.io.js');
let token = 'my jwt token'
let io = sailsIOClient(socketIOClient);
io.sails.url = 'http://localhost:1337/';
io.sails.headers = {authorization:token,origin:'http://localhost:3000'}
useEffect(() => {
io.socket.on('my event',(data) => {
console.log({data})
})
})
backend setup
var io = sails.io
io.emit('my event, {data:'my data'});
I think your issue may be that, as you said you are testing on a 'device' if that is the case then
io.sails.url = 'http://localhost:1337/';
Will not work, the device has no access to localhost, you need to make the socket server publicly available, even if you are using wifi. Localhost is just that, local to the host. Your app can access it on the desktop because, well its local but when its on the device it will try and connect to itself on port 1337, but nothing is running there so its failing.
I would suggest just pushing your code to a public server of some sort (socket server that is)
Some inexpensive / free location are
AWS (free tier)
Digital Ocean ( 100.00 credit or 5.00 / month)
Linode
(100.00 credit or 5.00 / month)
There are many others, but these are some popular ones, also with all options they have pre configured node instances that make it easy to get up and running quickly.
I have successfully deployed this example repo to azure and it is now working in the web chat and on slack.
Now I'm trying to use the facebook adapter in my bot. I have followed the instructions to use FacebookAdapter with BotBuilder and added the following code into index.js
const { FacebookAdapter } = require('botbuilder-adapter-facebook');
const restify = require('restify');
const adapter = new FacebookAdapter({
verify_token: process.env.FACEBOOK_VERIFY_TOKEN,
app_secret: process.env.FACEBOOK_APP_SECRET,
access_token: process.env.FACEBOOK_ACCESS_TOKEN
});
const server = restify.createServer();
server.use(restify.plugins.bodyParser());
server.use(restify.plugins.queryParser());
server.get('/api/messages', (req, res) => {
if (req.query['hub.mode'] === 'subscribe') {
if (req.query['hub.verify_token'] === process.env.FACEBOOK_VERIFY_TOKEN) {
const val = req.query['hub.challenge'];
res.sendRaw(200, val);
} else {
console.log('failed to verify endpoint');
res.send('OK');
}
}
});
server.post('/api/messages', (req, res) => {
adapter.processActivity(req, res, async(context) => {
await context.sendActivity('I heard a message!');
});
});
server.listen(process.env.port || process.env.PORT || 3000, () => {
console.log(`\n${ server.name } listening to ${ server.url }`);
});
also in my .env file I have added the various tokens and secrets required.
When I try testing the app locally with bot framework emulator I get the error
(node:11588) UnhandledPromiseRejectionWarning: Error: Invalid signature on incoming request
at FacebookAdapter.<anonymous> (/home/ronald/Desktop/03.welcome-users/node_modules/botbuilder-adapter-facebook/lib/facebook_adapter.js:421:23)
at Generator.next (<anonymous>)
at /home/ronald/Desktop/03.welcome-users/node_modules/botbuilder-adapter-facebook/lib/facebook_adapter.js:15:71
I'm not sure what I'm doing wrong
Unfortunately, this appears to be a bug of some variety. An issue already exists on the Botkit Github repo with various customers experiencing a similar problem, however there is no fix at this time. It seemingly doesn't affect all customers, as the Botkit developer (at the time of his posting) was able to use the adapter without error.
In looking into your problem, I was able to determine that the error is generated from the verifySignature() method in the FacebookAdapter class. There should be an "x-hub-signature" header returned from Facebook which is used to check the signature of the request payload for the webhook event. For unknown reasons, this header is missing which results in the "invalid signature" message.
I would recommend you comment on the above GH issue to help facilitate work on the problem.
Hope of help!
-----EDIT-----
The Facebook Adapter is designed to work independently of the Azure Bot Service / ABS Channels, even when integrated with a BotFramework bot. As such, it will not work with BotFramework Emulator. It is designed to connect directly to the bot's adapter.
This also means you need to adjust the Webhook Callback URL in your Facebook app settings to point to your locally running bot. The webhook value, when configured for ABS looks something like:
https://facebook.botframework.com/api/v1/bots/[botname].
You will want to adjust it to point to your ngrok endpoint (used for tunneling between your local bot and external sources like Facebook). The new webhook value would look something like this:
https://1a04e4ad.ngrok.io/api/messages.
Don't forget to include the verify token which also comes from Facebook (found in the settings).
Assuming you've changed the webhook url, supplied the verify token, and are NOT using Emulator, then it should work seemlessly.
Note: Facebook sends echos and delivery confirmations for every event passed. The result is, if you don't filter on incoming event types or turn off additional events in Facebook, then your bot will be hit continuously.
So apparently I have 4 environment , 3 environments runs on HTTP and one in HTTPS. Which are all deployed on azure. I am using react-redux as my front end and Asp.net MVC5 as my backend. I tried deploying and testing the signalR to the 3 environments that is running on HTTP and it works like a charm , but when I deployed it on HTTPS. It doesn't work. I have properly configured everything. Since the SignalR is used by me as a chat System and the others where running like REST Apis (endpoints etc. ) My question here is , is the problem in the SSL Certificate of the signalR? I have tried various searches but no luck. Here is my Client Side code since I think the problem is here.
connectToSignalR(){
const con = $.connection;
let hubConnection = con.activeViewersHub;
const { prop1, match: { prop2}, actions: {getViewingUsers} } = this.props;
hubConnection.client.getMessage= (response) =>{
getMessages(response);
};
con.hub.url = `${URL}/signalr`;
con.hub.start({withCredentials:true,transport: 'longPolling' })
.done(()=>{
hubConnection.server.addMessage(prop1,prop2);
});
}
my point is that SSL is properly configured in azure. Since the system is running and everything is working fine, only in signalR that it doesn't work. Been spending a week already in this scenario. Any thoughts about this?
I am developing bots for telegram, I am from Iran and telegram url is blocked in my country and I am forced to use VPN/Proxy servers to access telegram api from my local dev machine.
But I have other apps running on my system that won't work throw a VPN, So I am forced to use proxifier, I can define rules for the apps that I need to go throw a proxy.
But node.exe is ignoring this rules for some reason, I can see in NetLimiter that the connection is coming from C:\Program Files (x86)\nodejs\node.exe, But adding this path to proxifier's rules has no effect, other apps like telegram itself and firefox and ... works fine with these rules ...
So has anyone managed to force node.exe to go throw proxifier?
I also tried to setup a proxcy with php in my host, but none of the proxy scripts I found was able to handle the file uploads
My last hope is to install some modules for apache and use it as a proxy or just install nginx ...
I also tried https://github.com/krisives/proxysocket and https://github.com/TooTallNate/node-https-proxy-agent with no success, its just keeps throwing errors :(
Ok, after hours of trying finally got this to work with proxifier.
https://github.com/TooTallNate/node-https-proxy-agent
new HttpsProxyAgent('http://username:password#127.0.0.1:8080')
Update :
This approach had its problems so I created a small personal proxy server with node-http-proxy on my server and connected to it:
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;
const debug = require('debug')('app');
const http = require('http');
const httpProxy = require('http-proxy');
const proxy = httpProxy.createProxyServer({
secure : false
});
proxy.on('error', function (e) {
debug(e);
});
const server = http.createServer(function(req, res) {
// You can define here your custom logic to handle the request
// and then proxy the request.
proxy.web(req, res, { target: 'https://api.telegram.org', });
});
server.listen(3333);
And simply just redirected all the request to this server.
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.