socketio-jwt
Advanced tools
Comparing version 4.5.0 to 4.5.1
199
lib/index.js
@@ -1,15 +0,16 @@ | ||
var xtend = require('xtend'); | ||
var jwt = require('jsonwebtoken'); | ||
var UnauthorizedError = require('./UnauthorizedError'); | ||
const xtend = require('xtend'); | ||
const jwt = require('jsonwebtoken'); | ||
const UnauthorizedError = require('./UnauthorizedError'); | ||
function noQsMethod(options) { | ||
var defaults = { required: true }; | ||
options = xtend(defaults, options); | ||
function noQsMethod (options) { | ||
const defaults = { required: true }; | ||
options = xtend(defaults, options); | ||
return function (socket) { | ||
var server = this.server || socket.server; | ||
return (socket) => { | ||
'use strict'; // Node 4.x workaround | ||
const server = this.server || socket.server; | ||
if (!server.$emit) { | ||
//then is socket.io 1.0 | ||
var Namespace = Object.getPrototypeOf(server.sockets).constructor; | ||
const Namespace = Object.getPrototypeOf(server.sockets).constructor; | ||
if (!~Namespace.events.indexOf('authenticated')) { | ||
@@ -20,4 +21,5 @@ Namespace.events.push('authenticated'); | ||
if(options.required){ | ||
var auth_timeout = setTimeout(function () { | ||
let auth_timeout = null; | ||
if (options.required) { | ||
auth_timeout = setTimeout(() => { | ||
socket.disconnect('unauthorized'); | ||
@@ -27,42 +29,50 @@ }, options.timeout || 5000); | ||
socket.on('authenticate', function (data) { | ||
if(options.required){ | ||
socket.on('authenticate', (data) => { | ||
if (options.required) { | ||
clearTimeout(auth_timeout); | ||
} | ||
// error handler | ||
var onError = function(err, code) { | ||
if (err) { | ||
code = code || 'unknown'; | ||
var error = new UnauthorizedError(code, { | ||
message: (Object.prototype.toString.call(err) === '[object Object]' && err.message) ? err.message : err | ||
}); | ||
var callback_timeout; | ||
// If callback explicitely set to false, start timeout to disconnect socket | ||
if (options.callback === false || typeof options.callback === "number") { | ||
if (typeof options.callback === "number") { | ||
if (options.callback < 0) { | ||
// If callback is negative(invalid value), make it positive | ||
options.callback = Math.abs(options.callback); | ||
} | ||
const onError = (err, code) => { | ||
if (err) { | ||
code = code || 'unknown'; | ||
const error = new UnauthorizedError(code, { | ||
message: (Object.prototype.toString.call(err) === '[object Object]' && err.message) ? err.message : err | ||
}); | ||
let callback_timeout; | ||
// If callback explicitly set to false, start timeout to disconnect socket | ||
if (options.callback === false || typeof options.callback === 'number') { | ||
if (typeof options.callback === 'number') { | ||
if (options.callback < 0) { | ||
// If callback is negative(invalid value), make it positive | ||
options.callback = Math.abs(options.callback); | ||
} | ||
callback_timeout = setTimeout(function () { | ||
socket.disconnect('unauthorized'); | ||
}, (options.callback === false ? 0 : options.callback)); | ||
} | ||
socket.emit('unauthorized', error, function() { | ||
if (typeof options.callback === "number") { | ||
clearTimeout(callback_timeout); | ||
} | ||
callback_timeout = setTimeout(() => { | ||
socket.disconnect('unauthorized'); | ||
}); | ||
return; // stop logic, socket will be close on next tick | ||
}, (options.callback === false ? 0 : options.callback)); | ||
} | ||
socket.emit('unauthorized', error, () => { | ||
if (typeof options.callback === 'number') { | ||
clearTimeout(callback_timeout); | ||
} | ||
socket.disconnect('unauthorized'); | ||
}); | ||
return; // stop logic, socket will be close on next tick | ||
} | ||
}; | ||
if(!data || typeof data.token !== "string") { | ||
return onError({message: 'invalid token datatype'}, 'invalid_token'); | ||
const token = options.cookie ? socket.request.cookies[options.cookie] : (data ? data.token : undefined); | ||
if (!token || typeof token !== 'string') { | ||
return onError({ message: 'invalid token datatype' }, 'invalid_token'); | ||
} | ||
var onJwtVerificationReady = function(err, decoded) { | ||
// Store encoded JWT | ||
socket[options.encodedPropertyName] = token; | ||
const onJwtVerificationReady = (err, decoded) => { | ||
if (err) { | ||
@@ -73,4 +83,6 @@ return onError(err, 'invalid_token'); | ||
// success handler | ||
var onSuccess = function() { | ||
socket[options.decodedPropertyName] = decoded; | ||
const onSuccess = () => { | ||
socket[options.decodedPropertyName] = options.customDecoded | ||
? options.customDecoded(decoded) | ||
: decoded; | ||
socket.emit('authenticated'); | ||
@@ -81,5 +93,5 @@ if (server.$emit) { | ||
//try getting the current namespace otherwise fallback to all sockets. | ||
var namespace = (server.nsps && socket.nsp && | ||
server.nsps[socket.nsp.name]) || | ||
server.sockets; | ||
const namespace = (server.nsps && socket.nsp && | ||
server.nsps[socket.nsp.name]) || | ||
server.sockets; | ||
@@ -91,3 +103,3 @@ // explicit namespace | ||
if(options.additional_auth && typeof options.additional_auth === 'function') { | ||
if (options.additional_auth && typeof options.additional_auth === 'function') { | ||
options.additional_auth(decoded, onSuccess, onError); | ||
@@ -99,3 +111,3 @@ } else { | ||
var onSecretReady = function(err, secret) { | ||
const onSecretReady = (err, secret) => { | ||
if (err || !secret) { | ||
@@ -105,6 +117,6 @@ return onError(err, 'invalid_secret'); | ||
jwt.verify(data.token, secret, options, onJwtVerificationReady); | ||
jwt.verify(token, secret, options, onJwtVerificationReady); | ||
}; | ||
getSecret(socket.request, options.secret, data.token, onSecretReady); | ||
getSecret(socket.request, options.secret, token, onSecretReady); | ||
}); | ||
@@ -114,5 +126,9 @@ }; | ||
function authorize(options, onConnection) { | ||
options = xtend({ decodedPropertyName: 'decoded_token' }, options); | ||
function authorize (options) { | ||
options = xtend({ decodedPropertyName: 'decoded_token', encodedPropertyName: 'encoded_token' }, options); | ||
if (typeof options.secret !== 'string' && typeof options.secret !== 'function') { | ||
throw new Error(`Provided secret ${options.secret} is invalid, must be of type string or function.`); | ||
} | ||
if (!options.handshake) { | ||
@@ -122,5 +138,5 @@ return noQsMethod(options); | ||
var defaults = { | ||
success: function(data, accept){ | ||
if (data.request) { | ||
const defaults = { | ||
success: (socket, accept) => { | ||
if (socket.request) { | ||
accept(); | ||
@@ -131,4 +147,4 @@ } else { | ||
}, | ||
fail: function(error, data, accept){ | ||
if (data.request) { | ||
fail: (error, socket, accept) => { | ||
if (socket.request) { | ||
accept(error); | ||
@@ -141,14 +157,17 @@ } else { | ||
var auth = xtend(defaults, options); | ||
const auth = xtend(defaults, options); | ||
return function(data, accept){ | ||
var token, error; | ||
var req = data.request || data; | ||
var authorization_header = (req.headers || {}).authorization; | ||
return (socket, accept) => { | ||
'use strict'; // Node 4.x workaround | ||
let token, error; | ||
const handshake = socket.handshake; | ||
const req = socket.request || socket; | ||
const authorization_header = (req.headers || {}).authorization; | ||
if (authorization_header) { | ||
var parts = authorization_header.split(' '); | ||
const parts = authorization_header.split(' '); | ||
if (parts.length == 2) { | ||
var scheme = parts[0], | ||
credentials = parts[1]; | ||
const scheme = parts[0], | ||
credentials = parts[1]; | ||
@@ -162,8 +181,18 @@ if (scheme.toLowerCase() === 'bearer') { | ||
}); | ||
return auth.fail(error, data, accept); | ||
return auth.fail(error, socket, accept); | ||
} | ||
} | ||
//get the token from query string | ||
if (req._query && req._query.token) { | ||
// Check if the header has to include authentication | ||
if (options.auth_header_required && !token) { | ||
return auth.fail(new UnauthorizedError('missing_authorization_header', { | ||
message: 'Server requires Authorization Header' | ||
}), socket, accept); | ||
} | ||
// Get the token from handshake or query string | ||
if (handshake && handshake.query.token) { | ||
token = handshake.query.token; | ||
} | ||
else if (req._query && req._query.token) { | ||
token = req._query.token; | ||
@@ -177,23 +206,27 @@ } | ||
error = new UnauthorizedError('credentials_required', { | ||
message: 'No Authorization header was found' | ||
message: 'no token provided' | ||
}); | ||
return auth.fail(error, data, accept); | ||
return auth.fail(error, socket, accept); | ||
} | ||
var onJwtVerificationReady = function(err, decoded) { | ||
// Store encoded JWT | ||
socket[options.encodedPropertyName] = token; | ||
const onJwtVerificationReady = (err, decoded) => { | ||
if (err) { | ||
error = new UnauthorizedError(err.code || 'invalid_token', err); | ||
return auth.fail(error, data, accept); | ||
return auth.fail(error, socket, accept); | ||
} | ||
data[options.decodedPropertyName] = decoded; | ||
socket[options.decodedPropertyName] = options.customDecoded | ||
? options.customDecoded(decoded) | ||
: decoded; | ||
return auth.success(data, accept); | ||
return auth.success(socket, accept); | ||
}; | ||
var onSecretReady = function(err, secret) { | ||
const onSecretReady = (err, secret) => { | ||
if (err) { | ||
error = new UnauthorizedError(err.code || 'invalid_secret', err); | ||
return auth.fail(error, data, accept); | ||
return auth.fail(error, socket, accept); | ||
} | ||
@@ -208,3 +241,5 @@ | ||
function getSecret(request, secret, token, callback) { | ||
function getSecret (request, secret, token, callback) { | ||
'use strict'; // Node 4.x workaround | ||
if (typeof secret === 'function') { | ||
@@ -215,3 +250,3 @@ if (!token) { | ||
var parts = token.split('.'); | ||
const parts = token.split('.'); | ||
@@ -226,3 +261,3 @@ if (parts.length < 3) { | ||
var decodedToken = jwt.decode(token); | ||
let decodedToken = jwt.decode(token, { complete: true }); | ||
@@ -233,8 +268,14 @@ if (!decodedToken) { | ||
secret(request, decodedToken, callback); | ||
const arity = secret.length; | ||
if (arity == 4) { | ||
secret(request, decodedToken.header, decodedToken.payload, callback); | ||
} else { // arity == 3 | ||
secret(request, decodedToken.payload, callback); | ||
} | ||
} else { | ||
callback(null, secret); | ||
} | ||
}; | ||
} | ||
exports.authorize = authorize; | ||
exports.UnauthorizedError = UnauthorizedError; |
@@ -8,3 +8,3 @@ function UnauthorizedError (code, error) { | ||
code: code, | ||
type: "UnauthorizedError" | ||
type: 'UnauthorizedError' | ||
}; | ||
@@ -11,0 +11,0 @@ } |
{ | ||
"name": "socketio-jwt", | ||
"version": "4.5.0", | ||
"version": "4.5.1", | ||
"description": "authenticate socket.io connections using JWTs", | ||
"main": "lib/index.js", | ||
"types": "./types/index.d.ts", | ||
"keywords": [ | ||
@@ -25,17 +26,18 @@ "socket", | ||
"dependencies": { | ||
"jsonwebtoken": "^5.0.0", | ||
"jsonwebtoken": "^8.3.0", | ||
"xtend": "~2.1.2" | ||
}, | ||
"devDependencies": { | ||
"body-parser": "~1.13.3", | ||
"express": "~4.10.6", | ||
"mocha": "~1.17.0", | ||
"passport-local": "~0.1.6", | ||
"request": "~2.19.0", | ||
"serve-static": "^1.7.1", | ||
"@types/socket.io": "~1.4.29", | ||
"body-parser": "~1.17.1", | ||
"express": "~4.15.2", | ||
"mocha": "~3.2.0", | ||
"request": "~2.81.0", | ||
"serve-static": "^1.13.2", | ||
"q": "^1.5.1", | ||
"server-destroy": "~1.0.1", | ||
"should": "~1.2.2", | ||
"socket.io": "^1.0.4", | ||
"socket.io-client": "^1.0.4" | ||
"should": "~11.2.1", | ||
"socket.io": "^1.7.3", | ||
"socket.io-client": "^1.7.3" | ||
} | ||
} |
256
README.md
@@ -1,12 +0,37 @@ | ||
[![Build Status](https://travis-ci.org/auth0/socketio-jwt.svg)](https://travis-ci.org/auth0/socketio-jwt) | ||
# socketio-jwt | ||
Authenticate socket.io incoming connections with JWTs. This is useful if you are build a single page application and you are not using cookies as explained in this blog post: [Cookies vs Tokens. Getting auth right with Angular.JS](http://blog.auth0.com/2014/01/07/angularjs-authentication-with-cookies-vs-token/). | ||
[![All Contributors](https://img.shields.io/badge/all_contributors-5-orange.svg?style=flat-square)](#contributors) | ||
<img src="https://img.shields.io/badge/community-driven-brightgreen.svg"/> <br> | ||
### Contributors | ||
Thanks goes to these wonderful people who contribute(d) or maintain(ed) this repo ([emoji key](https://allcontributors.org/docs/en/emoji-key)): | ||
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --> | ||
<!-- prettier-ignore --> | ||
<table> | ||
<tr> | ||
<td align="center"><a href="https://twitter.com/beardaway"><img src="https://avatars3.githubusercontent.com/u/11062800?v=4" width="100px;" alt="Conrad Sopala"/><br /><sub><b>Conrad Sopala</b></sub></a><br /><a href="#review-beardaway" title="Reviewed Pull Requests">👀</a> <a href="#maintenance-beardaway" title="Maintenance">🚧</a></td> | ||
<td align="center"><a href="https://github.com/Annyv2"><img src="https://avatars3.githubusercontent.com/u/5016479?v=4" width="100px;" alt="Annyv2"/><br /><sub><b>Annyv2</b></sub></a><br /><a href="https://github.com/auth0-community/auth0-socketio-jwt/commits?author=Annyv2" title="Code">💻</a></td> | ||
<td align="center"><a href="https://github.com/Amialc"><img src="https://avatars0.githubusercontent.com/u/1114365?v=4" width="100px;" alt="Vladyslav Martynets"/><br /><sub><b>Vladyslav Martynets</b></sub></a><br /><a href="https://github.com/auth0-community/auth0-socketio-jwt/commits?author=Amialc" title="Code">💻</a></td> | ||
<td align="center"><a href="https://github.com/pose"><img src="https://avatars3.githubusercontent.com/u/419703?v=4" width="100px;" alt="Alberto Pose"/><br /><sub><b>Alberto Pose</b></sub></a><br /><a href="https://github.com/auth0-community/auth0-socketio-jwt/commits?author=pose" title="Code">💻</a></td> | ||
<td align="center"><a href="https://github.com/Root-Core"><img src="https://avatars2.githubusercontent.com/u/5329652?v=4" width="100px;" alt="Root-Core"/><br /><sub><b>Root-Core</b></sub></a><br /><a href="https://github.com/auth0-community/auth0-socketio-jwt/commits?author=Root-Core" title="Code">💻</a></td> | ||
</tr> | ||
</table> | ||
<!-- ALL-CONTRIBUTORS-LIST:END --> | ||
## Intro | ||
Authenticate socket.io incoming connections with JWTs. This is useful if you are building a single page application and you are not using cookies as explained in this blog post: [Cookies vs Tokens. Getting auth right with Angular.JS](http://blog.auth0.com/2014/01/07/angularjs-authentication-with-cookies-vs-token/). | ||
This repo is supported and maintained by Community Developers, not Auth0. For more information about different support levels check https://auth0.com/docs/support/matrix . | ||
## Installation | ||
``` | ||
```bash | ||
npm install socketio-jwt | ||
``` | ||
## Example usage | ||
## Usage | ||
@@ -19,5 +44,6 @@ ```javascript | ||
timeout: 15000 // 15 seconds to send the authentication message | ||
})).on('authenticated', function(socket) { | ||
})) | ||
.on('authenticated', (socket) => { | ||
//this socket is authenticated, we are good to handle more events from it. | ||
console.log('hello! ' + socket.decoded_token.name); | ||
console.log(`hello! ${socket.decoded_token.name}`); | ||
}); | ||
@@ -28,24 +54,31 @@ ``` | ||
__Client side__: | ||
**Client side** | ||
```javascript | ||
var socket = io.connect('http://localhost:9000'); | ||
socket.on('connect', function (socket) { | ||
const socket = io.connect('http://localhost:9000'); | ||
socket.on('connect', () => { | ||
socket | ||
.on('authenticated', function () { | ||
.emit('authenticate', { token: jwt }) //send the jwt | ||
.on('authenticated', () => { | ||
//do other things | ||
}) | ||
.emit('authenticate', {token: jwt}); //send the jwt | ||
.on('unauthorized', (msg) => { | ||
console.log(`unauthorized: ${JSON.stringify(msg.data)}`); | ||
throw new Error(msg.data.type); | ||
}) | ||
}); | ||
``` | ||
## One roundtrip | ||
### One roundtrip | ||
The previous approach uses a second roundtrip to send the jwt, there is a way you can authenticate on the handshake by sending the JWT as a query string, the caveat is that intermediary HTTP servers can log the url. | ||
The previous approach uses a second roundtrip to send the jwt. There is a way you can authenticate on the handshake by sending the JWT as a query string, the caveat is that intermediary HTTP servers can log the url. | ||
```javascript | ||
var io = require("socket.io")(server); | ||
var socketioJwt = require("socketio-jwt"); | ||
const io = require('socket.io')(server); | ||
const socketioJwt = require('socketio-jwt'); | ||
``` | ||
//// With socket.io < 1.0 //// | ||
With socket.io < 1.0: | ||
```javascript | ||
io.set('authorization', socketioJwt.authorize({ | ||
@@ -55,5 +88,11 @@ secret: 'your secret or public key', | ||
})); | ||
////////////////////////////// | ||
//// With socket.io >= 1.0 //// | ||
io.on('connection', (socket) => { | ||
console.log('hello!', socket.handshake.decoded_token.name); | ||
}); | ||
``` | ||
With socket.io >= 1.0: | ||
```javascript | ||
io.use(socketioJwt.authorize({ | ||
@@ -63,11 +102,6 @@ secret: 'your secret or public key', | ||
})); | ||
/////////////////////////////// | ||
io.on('connection', function (socket) { | ||
// in socket.io < 1.0 | ||
console.log('hello!', socket.handshake.decoded_token.name); | ||
// in socket.io 1.0 | ||
console.log('hello! ', socket.decoded_token.name); | ||
}) | ||
io.on('connection', (socket) => { | ||
console.log('hello!', socket.decoded_token.name); | ||
}); | ||
``` | ||
@@ -77,3 +111,3 @@ | ||
__Client side__: | ||
**Client side** | ||
@@ -83,26 +117,50 @@ Append the jwt token using query string: | ||
```javascript | ||
var socket = io.connect('http://localhost:9000', { | ||
'query': 'token=' + your_jwt | ||
const socket = io.connect('http://localhost:9000', { | ||
query: `token=${your_jwt}` | ||
}); | ||
``` | ||
## Handling token expiration | ||
Append the jwt token using 'Authorization Header' (Bearer Token): | ||
__Server side__: | ||
```javascript | ||
const socket = io.connect('http://localhost:9000', { | ||
extraHeaders: { Authorization: `Bearer ${your_jwt}` } | ||
}); | ||
``` | ||
When you sign the token with an expiration time: | ||
Both options can be combined or used optionally. | ||
### Authorization Header Requirement | ||
Require Bearer Tokens to be passed in as an Authorization Header | ||
**Server side**: | ||
```javascript | ||
var token = jwt.sign(user_profile, jwt_secret, {expiresInMinutes: 60}); | ||
io.use(socketioJwt.authorize({ | ||
secret: 'your secret or public key', | ||
handshake: true, | ||
auth_header_required: true | ||
})); | ||
``` | ||
Your client-side code should handle it as below. | ||
### Handling token expiration | ||
__Client side__: | ||
**Server side** | ||
When you sign the token with an expiration time (example: 60 minutes): | ||
```javascript | ||
socket.on("error", function(error) { | ||
if (error.type == "UnauthorizedError" || error.code == "invalid_token") { | ||
const token = jwt.sign(user_profile, jwt_secret, { expiresIn: 60*60 }); | ||
``` | ||
Your client-side code should handle it as below: | ||
**Client side** | ||
```javascript | ||
socket.on('unauthorized', (error) => { | ||
if (error.data.type == 'UnauthorizedError' || error.data.code == 'invalid_token') { | ||
// redirect user to login page perhaps? | ||
console.log("User's token has expired"); | ||
console.log('User token has expired'); | ||
} | ||
@@ -112,11 +170,11 @@ }); | ||
## Handling invalid token | ||
### Handling invalid token | ||
Token sent by client is invalid. | ||
__Server side__: | ||
**Server side**: | ||
No further configuration needed. | ||
__Client side__: | ||
**Client side** | ||
@@ -126,7 +184,7 @@ Add a callback client-side to execute socket disconnect server-side. | ||
```javascript | ||
socket.on("unauthorized", function(error, callback) { | ||
if (error.data.type == "UnauthorizedError" || error.data.code == "invalid_token") { | ||
socket.on('unauthorized', (error, callback) => { | ||
if (error.data.type == 'UnauthorizedError' || error.data.code == 'invalid_token') { | ||
// redirect user to login page perhaps or execute callback: | ||
callback(); | ||
console.log("User's token has expired"); | ||
console.log('User token has expired'); | ||
} | ||
@@ -136,3 +194,3 @@ }); | ||
__Server side__: | ||
**Server side** | ||
@@ -145,11 +203,11 @@ To disconnect socket server-side without client-side callback: | ||
// No client-side callback, terminate connection server-side | ||
callback: false | ||
callback: false | ||
})) | ||
``` | ||
__Client side__: | ||
**Client side** | ||
Nothing needs to be changed client-side if callback is false. | ||
__Server side__: | ||
**Server side** | ||
@@ -162,16 +220,16 @@ To disconnect socket server-side while giving client-side 15 seconds to execute callback: | ||
// Delay server-side socket disconnect to wait for client-side callback | ||
callback: 15000 | ||
callback: 15000 | ||
})) | ||
``` | ||
Your client-side code should handle it as below. | ||
Your client-side code should handle it as below: | ||
__Client side__: | ||
**Client side** | ||
```javascript | ||
socket.on("unauthorized", function(error, callback) { | ||
if (error.data.type == "UnauthorizedError" || error.data.code == "invalid_token") { | ||
socket.on('unauthorized', (error, callback) => { | ||
if (error.data.type == 'UnauthorizedError' || error.data.code == 'invalid_token') { | ||
// redirect user to login page perhaps or execute callback: | ||
callback(); | ||
console.log("User's token has expired"); | ||
console.log('User token has expired'); | ||
} | ||
@@ -181,4 +239,5 @@ }); | ||
## Getting the secret dynamically | ||
You can pass a function instead of an string when configuring secret. | ||
### Getting the secret dynamically | ||
You can pass a function instead of a string when configuring secret. | ||
This function receives the request, the decoded token and a callback. This | ||
@@ -188,6 +247,6 @@ way, you are allowed to use a different secret based on the request and / or | ||
__Server side__: | ||
**Server side** | ||
```javascript | ||
var SECRETS = { | ||
const SECRETS = { | ||
'user1': 'secret 1', | ||
@@ -198,4 +257,4 @@ 'user2': 'secret 2' | ||
io.use(socketioJwt.authorize({ | ||
secret: function(request, decodedToken, callback) { | ||
// SECRETS[decodedToken.userId] will be used a a secret or | ||
secret: (request, decodedToken, callback) => { | ||
// SECRETS[decodedToken.userId] will be used as a secret or | ||
// public key for connection user. | ||
@@ -207,3 +266,25 @@ | ||
})); | ||
``` | ||
### Altering the value of the decoded token | ||
You can pass a function to change the value of the decoded token | ||
```javascript | ||
io.on( | ||
'connection', | ||
socketIOJwt.authorize({ | ||
customDecoded: (decoded) => { | ||
return "new decoded token"; | ||
}, | ||
secret: 'my_secret_key', | ||
decodedPropertyName: 'my_decoded_token', | ||
}), | ||
); | ||
io.on('authenticated', (socket) => { | ||
console.log(socket.my_decoded_token); // new decoded token | ||
}); | ||
``` | ||
@@ -213,5 +294,7 @@ | ||
You are always welcome to open an issue or provide a pull-request! | ||
Feel like contributing to this repo? We're glad to hear that! Before you start contributing please visit our [Contributing Guideline](https://github.com/auth0-community/getting-started/blob/master/CONTRIBUTION.md). | ||
Also check out the unit tests: | ||
Here you can also find the [PR template](https://github.com/auth0-community/socketio-jwt/blob/master/PULL_REQUEST_TEMPLATE.md) to fill once creating a PR. It will automatically appear once you open a pull request. | ||
You might run the unit tests, before creating a PR: | ||
```bash | ||
@@ -221,12 +304,51 @@ npm test | ||
## Issue Reporting | ||
## Issues Reporting | ||
If you have found a bug or if you have a feature request, please report them at this repository issues section. Please do not report security vulnerabilities on the public GitHub issue tracker. The [Responsible Disclosure Program](https://auth0.com/whitehat) details the procedure for disclosing security issues. | ||
Spotted a bug or any other kind of issue? We're just humans and we're always waiting for constructive feedback! Check our section on how to [report issues](https://github.com/auth0-community/getting-started/blob/master/CONTRIBUTION.md#issues)! | ||
## Author | ||
Here you can also find the [Issue template](https://github.com/auth0-community/socketio-jwt/blob/master/ISSUE_TEMPLATE.md) to fill once opening a new issue. It will automatically appear once you create an issue. | ||
[Auth0](auth0.com) | ||
## Repo Community | ||
Feel like PRs and issues are not enough? Want to dive into further discussion about the tool? We created topics for each Auth0 Community repo so that you can join discussion on stack available on our repos. Here it is for this one: [socketio-jwt](https://community.auth0.com/t/auth0-community-oss-socketio-jwt/20024) | ||
<a href="https://community.auth0.com/"> | ||
<img src="/assets/join_auth0_community_badge.png"/> | ||
</a> | ||
## License | ||
This project is licensed under the MIT license. See the [LICENSE](LICENSE) file for more info. | ||
This project is licensed under the MIT license. See the [LICENSE](https://github.com/auth0-community/socketio-jwt/blob/master/LICENSE) file for more info. | ||
## What is Auth0? | ||
Auth0 helps you to: | ||
* Add authentication with [multiple authentication sources](https://docs.auth0.com/identityproviders), either social like | ||
* Microsoft | ||
* GitHub | ||
* Box | ||
* Salesforce | ||
* etc. | ||
**or** enterprise identity systems like: | ||
* Windows Azure AD | ||
* Google Apps | ||
* Active Directory | ||
* ADFS | ||
* Any SAML Identity Provider | ||
* Add authentication through more traditional [username/password databases](https://docs.auth0.com/mysql-connection-tutorial) | ||
* Add support for [linking different user accounts](https://docs.auth0.com/link-accounts) with the same user | ||
* Support for generating signed [JSON Web Tokens](https://docs.auth0.com/jwt) to call your APIs and create user identity flow securely | ||
* Analytics of how, when and where users are logging in | ||
* Pull data from other sources and add it to user profile, through [JavaScript rules](https://docs.auth0.com/rules) | ||
## Create a free Auth0 account | ||
* Go to [Auth0 website](https://auth0.com/signup) | ||
* Hit the **SIGN UP** button in the upper-right corner |
@@ -1,22 +0,50 @@ | ||
var fixture = require('./fixture/namespace'); | ||
var request = require('request'); | ||
var io = require('socket.io-client'); | ||
const fixture = require('./fixture/namespace'); | ||
const request = require('request'); | ||
const io = require('socket.io-client'); | ||
describe('authorizer with namespaces', function () { | ||
describe('authorizer with namespaces', () => { | ||
//start and stop the server | ||
before(fixture.start); | ||
after(fixture.stop); | ||
describe('when the user is not logged in', function () { | ||
describe('when the user is not logged in', () => { | ||
it('should be able to connect to the default namespace', function (done){ | ||
var socket = io.connect('http://localhost:9000'); | ||
socket.once('hi', done); | ||
it('should be able to connect to the default namespace', (done) => { | ||
io.connect('http://localhost:9000') | ||
.once('hi', () => done()) | ||
.on('error', done); | ||
}); | ||
it('should not be able to connect to the admin namespace', function (done){ | ||
var socket = io.connect('http://localhost:9000/admin'); | ||
socket.once('disconnect', function () { | ||
it('should not be able to connect to the admin namespace', (done) => { | ||
io.connect('http://localhost:9000/admin') | ||
.once('disconnect', () => done()) | ||
.once('hi admin', () => done(new Error('unauthenticated client was able to connect to the admin namespace'))); | ||
}); | ||
it('should not be able to connect to the admin_hs namespace', (done) => { | ||
io.connect('http://localhost:9000/admin_hs') | ||
.once('hi admin', () => done(new Error('unauthenticated client was able to connect to the admin_hs namespace'))) | ||
.on('error', (err) => { | ||
if (err === 'Invalid namespace') { // SocketIO throws this error, if auth failed | ||
return; | ||
} else if (err && err.type == 'UnauthorizedError') { | ||
done(); | ||
} else { | ||
done(err); | ||
} | ||
}); | ||
}); | ||
}); | ||
describe('when the user is logged in', () => { | ||
beforeEach((done) => { | ||
request.post({ | ||
url: 'http://localhost:9000/login', | ||
form: { username: 'jose', password: 'Pa123' }, | ||
json: true | ||
}, (err, resp, body) => { | ||
this.token = body.token; | ||
done(); | ||
@@ -26,7 +54,18 @@ }); | ||
it('should do the authentication and connect', (done) => { | ||
io.connect('http://localhost:9000/admin', { forceNew: true }) | ||
.on('hi admin', () => done()) | ||
.emit('authenticate', { token: this.token }); | ||
}); | ||
it('should do the authentication and connect without "forceNew"', (done) => { | ||
io.connect('http://localhost:9000/admin', { forceNew: false }) | ||
.on('hi admin', () => done()) | ||
.emit('authenticate', { token: this.token }); | ||
}); | ||
}); | ||
describe('when the user is logged in', function() { | ||
describe('when the user is logged in via handshake', () => { | ||
beforeEach(function (done) { | ||
beforeEach((done) => { | ||
request.post({ | ||
@@ -36,21 +75,19 @@ url: 'http://localhost:9000/login', | ||
json: true | ||
}, function (err, resp, body) { | ||
}, (err, resp, body) => { | ||
this.token = body.token; | ||
done(); | ||
}.bind(this)); | ||
}); | ||
}); | ||
it('should do the handshake and connect', function (done){ | ||
var socket = io.connect('http://localhost:9000/admin', { | ||
'forceNew': true, | ||
}); | ||
var token = this.token; | ||
socket.on('connect', function(){ | ||
socket.on('authenticated', function () { | ||
done(); | ||
}).emit('authenticate', { token: token }); | ||
}); | ||
it('should do the handshake and connect', (done) => { | ||
io.connect('http://localhost:9000/admin_hs', { forceNew: true, query: 'token=' + this.token }) | ||
.once('hi admin', () => done()); | ||
}); | ||
it('should do the handshake and connect without "forceNew"', (done) => { | ||
io.connect('http://localhost:9000/admin_hs', { forceNew: false, query: 'token=' + this.token }) | ||
.once('hi admin', () => done()); | ||
}); | ||
}); | ||
}); |
@@ -1,12 +0,10 @@ | ||
var fixture = require('./fixture'); | ||
var request = require('request'); | ||
var io = require('socket.io-client'); | ||
const fixture = require('./fixture'); | ||
const request = require('request'); | ||
const io = require('socket.io-client'); | ||
describe('authorizer without querystring', function () { | ||
describe('authorizer without querystring', () => { | ||
//start and stop the server | ||
before(function (done) { | ||
fixture.start({ | ||
handshake: false | ||
} , done); | ||
before((done) => { | ||
fixture.start({ handshake: false }, done); | ||
}); | ||
@@ -16,22 +14,14 @@ | ||
describe('when the user is not logged in', function () { | ||
describe('when the user is not logged in', () => { | ||
it('should close the connection after a timeout if no auth message is received', function (done){ | ||
var socket = io.connect('http://localhost:9000', { | ||
forceNew: true | ||
}); | ||
socket.once('disconnect', function () { | ||
done(); | ||
}); | ||
it('should close the connection after a timeout if no auth message is received', (done) => { | ||
io.connect('http://localhost:9000', { forceNew: true }) | ||
.once('disconnect', () => done()); | ||
}); | ||
it('should not respond echo', function (done){ | ||
var socket = io.connect('http://localhost:9000', { | ||
'forceNew':true, | ||
}); | ||
it('should not respond echo', (done) => { | ||
io.connect('http://localhost:9000', { forceNew: true }) | ||
.on('echo-response', () => done(new Error('this should not happen'))) | ||
.emit('echo', { hi: 123 }); | ||
socket.on('echo-response', function () { | ||
done(new Error('this should not happen')); | ||
}).emit('echo', { hi: 123 }); | ||
setTimeout(done, 1200); | ||
@@ -42,5 +32,5 @@ }); | ||
describe('when the user is logged in', function() { | ||
describe('when the user is logged in', () => { | ||
beforeEach(function (done) { | ||
beforeEach((done) => { | ||
request.post({ | ||
@@ -50,21 +40,18 @@ url: 'http://localhost:9000/login', | ||
json: true | ||
}, function (err, resp, body) { | ||
}, (err, resp, body) => { | ||
this.token = body.token; | ||
done(); | ||
}.bind(this)); | ||
}); | ||
}); | ||
it('should do the handshake and connect', function (done){ | ||
var socket = io.connect('http://localhost:9000', { | ||
'forceNew':true, | ||
}); | ||
var token = this.token; | ||
socket.on('connect', function(){ | ||
socket.on('echo-response', function () { | ||
it('should do the authentication and connect', (done) => { | ||
const socket = io.connect('http://localhost:9000', { forceNew: true }); | ||
socket | ||
.on('echo-response', () => { | ||
socket.close(); | ||
done(); | ||
}).on('authenticated', function () { | ||
socket.emit('echo'); | ||
}).emit('authenticate', { token: token }); | ||
}); | ||
}) | ||
.on('authenticated', () => { socket.emit('echo'); }) | ||
.emit('authenticate', { token: this.token }); | ||
}); | ||
@@ -71,0 +58,0 @@ }); |
@@ -1,12 +0,12 @@ | ||
var fixture = require('./fixture/secret_function'); | ||
var request = require('request'); | ||
var io = require('socket.io-client'); | ||
const fixture = require('./fixture/secret_function'); | ||
const request = require('request'); | ||
const io = require('socket.io-client'); | ||
describe('authorizer with secret function', function () { | ||
describe('authorizer with secret function', () => { | ||
//start and stop the server | ||
before(function (done) { | ||
before((done) => { | ||
fixture.start({ | ||
handshake: false | ||
} , done); | ||
}, done); | ||
}); | ||
@@ -16,29 +16,19 @@ | ||
describe('when the user is not logged in', function () { | ||
describe('when the user is not logged in', () => { | ||
describe('and when token is not valid', function() { | ||
beforeEach(function (done) { | ||
describe('and when token is not valid', () => { | ||
beforeEach((done) => { | ||
request.post({ | ||
url: 'http://localhost:9000/login', | ||
json: { username: 'invalid_signature', password: 'Pa123' } | ||
}, function (err, resp, body) { | ||
}, (err, resp, body) => { | ||
this.invalidToken = body.token; | ||
done(); | ||
}.bind(this)); | ||
}); | ||
}); | ||
it('should emit unauthorized', function (done){ | ||
var socket = io.connect('http://localhost:9000', { | ||
'forceNew':true, | ||
}); | ||
var invalidToken = this.invalidToken; | ||
socket.on('unauthorized', function() { | ||
done(); | ||
}); | ||
socket.on('connect', function(){ | ||
socket | ||
.emit('authenticate', { token: invalidToken + 'ass' }) | ||
}); | ||
it('should emit unauthorized', (done) => { | ||
io.connect('http://localhost:9000', { forceNew: true }) | ||
.on('unauthorized', () => done()) | ||
.emit('authenticate', { token: this.invalidToken + 'ass' }) | ||
}); | ||
@@ -49,28 +39,24 @@ }); | ||
describe('when the user is logged in', function() { | ||
describe('when the user is logged in', () => { | ||
beforeEach(function (done) { | ||
beforeEach((done) => { | ||
request.post({ | ||
url: 'http://localhost:9000/login', | ||
json: { username: 'valid_signature', password: 'Pa123' } | ||
}, function (err, resp, body) { | ||
}, (err, resp, body) => { | ||
this.token = body.token; | ||
done(); | ||
}.bind(this)); | ||
}); | ||
}); | ||
it('should do the handshake and connect', function (done){ | ||
var socket = io.connect('http://localhost:9000', { | ||
'forceNew':true, | ||
}); | ||
var token = this.token; | ||
socket.on('connect', function(){ | ||
socket.on('echo-response', function () { | ||
it('should do the authentication and connect', (done) => { | ||
const socket = io.connect('http://localhost:9000', { forceNew: true }); | ||
socket | ||
.on('echo-response', () => { | ||
socket.close(); | ||
done(); | ||
}).on('authenticated', function () { | ||
socket.emit('echo'); | ||
}) | ||
.emit('authenticate', { token: token }) | ||
}); | ||
.on('authenticated', () => { socket.emit('echo'); }) | ||
.emit('authenticate', { token: this.token }); | ||
}); | ||
@@ -77,0 +63,0 @@ }); |
@@ -1,6 +0,6 @@ | ||
var fixture = require('./fixture/secret_function'); | ||
var request = require('request'); | ||
var io = require('socket.io-client'); | ||
const fixture = require('./fixture/secret_function'); | ||
const request = require('request'); | ||
const io = require('socket.io-client'); | ||
describe('authorizer with secret function', function () { | ||
describe('authorizer with secret function', () => { | ||
@@ -11,12 +11,10 @@ //start and stop the server | ||
describe('when the user is not logged in', function () { | ||
describe('when the user is not logged in', () => { | ||
it('should emit error with unauthorized handshake', function (done){ | ||
var socket = io.connect('http://localhost:9000?token=boooooo', { | ||
'forceNew': true | ||
}); | ||
it('should emit error with unauthorized handshake', (done) => { | ||
const socket = io.connect('http://localhost:9000?token=boooooo', { forceNew: true }); | ||
socket.on('error', function(err){ | ||
err.message.should.eql("jwt malformed"); | ||
err.code.should.eql("invalid_token"); | ||
socket.on('error', (err) => { | ||
err.message.should.eql('jwt malformed'); | ||
err.code.should.eql('invalid_token'); | ||
socket.close(); | ||
@@ -29,44 +27,50 @@ done(); | ||
describe('when the user is logged in', function() { | ||
describe('when the user is logged in', () => { | ||
beforeEach(function (done) { | ||
beforeEach((done) => { | ||
request.post({ | ||
url: 'http://localhost:9000/login', | ||
json: { username: 'valid_signature', password: 'Pa123' } | ||
}, function (err, resp, body) { | ||
}, (err, resp, body) => { | ||
this.token = body.token; | ||
done(); | ||
}.bind(this)); | ||
}); | ||
}); | ||
it('should do the handshake and connect', function (done){ | ||
var socket = io.connect('http://localhost:9000', { | ||
'forceNew':true, | ||
'query': 'token=' + this.token | ||
it('should do the handshake and connect', (done) => { | ||
const socket = io.connect('http://localhost:9000', { | ||
forceNew: true, | ||
query: 'token=' + this.token | ||
}); | ||
socket.on('connect', function(){ | ||
socket.close(); | ||
done(); | ||
}).on('error', done); | ||
socket | ||
.on('connect', () => { | ||
socket.close(); | ||
done(); | ||
}) | ||
.on('error', done); | ||
}); | ||
}); | ||
describe('unsigned token', function() { | ||
beforeEach(function () { | ||
describe('unsigned token', () => { | ||
beforeEach(() => { | ||
this.token = 'eyJhbGciOiJub25lIiwiY3R5IjoiSldUIn0.eyJuYW1lIjoiSm9obiBGb28ifQ.'; | ||
}); | ||
it('should not do the handshake and connect', function (done){ | ||
var socket = io.connect('http://localhost:9000', { | ||
'forceNew':true, | ||
'query': 'token=' + this.token | ||
it('should not do the handshake and connect', (done) => { | ||
const socket = io.connect('http://localhost:9000', { | ||
forceNew: true, | ||
query: 'token=' + this.token | ||
}); | ||
socket.on('connect', function () { | ||
socket.close(); | ||
done(new Error('this shouldnt happen')); | ||
}).on('error', function (err) { | ||
socket.close(); | ||
err.message.should.eql("jwt signature is required"); | ||
done(); | ||
}); | ||
socket | ||
.on('connect', () => { | ||
socket.close(); | ||
done(new Error('this shouldnt happen')); | ||
}) | ||
.on('error', (err) => { | ||
socket.close(); | ||
err.message.should.eql('jwt signature is required'); | ||
done(); | ||
}); | ||
}); | ||
@@ -73,0 +77,0 @@ }); |
@@ -1,21 +0,20 @@ | ||
var fixture = require('./fixture'); | ||
var request = require('request'); | ||
var io = require('socket.io-client'); | ||
const Q = require('q'); | ||
const fixture = require('./fixture'); | ||
const request = require('request'); | ||
const io = require('socket.io-client'); | ||
describe('authorizer', function () { | ||
describe('authorizer', () => { | ||
//start and stop the server | ||
before(fixture.start); | ||
before((done) => { fixture.start({ }, done) }); | ||
after(fixture.stop); | ||
describe('when the user is not logged in', function () { | ||
it('should emit error with unauthorized handshake', function (done){ | ||
var socket = io.connect('http://localhost:9000?token=boooooo', { | ||
'forceNew': true | ||
describe('when the user is not logged in', () => { | ||
it('should emit error with unauthorized handshake', (done) => { | ||
const socket = io.connect('http://localhost:9000?token=boooooo', { | ||
forceNew: true | ||
}); | ||
socket.on('error', function(err){ | ||
err.message.should.eql("jwt malformed"); | ||
err.code.should.eql("invalid_token"); | ||
socket.on('error', (err) => { | ||
err.message.should.eql('jwt malformed'); | ||
err.code.should.eql('invalid_token'); | ||
socket.close(); | ||
@@ -25,8 +24,6 @@ done(); | ||
}); | ||
}); | ||
describe('when the user is logged in', function() { | ||
beforeEach(function (done) { | ||
describe('when the user is logged in', () => { | ||
before((done) => { | ||
request.post({ | ||
@@ -36,41 +33,111 @@ url: 'http://localhost:9000/login', | ||
json: true | ||
}, function (err, resp, body) { | ||
}, (err, resp, body) => { | ||
this.token = body.token; | ||
done(); | ||
}.bind(this)); | ||
}); | ||
}); | ||
it('should do the handshake and connect', function (done){ | ||
var socket = io.connect('http://localhost:9000', { | ||
'forceNew':true, | ||
'query': 'token=' + this.token | ||
describe('authorizer disallows query string token when specified in startup options', () => { | ||
before((done) => { | ||
Q.ninvoke(fixture, 'stop') | ||
.then(() => Q.ninvoke(fixture, 'start', { auth_header_required: true })) | ||
.done(done); | ||
}); | ||
socket.on('connect', function(){ | ||
socket.close(); | ||
done(); | ||
}).on('error', done); | ||
after((done) => { | ||
Q.ninvoke(fixture, 'stop') | ||
.then(() => Q.ninvoke(fixture, 'start', { })) | ||
.done(done); | ||
}); | ||
it('auth headers are supported', (done) => { | ||
const socket = io.connect('http://localhost:9000', { | ||
forceNew: true, | ||
extraHeaders: { Authorization: 'Bearer ' + this.token} | ||
}); | ||
socket | ||
.on('connect', () => { | ||
socket.close(); | ||
done(); | ||
}) | ||
.on('error', done); | ||
}); | ||
it('auth token in query string is disallowed', (done) => { | ||
const socket = io.connect('http://localhost:9000', { | ||
forceNew: true, | ||
query: 'token=' + this.token | ||
}); | ||
socket.on('error', (err) => { | ||
err.message.should.eql('Server requires Authorization Header'); | ||
err.code.should.eql('missing_authorization_header'); | ||
socket.close(); | ||
done(); | ||
}); | ||
}); | ||
}) | ||
describe('authorizer all auth types allowed', () => { | ||
before((done) => { | ||
Q.ninvoke(fixture, 'stop') | ||
.then(() => Q.ninvoke(fixture, 'start', {})) | ||
.done(done); | ||
}) | ||
it('auth headers are supported', (done) => { | ||
const socket = io.connect('http://localhost:9000', { | ||
forceNew: true, | ||
extraHeaders: { Authorization: 'Bearer ' + this.token } | ||
}); | ||
socket | ||
.on('connect', () => { | ||
socket.close(); | ||
done(); | ||
}) | ||
.on('error', done); | ||
}); | ||
it('should do the handshake and connect', (done) => { | ||
const socket = io.connect('http://localhost:9000', { | ||
forceNew: true, | ||
query: 'token=' + this.token | ||
}); | ||
socket | ||
.on('connect', () => { | ||
socket.close(); | ||
done(); | ||
}) | ||
.on('error', done); | ||
}); | ||
}); | ||
}); | ||
describe('unsgined token', function() { | ||
beforeEach(function () { | ||
describe('unsigned token', () => { | ||
beforeEach(() => { | ||
this.token = 'eyJhbGciOiJub25lIiwiY3R5IjoiSldUIn0.eyJuYW1lIjoiSm9obiBGb28ifQ.'; | ||
}); | ||
it('should not do the handshake and connect', function (done){ | ||
var socket = io.connect('http://localhost:9000', { | ||
'forceNew':true, | ||
'query': 'token=' + this.token | ||
it('should not do the handshake and connect', (done) => { | ||
const socket = io.connect('http://localhost:9000', { | ||
forceNew: true, | ||
query: 'token=' + this.token | ||
}); | ||
socket.on('connect', function () { | ||
socket.close(); | ||
done(new Error('this shouldnt happen')); | ||
}).on('error', function (err) { | ||
socket.close(); | ||
err.message.should.eql("jwt signature is required"); | ||
done(); | ||
}); | ||
socket | ||
.on('connect', () => { | ||
socket.close(); | ||
done(new Error('this shouldnt happen')); | ||
}) | ||
.on('error', (err) => { | ||
socket.close(); | ||
err.message.should.eql('jwt signature is required'); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); |
@@ -1,18 +0,19 @@ | ||
var express = require('express'); | ||
var http = require('http'); | ||
'use strict'; // Node 4.x workaround | ||
var socketIo = require('socket.io'); | ||
var socketio_jwt = require('../../lib'); | ||
const express = require('express'); | ||
const http = require('http'); | ||
var jwt = require('jsonwebtoken'); | ||
const socketIo = require('socket.io'); | ||
const socketio_jwt = require('../../lib'); | ||
var xtend = require('xtend'); | ||
var bodyParser = require('body-parser'); | ||
const jwt = require('jsonwebtoken'); | ||
const xtend = require('xtend'); | ||
const bodyParser = require('body-parser'); | ||
const enableDestroy = require('server-destroy'); | ||
var server, sio; | ||
var enableDestroy = require('server-destroy'); | ||
let sio; | ||
exports.start = function (options, callback) { | ||
exports.start = (options, callback) => { | ||
if(typeof options == 'function'){ | ||
if (typeof options == 'function') { | ||
callback = options; | ||
@@ -28,8 +29,9 @@ options = {}; | ||
var app = express(); | ||
const app = express(); | ||
const server = http.createServer(app); | ||
sio = socketIo.listen(server); | ||
app.use(bodyParser.json()); | ||
app.post('/login', function (req, res) { | ||
var profile = { | ||
app.post('/login', (req, res) => { | ||
const profile = { | ||
first_name: 'John', | ||
@@ -42,15 +44,11 @@ last_name: 'Doe', | ||
// We are sending the profile inside the token | ||
var token = jwt.sign(profile, options.secret, { expiresInMinutes: 60*5 }); | ||
const token = jwt.sign(profile, options.secret, { expiresIn: 60*60*5 }); | ||
res.json({token: token}); | ||
}); | ||
server = http.createServer(app); | ||
sio = socketIo.listen(server); | ||
if (options.handshake) { | ||
sio.use(socketio_jwt.authorize(options)); | ||
sio.sockets.on('echo', function (m) { | ||
sio.sockets.on('echo', (m) => { | ||
sio.sockets.emit('echo-response', m); | ||
@@ -61,4 +59,4 @@ }); | ||
.on('connection', socketio_jwt.authorize(options)) | ||
.on('authenticated', function (socket) { | ||
socket.on('echo', function (m) { | ||
.on('authenticated', (socket) => { | ||
socket.on('echo', (m) => { | ||
socket.emit('echo-response', m); | ||
@@ -70,3 +68,3 @@ }); | ||
server.__sockets = []; | ||
server.on('connection', function (c) { | ||
server.on('connection', (c) => { | ||
server.__sockets.push(c); | ||
@@ -78,3 +76,3 @@ }); | ||
exports.stop = function (callback) { | ||
exports.stop = (callback) => { | ||
sio.close(); | ||
@@ -85,2 +83,2 @@ try { | ||
callback(); | ||
}; | ||
}; |
@@ -1,14 +0,15 @@ | ||
var express = require('express'); | ||
var http = require('http'); | ||
'use strict'; // Node 4.x workaround | ||
var socketIo = require('socket.io'); | ||
var socketio_jwt = require('../../lib'); | ||
const express = require('express'); | ||
const http = require('http'); | ||
var jwt = require('jsonwebtoken'); | ||
const socketIo = require('socket.io'); | ||
const socketio_jwt = require('../../lib'); | ||
var xtend = require('xtend'); | ||
var bodyParser = require('body-parser'); | ||
const jwt = require('jsonwebtoken'); | ||
const xtend = require('xtend'); | ||
const enableDestroy = require('server-destroy'); | ||
const bodyParser = require('body-parser'); | ||
var server, sio; | ||
var enableDestroy = require('server-destroy'); | ||
let sio; | ||
@@ -20,5 +21,5 @@ /** | ||
*/ | ||
exports.start = function (callback) { | ||
exports.start = (callback) => { | ||
options = { | ||
const options = { | ||
secret: 'aaafoo super sercret', | ||
@@ -29,8 +30,9 @@ timeout: 1000, | ||
var app = express(); | ||
const app = express(); | ||
const server = http.createServer(app); | ||
sio = socketIo.listen(server); | ||
app.use(bodyParser.json()); | ||
app.post('/login', function (req, res) { | ||
var profile = { | ||
app.post('/login', (req, res) => { | ||
const profile = { | ||
first_name: 'John', | ||
@@ -43,23 +45,29 @@ last_name: 'Doe', | ||
// We are sending the profile inside the token | ||
var token = jwt.sign(profile, options.secret, { expiresInMinutes: 60*5 }); | ||
res.json({token: token}); | ||
const token = jwt.sign(profile, options.secret, { expiresIn: 60*60*5 }); | ||
res.json({ token: token }); | ||
}); | ||
server = http.createServer(app); | ||
sio = socketIo.listen(server); | ||
sio.on('connection', function (socket) { | ||
// Global namespace (public) | ||
sio.on('connection', (socket) => { | ||
socket.emit('hi'); | ||
}); | ||
var admin_nsp = sio.of('/admin'); | ||
// Second roundtrip | ||
const admin_nsp = sio.of('/admin'); | ||
admin_nsp.on('connection', socketio_jwt.authorize(options)) | ||
.on('authenticated', function (socket) { | ||
socket.emit('hi admin'); | ||
}); | ||
.on('authenticated', (socket) => { | ||
socket.emit('hi admin'); | ||
}); | ||
// One roundtrip | ||
const admin_nsp_hs = sio.of('/admin_hs'); | ||
admin_nsp_hs.use(socketio_jwt.authorize(xtend(options, { handshake: true }))); | ||
admin_nsp_hs.on('connection', (socket) => { | ||
socket.emit('hi admin'); | ||
}); | ||
server.listen(9000, callback); | ||
@@ -69,3 +77,3 @@ enableDestroy(server); | ||
exports.stop = function (callback) { | ||
exports.stop = (callback) => { | ||
sio.close(); | ||
@@ -76,2 +84,2 @@ try { | ||
callback(); | ||
}; | ||
}; |
@@ -1,17 +0,18 @@ | ||
var express = require('express'); | ||
var http = require('http'); | ||
'use strict'; // Node 4.x workaround | ||
var socketIo = require('socket.io'); | ||
var socketio_jwt = require('../../lib'); | ||
const express = require('express'); | ||
const http = require('http'); | ||
var jwt = require('jsonwebtoken'); | ||
const socketIo = require('socket.io'); | ||
const socketio_jwt = require('../../lib'); | ||
var xtend = require('xtend'); | ||
var bodyParser = require('body-parser'); | ||
const jwt = require('jsonwebtoken'); | ||
const xtend = require('xtend'); | ||
const bodyParser = require('body-parser'); | ||
const enableDestroy = require('server-destroy'); | ||
var server, sio; | ||
var enableDestroy = require('server-destroy'); | ||
let sio; | ||
exports.start = function (options, callback) { | ||
var SECRETS = { | ||
exports.start = (options, callback) => { | ||
const SECRETS = { | ||
123: 'aaafoo super sercret', | ||
@@ -21,3 +22,3 @@ 555: 'other' | ||
if(typeof options == 'function'){ | ||
if (typeof options == 'function') { | ||
callback = options; | ||
@@ -28,3 +29,3 @@ options = {}; | ||
options = xtend({ | ||
secret: function(request, decodedToken, callback) { | ||
secret: (request, decodedToken, callback) => { | ||
callback(null, SECRETS[decodedToken.id]); | ||
@@ -36,8 +37,9 @@ }, | ||
var app = express(); | ||
const app = express(); | ||
const server = http.createServer(app); | ||
sio = socketIo.listen(server); | ||
app.use(bodyParser.json()); | ||
app.post('/login', function (req, res) { | ||
var profile = { | ||
app.post('/login', (req, res) => { | ||
const profile = { | ||
first_name: 'John', | ||
@@ -50,15 +52,10 @@ last_name: 'Doe', | ||
// We are sending the profile inside the token | ||
var token = jwt.sign(profile, SECRETS[123], { expiresIn: 60*60*5 }); | ||
const token = jwt.sign(profile, SECRETS[123], { expiresIn: 60*60*5 }); | ||
res.json({token: token}); | ||
}); | ||
server = http.createServer(app); | ||
sio = socketIo.listen(server); | ||
if (options.handshake) { | ||
sio.use(socketio_jwt.authorize(options)); | ||
sio.sockets.on('echo', function (m) { | ||
sio.sockets.on('echo', (m) => { | ||
sio.sockets.emit('echo-response', m); | ||
@@ -69,4 +66,4 @@ }); | ||
.on('connection', socketio_jwt.authorize(options)) | ||
.on('authenticated', function (socket) { | ||
socket.on('echo', function (m) { | ||
.on('authenticated', (socket) => { | ||
socket.on('echo', (m) => { | ||
socket.emit('echo-response', m); | ||
@@ -78,3 +75,3 @@ }); | ||
server.__sockets = []; | ||
server.on('connection', function (c) { | ||
server.on('connection', (c) => { | ||
server.__sockets.push(c); | ||
@@ -87,3 +84,3 @@ }); | ||
exports.stop = function (callback) { | ||
exports.stop = (callback) => { | ||
sio.close(); | ||
@@ -96,2 +93,1 @@ try { | ||
}; | ||
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 4 instances in 1 package
59413
836
338
0
11
22
+ Addedjsonwebtoken@8.5.1(transitive)
+ Addedlodash.includes@4.3.0(transitive)
+ Addedlodash.isboolean@3.0.3(transitive)
+ Addedlodash.isinteger@4.0.4(transitive)
+ Addedlodash.isnumber@3.0.3(transitive)
+ Addedlodash.isplainobject@4.0.6(transitive)
+ Addedlodash.isstring@4.0.1(transitive)
+ Addedlodash.once@4.1.1(transitive)
+ Addedms@2.1.3(transitive)
+ Addedsemver@5.7.2(transitive)
- Removedjsonwebtoken@5.7.0(transitive)
- Removedms@0.7.3(transitive)
- Removedxtend@4.0.2(transitive)
Updatedjsonwebtoken@^8.3.0