1 | # express-jwt
|
2 |
|
3 | [![Build](https://travis-ci.org/auth0/express-jwt.png)](http://travis-ci.org/auth0/express-jwt)
|
4 |
|
5 | This module provides Express middleware for validating JWTs ([JSON Web Tokens](https://jwt.io)) through the [jsonwebtoken](https://github.com/auth0/node-jsonwebtoken/) module. The decoded JWT payload is available on the request object.
|
6 |
|
7 | ## Install
|
8 |
|
9 | ```
|
10 | $ npm install express-jwt
|
11 | ```
|
12 |
|
13 | ## Usage
|
14 |
|
15 | Basic usage using an HS256 secret:
|
16 |
|
17 | ```javascript
|
18 | var jwt = require('express-jwt');
|
19 |
|
20 | app.get('/protected',
|
21 | jwt({ secret: 'shhhhhhared-secret' }),
|
22 | function(req, res) {
|
23 | if (!req.user.admin) return res.sendStatus(401);
|
24 | res.sendStatus(200);
|
25 | });
|
26 | ```
|
27 |
|
28 | The decoded JWT payload is available on the request via the `user` property. This can be configured using the `requestProperty` option ([see below](#retrieving-the-decoded-payload)).
|
29 |
|
30 | > The default behavior of the module is to extract the JWT from the `Authorization` header as an [OAuth2 Bearer token](https://oauth.net/2/bearer-tokens/).
|
31 |
|
32 | ### Additional Options
|
33 |
|
34 | You can specify audience and/or issuer as well:
|
35 |
|
36 | ```javascript
|
37 | jwt({
|
38 | secret: 'shhhhhhared-secret',
|
39 | audience: 'http://myapi/protected',
|
40 | issuer: 'http://issuer'
|
41 | })
|
42 | ```
|
43 |
|
44 | > If the JWT has an expiration (`exp`), it will be checked.
|
45 |
|
46 | If you are using a base64 URL-encoded secret, pass a `Buffer` with `base64` encoding as the secret instead of a string:
|
47 |
|
48 | ```javascript
|
49 | jwt({ secret: new Buffer('shhhhhhared-secret', 'base64') })
|
50 | ```
|
51 |
|
52 | Optionally you can make some paths unprotected as follows:
|
53 |
|
54 | ```javascript
|
55 | app.use(jwt({ secret: 'shhhhhhared-secret'}).unless({path: ['/token']}));
|
56 | ```
|
57 |
|
58 | This is especially useful when applying to multiple routes. In the example above, `path` can be a string, a regexp, or an array of any of those.
|
59 |
|
60 | > For more details on the `.unless` syntax including additional options, please see [express-unless](https://github.com/jfromaniello/express-unless).
|
61 |
|
62 | This module also support tokens signed with public/private key pairs. Instead of a secret, you can specify a Buffer with the public key
|
63 |
|
64 | ```javascript
|
65 | var publicKey = fs.readFileSync('/path/to/public.pub');
|
66 | jwt({ secret: publicKey });
|
67 | ```
|
68 |
|
69 | ### Retrieving the Decoded Payload
|
70 |
|
71 | By default, the decoded token is attached to `req.user` but can be configured with the `requestProperty` option.
|
72 |
|
73 |
|
74 | ```javascript
|
75 | jwt({ secret: publicKey, requestProperty: 'auth' });
|
76 | ```
|
77 |
|
78 | The token can also be attached to the `result` object with the `resultProperty` option. This option will override any `requestProperty`.
|
79 |
|
80 | ```javascript
|
81 | jwt({ secret: publicKey, resultProperty: 'locals.user' });
|
82 | ```
|
83 |
|
84 | Both `resultProperty` and `requestProperty` utilize [lodash.set](https://lodash.com/docs/4.17.2#set) and will accept nested property paths.
|
85 |
|
86 | ### Customizing Token Location
|
87 |
|
88 | A custom function for extracting the token from a request can be specified with
|
89 | the `getToken` option. This is useful if you need to pass the token through a
|
90 | query parameter or a cookie. You can throw an error in this function and it will
|
91 | be handled by `express-jwt`.
|
92 |
|
93 | ```javascript
|
94 | app.use(jwt({
|
95 | secret: 'hello world !',
|
96 | credentialsRequired: false,
|
97 | getToken: function fromHeaderOrQuerystring (req) {
|
98 | if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') {
|
99 | return req.headers.authorization.split(' ')[1];
|
100 | } else if (req.query && req.query.token) {
|
101 | return req.query.token;
|
102 | }
|
103 | return null;
|
104 | }
|
105 | }));
|
106 | ```
|
107 |
|
108 | ### Multi-tenancy
|
109 |
|
110 | If you are developing an application in which the secret used to sign tokens is not static, you can provide a callback function as the `secret` parameter. The function has the signature: `function(req, payload, done)`:
|
111 | * `req` (`Object`) - The express `request` object.
|
112 | * `payload` (`Object`) - An object with the JWT claims.
|
113 | * `done` (`Function`) - A function with signature `function(err, secret)` to be invoked when the secret is retrieved.
|
114 | * `err` (`Any`) - The error that occurred.
|
115 | * `secret` (`String`) - The secret to use to verify the JWT.
|
116 |
|
117 | For example, if the secret varies based on the [JWT issuer](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#issDef):
|
118 |
|
119 | ```javascript
|
120 | var jwt = require('express-jwt');
|
121 | var data = require('./data');
|
122 | var utilities = require('./utilities');
|
123 |
|
124 | var secretCallback = function(req, payload, done){
|
125 | var issuer = payload.iss;
|
126 |
|
127 | data.getTenantByIdentifier(issuer, function(err, tenant){
|
128 | if (err) { return done(err); }
|
129 | if (!tenant) { return done(new Error('missing_secret')); }
|
130 |
|
131 | var secret = utilities.decrypt(tenant.secret);
|
132 | done(null, secret);
|
133 | });
|
134 | };
|
135 |
|
136 | app.get('/protected',
|
137 | jwt({ secret: secretCallback }),
|
138 | function(req, res) {
|
139 | if (!req.user.admin) return res.sendStatus(401);
|
140 | res.sendStatus(200);
|
141 | });
|
142 | ```
|
143 |
|
144 | ### Revoked tokens
|
145 | It is possible that some tokens will need to be revoked so they cannot be used any longer. You can provide a function as the `isRevoked` option. The signature of the function is `function(req, payload, done)`:
|
146 | * `req` (`Object`) - The express `request` object.
|
147 | * `payload` (`Object`) - An object with the JWT claims.
|
148 | * `done` (`Function`) - A function with signature `function(err, revoked)` to be invoked once the check to see if the token is revoked or not is complete.
|
149 | * `err` (`Any`) - The error that occurred.
|
150 | * `revoked` (`Boolean`) - `true` if the JWT is revoked, `false` otherwise.
|
151 |
|
152 | For example, if the `(iss, jti)` claim pair is used to identify a JWT:
|
153 | ```javascript
|
154 | var jwt = require('express-jwt');
|
155 | var data = require('./data');
|
156 | var utilities = require('./utilities');
|
157 |
|
158 | var isRevokedCallback = function(req, payload, done){
|
159 | var issuer = payload.iss;
|
160 | var tokenId = payload.jti;
|
161 |
|
162 | data.getRevokedToken(issuer, tokenId, function(err, token){
|
163 | if (err) { return done(err); }
|
164 | return done(null, !!token);
|
165 | });
|
166 | };
|
167 |
|
168 | app.get('/protected',
|
169 | jwt({
|
170 | secret: 'shhhhhhared-secret',
|
171 | isRevoked: isRevokedCallback
|
172 | }),
|
173 | function(req, res) {
|
174 | if (!req.user.admin) return res.sendStatus(401);
|
175 | res.sendStatus(200);
|
176 | }
|
177 | );
|
178 | ```
|
179 |
|
180 | ### Error handling
|
181 |
|
182 | The default behavior is to throw an error when the token is invalid, so you can add your custom logic to manage unauthorized access as follows:
|
183 |
|
184 | ```javascript
|
185 | app.use(function (err, req, res, next) {
|
186 | if (err.name === 'UnauthorizedError') {
|
187 | res.status(401).send('invalid token...');
|
188 | }
|
189 | });
|
190 | ```
|
191 |
|
192 | You might want to use this module to identify registered users while still providing access to unregistered users. You can do this by using the option `credentialsRequired`:
|
193 |
|
194 | ```javascript
|
195 | app.use(jwt({
|
196 | secret: 'hello world !',
|
197 | credentialsRequired: false
|
198 | }));
|
199 | ```
|
200 |
|
201 | ## Related Modules
|
202 |
|
203 | - [jsonwebtoken](https://github.com/auth0/node-jsonwebtoken) — JSON Web Token sign and verification
|
204 | - [express-jwt-permissions](https://github.com/MichielDeMey/express-jwt-permissions) - Permissions middleware for JWT tokens
|
205 |
|
206 | ## Tests
|
207 |
|
208 | ```
|
209 | $ npm install
|
210 | $ npm test
|
211 | ```
|
212 |
|
213 | ## Contributors
|
214 | Check them out [here](https://github.com/auth0/express-jwt/graphs/contributors)
|
215 |
|
216 | ## Issue Reporting
|
217 |
|
218 | 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.
|
219 |
|
220 | ## Author
|
221 |
|
222 | [Auth0](auth0.com)
|
223 |
|
224 | ## License
|
225 |
|
226 | This project is licensed under the MIT license. See the [LICENSE](LICENSE) file for more info.
|