diff --git a/README.md b/README.md index db7b6280d..2b422be3a 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ can use one of the many wrappers available on npm, like - [Simple server](#simple-server) - [External HTTP/S server](#external-https-server) - [Multiple servers sharing a single HTTP/S server](#multiple-servers-sharing-a-single-https-server) + - [Client authentication](#client-authentication) - [Server broadcast](#server-broadcast) - [echo.websocket.org demo](#echowebsocketorg-demo) - [Use the Node.js streams API](#use-the-nodejs-streams-api) @@ -249,6 +250,40 @@ server.on('upgrade', function upgrade(request, socket, head) { server.listen(8080); ``` +### Client authentication + +```js +const http = require('http'); +const WebSocket = require('ws'); +const url = require('url'); + +const server = http.createServer(); +const wss = new WebSocket.Server({ noServer: true }); + +wss.on('connection', function(ws, request, client) { + ws.on('message', function(message) { + console.log(`WS message ${message} from user ${client}`); + }); +}); + +server.on('upgrade', function upgrade(request, socket, head) { + authenticate(request, (err, client) => { + if (err || !client) { + socket.destroy(); + return; + } + wss.handleUpgrade(request, socket, head, function done(ws) { + wss.emit('connection', ws, request, client); + }); + }); +}); + +server.listen(8080); +``` + +Also see the provided [example](./examples/express-session-parse) using +`express-session`. + ### Server broadcast A client WebSocket broadcasting to all connected WebSocket clients, including diff --git a/doc/ws.md b/doc/ws.md index 77b3e42e0..ef4ec0fbd 100644 --- a/doc/ws.md +++ b/doc/ws.md @@ -57,7 +57,8 @@ This class represents a WebSocket server. It extends the `EventEmitter`. - `backlog` {Number} The maximum length of the queue of pending connections. - `server` {http.Server|https.Server} A pre-created Node.js HTTP/S server. - `verifyClient` {Function} A function which can be used to validate incoming - connections. See description below. + connections. See description below. (Usage is discouraged: see + [Issue #337](https://github.com/websockets/ws/issues/377#issuecomment-462152231)) - `handleProtocols` {Function} A function which can be used to handle the WebSocket subprotocols. See description below. - `path` {String} Accept only connections matching this path. @@ -75,6 +76,10 @@ started manually. The "noServer" mode allows the WebSocket server to be completly detached from the HTTP/S server. This makes it possible, for example, to share a single HTTP/S server between multiple WebSocket servers. +> **NOTE:** Use of `verifyClient` is discouraged. Rather handle client +> authentication in the `upgrade` event of the HTTP server. See examples for +> more details. + If `verifyClient` is not set then the handshake is automatically accepted. If it is provided with a single argument then that is: diff --git a/examples/express-session-parse/index.js b/examples/express-session-parse/index.js index 761987dc9..4e4c4789c 100644 --- a/examples/express-session-parse/index.js +++ b/examples/express-session-parse/index.js @@ -48,20 +48,20 @@ app.delete('/logout', function(request, response) { // const server = http.createServer(app); -const wss = new WebSocket.Server({ - verifyClient: function(info, done) { - console.log('Parsing session from request...'); - sessionParser(info.req, {}, () => { - console.log('Session is parsed!'); +const wss = new WebSocket.Server({ noServer: true }); - // - // We can reject the connection by returning false to done(). For example, - // reject here if user is unknown. - // - done(info.req.session.userId); +server.on('upgrade', function upgrade(request, socket, head) { + console.log('Parsing session from request...'); + sessionParser(request, {}, () => { + if (!request.session.userId) { + socket.destroy(); + return; + } + console.log('Session is parsed!'); + wss.handleUpgrade(request, socket, head, function done(ws) { + wss.emit('connection', ws, request); }); - }, - server + }); }); wss.on('connection', function(ws, request) { diff --git a/examples/express-session-parse/public/app.js b/examples/express-session-parse/public/app.js index 56abc591a..99a6e5cf2 100644 --- a/examples/express-session-parse/public/app.js +++ b/examples/express-session-parse/public/app.js @@ -1,6 +1,7 @@ (function() { const messages = document.querySelector('#messages'); const wsButton = document.querySelector('#wsButton'); + const wsSendButton = document.querySelector('#wsSendButton'); const logout = document.querySelector('#logout'); const login = document.querySelector('#login'); @@ -50,6 +51,16 @@ }; ws.onclose = function() { showMessage('WebSocket connection closed'); + ws = null; }; }; + + wsSendButton.onclick = function() { + if (!ws) { + showMessage('No WebSocket connection'); + return; + } + ws.send('Hello World!'); + showMessage('Sent "Hello World!"'); + }; })(); diff --git a/examples/express-session-parse/public/index.html b/examples/express-session-parse/public/index.html index c99949c77..c07aa2e87 100644 --- a/examples/express-session-parse/public/index.html +++ b/examples/express-session-parse/public/index.html @@ -15,6 +15,9 @@

Choose an action.

+