I have a React app (client-side) and Express (server-side). I am trying to make a connection using Socket.io.
/client : [email protected] /server : [email protected]
// server/server.js:
const express = require('express');
const { createServer } = require('http');
const { Server } = require('socket.io');
const socketioJwt = require('socketio-jwt');
const cors = require('cors');
const helmet = require('helmet');
const app = express();
// Enable CORS for all routes
app.use(cors());
// Enable Trust Proxy
app.set("trust proxy", 1);
// Use Helmet middleware to enhance security
app.use(helmet());
// Add this line to parse JSON data in incoming requests
app.use(express.json());
const httpServer = createServer(app);
const io = new Server(httpServer, {
cors: {
origin: "http://localhost:3000", // here i am putting the Ngork Client Url "https://ngrok-url.com"
methods: ["GET", "POST"],
credentials: true,
},
});
const port = process.env.PORT || 4821;
io.use((socket, next) => {
const clientIP = socket.handshake.address;
Configure JWT authentication middleware
io.use(
socketioJwt.authorize({
secret: secretKey, // my secret from .env file
handshake: true,
})
);
// client/src/App.js:
import React, { useState, useEffect } from 'react';
import io from 'socket.io-client';
import './styles.css';
const jwt = require('jsonwebtoken');
const token = jwt.sign(
{
username: "myUsername",
},
process.env.REACT_APP_JWT_SECRET
);
const socket = io("http:/localhost:4821", {. // here i am putting the ngork ServerUrl "https://ngrok-url.com"
query: { token },
});
socket.on('connect', () => {
console.log('Connected to the server');
});
socket.on('error', (error) => {
console.error('WebSocket Error:', error);
});
NGROK Server: (on Virtual machine/Linux Ubuntu/Node.js LTS 18)
- sudo ufw status, //(active), sudo ufw allow 4821, sudo ufw reload
- Starting /server – npm start; // script: nodemon node server.js
- Starting ngrok tunnel with – ngrok start server //ngrok.yml http localhost:4821
- Get the Ngrok https SERVER URL
- Paste Ngrok Server URL in /client/App.js // type ctrl+c, npm start again App.js
NGROK Client: (on MAC)
- Starting – /client/src/App.js – npm start
- Starting ngrok tunnel with – ngrok start client //ngrok.yml http localhost:3000
- Get the Ngrok https CLIENT URL
- Paste Ngrok Client URL in /server/server.js // type "rs" in terminal to restart nodemon
When I am using localhost:3000 (client) and localhost:4821 (server) I can see Socket.io connection, I do not have any problems. But when I am using Ngrok I have a big problem, I can not see Socket.io connection.
I do not have errors in the browser console.
In the Network Tab (ALL), when I clicked on /socket… I saw:
Request URL: https://f65b-185-213-154-249.ngrok-free.app/socket.io/?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InNhdG9zaGlAMjFubWlsbC5pbyIsImlhdCI6MTY5ODUwNjE1M30.v5hCOKlmMHf3RSEdXTumzO7PEtKzYz-XZrA6CqPsCkg&EIO=4&transport=polling&t=OjssoEr Request Method: GET Status Code: 200 OK (from service worker) Referrer Policy: strict-origin-when-cross-origin Access-Control-Allow-Origin: * Content-Length: 1396 Content-Security-Policy: default-src 'self' https://cdn.ngrok.com 'unsafe-eval' 'unsafe-inline'; img-src data: w3.org/svg/2000 Content-Type: text/html Date: Sat, 28 Oct 2023 15:15:55 GMT Ngrok-Trace-Id: 7ca3e23723940ef090231cf42ad421a1 Referrer-Policy: no-referrer X-Content-Type-Options: nosniff Accept: */* Referer: https://ed5e-185-213-154-249.ngrok-free.app/ Sec-Ch-Ua: "Chromium";v="118", "Brave";v="118", "Not=A?Brand";v="99" Sec-Ch-Ua-Mobile: ?0 Sec-Ch-Ua-Platform: "macOS"
In the Network Tab (WS), when I clicked on /socket… I saw only one sockjs-node, then when I clicked on sockjs-node:
Request URL: wss://ed5e-185-213-154-249.ngrok-free.app/sockjs-node Request Method: GET Status Code: 101 Switching Protocols Connection: Upgrade Ngrok-Trace-Id: 58a6ffcdbd0cd5a1ef2d633378c24398 Sec-Websocket-Accept: ONgwe/ms0WvXB6Tb2eIyPvx6dVo= Upgrade: websocket Accept-Encoding: gzip, deflate, br Accept-Language: en-GB,en-US;q=0.9,en;q=0.8 Cache-Control: no-cache Connection: Upgrade Cookie: abuse_interstitial=ed5e-185-213-154-249.ngrok-free.app Host: ed5e-185-213-154-249.ngrok-free.app Origin: https://ed5e-185-213-154-249.ngrok-free.app Pragma: no-cache Sec-Gpc: 1 Sec-Websocket-Extensions: permessage-deflate; client_max_window_bits Sec-Websocket-Key: QQjVTB/9a2Ou5OcaPX2YnA== Sec-Websocket-Version: 13 Upgrade: websocket User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36
What I think is wrong is the fact that I do not have SSL certs for Ngrok (Let’s Encrypt). I also think that I need to add two extra lines in the client/src/App.js file, but I am not sure if I really need to:
// /client/src/App.js
...
const socket = io("http:/localhost:4821",
{ query: { token },
withCredentials: true, // NEW LINE
transport: [websockets, polling], // NEW LINE
});
2
Answers
I'm using localtunel now and I don't have any problems with it instead with Ngrog.
PM from ngrok here. It sounds like you might be hitting an issue with the abuse interstitial that ngrok adds to free accounts as a way to reduce phishing attempts. To get around the interstitial, follow these instructions and add the
ngrok-skip-browser-warning
header to the request to the ngrok url inApp.js
.