2
1
mirror of https://github.com/Thream/socketio-jwt.git synced 2024-11-09 22:20:08 +01:00
socketio-jwt/README.md

338 lines
11 KiB
Markdown
Raw Normal View History

2019-01-15 17:43:44 +01:00
# socketio-jwt
2019-07-23 15:22:23 +02:00
2019-07-16 11:36:35 +02:00
[![All Contributors](https://img.shields.io/badge/all_contributors-5-orange.svg?style=flat-square)](#contributors)
2019-07-23 15:22:23 +02:00
<img src="https://img.shields.io/badge/community-driven-brightgreen.svg"/> <br>
2015-05-29 14:42:14 +02:00
2019-07-16 11:33:44 +02:00
### 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>
2019-07-16 11:34:11 +02:00
<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>
2019-07-16 11:34:43 +02:00
<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>
2019-07-16 11:35:21 +02:00
<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>
2019-07-16 11:36:35 +02:00
<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>
2019-07-16 11:33:44 +02:00
</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/).
2012-09-05 20:14:36 +02:00
2019-01-15 17:43:44 +01:00
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
2019-01-15 17:43:44 +01:00
```bash
npm install socketio-jwt
2012-09-05 20:14:36 +02:00
```
2019-01-15 17:43:44 +01:00
## Usage
2012-09-05 20:14:36 +02:00
2014-01-14 12:30:39 +01:00
```javascript
// set authorization for socket.io
io.sockets
.on('connection', socketioJwt.authorize({
secret: 'your secret or public key',
timeout: 15000 // 15 seconds to send the authentication message
}))
.on('authenticated', (socket) => {
2014-01-14 12:30:39 +01:00
//this socket is authenticated, we are good to handle more events from it.
console.log(`hello! ${socket.decoded_token.name}`);
2015-05-29 14:49:24 +02:00
});
2014-01-14 12:30:39 +01:00
```
**Note:** If you are using a base64-encoded secret (e.g. your Auth0 secret key), you need to convert it to a Buffer: `Buffer('your secret key', 'base64')`
2019-01-15 17:43:44 +01:00
**Client side**
2014-01-14 12:30:39 +01:00
```javascript
const socket = io.connect('http://localhost:9000');
socket.on('connect', () => {
2014-01-14 12:30:39 +01:00
socket
.emit('authenticate', { token: jwt }) //send the jwt
.on('authenticated', () => {
2014-01-14 12:30:39 +01:00
//do other things
})
.on('unauthorized', (msg) => {
console.log(`unauthorized: ${JSON.stringify(msg.data)}`);
2016-08-19 17:01:36 +02:00
throw new Error(msg.data.type);
})
2014-01-14 12:30:39 +01:00
});
```
2019-01-15 17:43:44 +01:00
### One roundtrip
2014-01-14 12:30:39 +01:00
2019-01-15 17:43:44 +01:00
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.
2012-09-05 20:14:36 +02:00
```javascript
const io = require('socket.io')(server);
const socketioJwt = require('socketio-jwt');
```
2012-09-05 20:14:36 +02:00
With socket.io < 1.0:
```javascript
io.set('authorization', socketioJwt.authorize({
2014-01-14 12:30:39 +01:00
secret: 'your secret or public key',
handshake: true
}));
2014-06-03 13:12:07 +02:00
io.on('connection', (socket) => {
console.log('hello!', socket.handshake.decoded_token.name);
});
```
With socket.io >= 1.0:
```javascript
2014-06-03 13:12:07 +02:00
io.use(socketioJwt.authorize({
secret: 'your secret or public key',
handshake: true
}));
2014-01-13 22:41:10 +01:00
io.on('connection', (socket) => {
console.log('hello!', socket.decoded_token.name);
});
2013-11-15 15:16:16 +01:00
```
2012-11-16 16:43:12 +01:00
For more validation options see [auth0/jsonwebtoken](https://github.com/auth0/node-jsonwebtoken).
2012-11-16 16:43:12 +01:00
2019-01-15 17:43:44 +01:00
**Client side**
2013-11-15 15:16:16 +01:00
2014-01-13 22:41:10 +01:00
Append the jwt token using query string:
2013-11-19 10:52:36 +01:00
```javascript
const socket = io.connect('http://localhost:9000', {
query: `token=${your_jwt}`
2013-11-19 10:52:36 +01:00
});
```
Append the jwt token using 'Authorization Header' (Bearer Token):
```javascript
const socket = io.connect('http://localhost:9000', {
extraHeaders: { Authorization: `Bearer ${your_jwt}` }
});
```
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
io.use(socketioJwt.authorize({
secret: 'your secret or public key',
handshake: true,
auth_header_required: true
}));
```
2019-01-15 17:43:44 +01:00
### Handling token expiration
2019-01-15 17:43:44 +01:00
**Server side**
When you sign the token with an expiration time (example: 60 minutes):
```javascript
const token = jwt.sign(user_profile, jwt_secret, { expiresIn: 60*60 });
```
2019-01-15 17:43:44 +01:00
Your client-side code should handle it as below:
2019-01-15 17:43:44 +01:00
**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 token has expired');
}
});
```
2019-01-15 17:43:44 +01:00
### Handling invalid token
Token sent by client is invalid.
2019-01-15 17:43:44 +01:00
**Server side**:
No further configuration needed.
2019-01-15 17:43:44 +01:00
**Client side**
Add a callback client-side to execute socket disconnect server-side.
```javascript
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 token has expired');
}
});
```
2019-01-15 17:43:44 +01:00
**Server side**
To disconnect socket server-side without client-side callback:
```javascript
io.sockets.on('connection', socketioJwt.authorize({
secret: 'secret goes here',
// No client-side callback, terminate connection server-side
2019-01-15 17:43:44 +01:00
callback: false
}))
```
2019-01-15 17:43:44 +01:00
**Client side**
Nothing needs to be changed client-side if callback is false.
2019-01-15 17:43:44 +01:00
**Server side**
To disconnect socket server-side while giving client-side 15 seconds to execute callback:
```javascript
io.sockets.on('connection', socketioJwt.authorize({
secret: 'secret goes here',
// Delay server-side socket disconnect to wait for client-side callback
2019-01-15 17:43:44 +01:00
callback: 15000
}))
```
2019-01-15 17:43:44 +01:00
Your client-side code should handle it as below:
2019-01-15 17:43:44 +01:00
**Client side**
```javascript
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 token has expired');
}
});
```
2019-01-15 17:43:44 +01:00
### 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
way, you are allowed to use a different secret based on the request and / or
the provided token.
2019-01-15 17:43:44 +01:00
**Server side**
```javascript
const SECRETS = {
'user1': 'secret 1',
'user2': 'secret 2'
}
io.use(socketioJwt.authorize({
secret: (request, decodedToken, callback) => {
2017-01-04 11:09:02 +01:00
// SECRETS[decodedToken.userId] will be used as a secret or
// public key for connection user.
callback(null, SECRETS[decodedToken.userId]);
},
handshake: false
}));
```
### 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
});
```
## Contribute
2013-11-19 10:52:36 +01:00
2019-01-15 17:43:44 +01:00
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).
2013-11-15 15:16:16 +01:00
2019-01-15 17:43:44 +01:00
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
npm test
```
2019-01-15 17:43:44 +01:00
## Issues Reporting
2012-09-05 20:14:36 +02:00
2019-01-15 17:43:44 +01:00
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)!
2016-01-14 13:19:40 +01:00
2019-01-15 17:43:44 +01:00
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.
2016-01-14 13:19:40 +01:00
2019-01-15 17:43:44 +01:00
## Repo Community
2016-01-14 13:19:40 +01:00
2019-01-15 17:43:44 +01:00
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>
2016-01-14 13:19:40 +01:00
2013-11-15 15:16:16 +01:00
## License
2019-01-15 17:43:44 +01:00
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
* Google
* Facebook
* Microsoft
* Linkedin
* GitHub
* Twitter
* 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