From b111b3f327e4b5854cc8aa5b4cc9f2e0090109c7 Mon Sep 17 00:00:00 2001 From: Screeny Date: Fri, 15 Nov 2013 15:16:16 +0100 Subject: [PATCH 1/2] Update README.md --- README.md | 156 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 108 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 931364c..d1d329c 100644 --- a/README.md +++ b/README.md @@ -1,69 +1,129 @@ -Access [Passport.js](http://passportjs.org) user information from [socket.io](http://socket.io) connection. +# passport.socketio +> Access [passport.js](http://passportjs.org) user information from a [socket.io](http://socket.io) connection. -Installation -============ +## Installation ``` npm install passport.socketio ``` -Usage -===== +## Example usage ```javascript - //configure passport and express - - var socketIo = require("socket.io"), +// initialize our modules +var io = require("socket.io")(server), + sessionStore = require('awesomeSessionStore'), // find a working session store (have a look at the readme) passportSocketIo = require("passport.socketio"); - var sio = socketIo.listen(webServer); +// set authorization for socket.io +io.set('authorization', passportSocketIo.authorize({ + cookieParse: express.cookieParse, + key: 'express.sid', // the name of the cookie where express/connect stores its session_id + secret: 'session_secret', // the session_secret to parse the cookie + store: sessionStore, // we NEED to use a sessionstore. no memorystore please + success: onAuthorizeSuccess, // *optional* callback on success - read more below + fail: onAuthorizeFail, // *optional* callback on fail/error - read more below +}); +function onAuthorizeSuccess(data, accept){ + console.log('successful connection to socket.io'); + + // The accept-callback still allows us to decide whether to + // accept the connection or not. + accept(null, true); +} - //except for the optional fail and success the parameter object has the - //same attribute than the session middleware http://www.senchalabs.org/connect/middleware-session.html - - sio.set("authorization", passportSocketIo.authorize({ - cookieParser: express.cookieParser, //or connect.cookieParser - key: 'express.sid', //the cookie where express (or connect) stores its session id. - secret: 'my session secret', //the session secret to parse the cookie - store: mySessionStore, //the session store that express uses - fail: function(data, accept) { // *optional* callbacks on success or fail - accept(null, false); // second param takes boolean on whether or not to allow handshake - }, - success: function(data, accept) { - accept(null, true); - } - })); - - sio.sockets.on("connection", function(socket){ - console.log("user connected: ", socket.handshake.user.name); - - //filter sockets by user... - var userGender = socket.handshake.user.gender, - opposite = userGender === "male" ? "female" : "male"; - - passportSocketIo.filterSocketsByUser(sio, function (user) { - return user.gender === opposite; - }).forEach(function(s){ - s.send("a " + userGender + " has arrived!"); - }); - - }); - +function onAuthorizeFail(data, message, error, accept){ + if(critical) + throw new Error(message); + console.log('failed connection to socket.io:', message); + + // We use this callback to log all of our failed connections. + accept(null, false); +} ``` -__Note:__ in the client-side use `io.connect()` or `io.connect('http://the-same-domain.com')` because Socket.io can work with CORS but the browser will not send the cookies. +## passport.socketio - Options -Develop -======= +### `store` [function] **required**: +*Always* provide one. If you don't know what sessionStore to use, have a look at [this list](https://github.com/senchalabs/connect/wiki#session-stores). +Also be sure to use the same sessionStore or at least a connection to *the same collection/table/whatever*. And don't forget your `express.session()` middleware: +`app.use(express.session({ store: awesomeSessionStore }));` +For further info about this middleware see [the official documentation](http://www.senchalabs.org/connect/session.html#session). - npm install - npm test +### `cookieParser` [function] **required**: +You have to provide your cookieParser from express: `express.cookieParser` -License -======== +### `key` [string] **optional**: +Defaults to `'connect.sid'`. But you're always better of to be sure and set your own key. Don't forget to also change it in your `express.session()`: +`app.use(express.session({ key: 'your.sid-key' }));` -MIT - José F. Romaniello 2012. +### `secret` [string] **optional**: +As with `key`, also the secret you provide is optional. *But:* be sure to have one. That's always safer. You can set it like the key: +`app.use(express.session({ secret: 'pinkie ate my cupcakes!' }));` + +### `passport` [function] **optional**: +Defaults to `require('passport')`. If you want, you can provide your own instance of passport for whatever reason. + +### `success` [function] **optional**: +Callback which will be called everytime a *authorized* user successfuly connects to your socket.io instance. **Always** be sure to accept/reject the connection. +For that, there are two parameters: `function(data[object], accept[function])`. `data` contains all the user-information from passport. +The second parameter is for accepting/rejecting connections. Use it like this: +```javascript +// accept connection +accept(null, true); + +// reject connection (for whatever reason) +accept(null, false); +``` + +### `fail` [function] **optional**: +The name of this callback may be a little confusing. While it is called when a not-authorized-user connects, it is also called when there's a error. +For debugging reasons you are provided with two additional parameters `function(data[object], message[string], error[bool], accept[function])`: +```javascript +/* ... */ +function onAuthorizeFail(data, message, error, accept){ + // error indicates whether the fail is due to an error or just a unauthorized client + if(error){ + throw new Error(message); + } else { + console.log(message); + accept(null, false); // the same accept-method as above + } +} +``` +You can use the `message` parameter for debugging/logging/etc uses. + +## `socket.handshake.user` +This property is always available from inside a `io.on('connection')` handler. If the user is authorized via passport, you can access all the properties from there. +**Plus** you have the `socket.handshake.user.logged_in` property which tells you whether the user is currently authorized or not. + +## Additional methods + +### `passportSocketIo.filterSocketsbyUser` +This function gives you the ability to filter all connected sockets via a user property. Needs two parameters `function(io, function(user))`. Example: +```javascript +passportSocketIo.filterSocketsByUser(io, function(user){ + return user.gender === 'female'; +}).forEach(function(socket){ + socket.send('msg', 'hello, woman!'); +}); +``` + +## Notes: +* Does **NOT** support cookie-based sessions. eg: `express.cookieSession` +* If the connection fails, check if you are requesting from a client via CORS. Check `socket.handshake.xdomain === true` as there are no cookies sent. + +## Contribute +You are always welcome to open an issue or provide a pull-request! +Also check out the unit tests: +```bash +npm test +``` + +## License +Licensed under the MIT-License. +2012-2013 José F. Romaniello. From 2d257bfb1ee3e9aa60abc8ffff73c848fb150ffd Mon Sep 17 00:00:00 2001 From: Screeny Date: Fri, 15 Nov 2013 15:54:47 +0100 Subject: [PATCH 2/2] Update README.md --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d1d329c..6beda21 100644 --- a/README.md +++ b/README.md @@ -91,9 +91,17 @@ function onAuthorizeFail(data, message, error, accept){ throw new Error(message); } else { console.log(message); - accept(null, false); // the same accept-method as above + // the same accept-method as above in the success-callback + accept(null, false); } } + +// or +// This function accepts every client unless there's an error +function onAuthorizeFail(data, message, error, accept){ + console.log(message); + accept(null, !error); +} ``` You can use the `message` parameter for debugging/logging/etc uses.