UNPKG

9.42 kBMarkdownView Raw
1# express-jwt
2
3This 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.
4
5## Install
6
7```
8$ npm install express-jwt
9```
10
11## API
12
13`expressjwt(options)`
14
15Options has the following paramters:
16
17- `secret: jwt.Secret | GetVerificationKey` (required): The secret as an string or a function to retrieve the secret.
18- `getToken?: TokenGetter` (optional): A function that receives the express `Request` and returns the token, by default it looks in the `Authorization` header.
19- `isRevoked?: IsRevoked` (optional): A function to verify if a token is revoked.
20- `credentialsRequired?: boolean` (optional): If its false, continue to the next middleware if the request does not contain a token instead of failing, defaults to true.
21- `requestProperty?: string` (optional): name of the property in the request object where the payload is set. Default to `req.auth`.
22- Plus... all the options available in the [jsonwebtoken verify function](https://github.com/auth0/node-jsonwebtoken#jwtverifytoken-secretorpublickey-options-callback).
23
24The available functions have the following interface:
25
26- `GetVerificationKey = (req: express.Request, token: jwt.Jwt | undefined) => Promise<jwt.Secret>;`
27- `IsRevoked = (req: express.Request, token: jwt.Jwt | undefined) => Promise<boolean>;`
28- `TokenGetter = (req: express.Request) => string | Promise<string> | undefined;`
29
30## Usage
31
32Basic usage using an HS256 secret:
33
34```javascript
35var { expressjwt: jwt } = require("express-jwt");
36// or ES6
37// import { expressjwt, ExpressJwtRequest } from "express-jwt";
38
39app.get(
40 "/protected",
41 jwt({ secret: "shhhhhhared-secret", algorithms: ["HS256"] }),
42 function (req, res) {
43 if (!req.auth.admin) return res.sendStatus(401);
44 res.sendStatus(200);
45 }
46);
47```
48
49The decoded JWT payload is available on the request via the `auth` property.
50
51> 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/).
52
53### Required Parameters
54
55The `algorithms` parameter is required to prevent potential downgrade attacks when providing third party libraries as **secrets**.
56
57:warning: **Do not mix symmetric and asymmetric (ie HS256/RS256) algorithms**: Mixing algorithms without further validation can potentially result in downgrade vulnerabilities.
58
59```javascript
60jwt({
61 secret: "shhhhhhared-secret",
62 algorithms: ["HS256"],
63 //algorithms: ['RS256']
64});
65```
66
67### Additional Options
68
69You can specify audience and/or issuer as well, which is highly recommended for security purposes:
70
71```javascript
72jwt({
73 secret: "shhhhhhared-secret",
74 audience: "http://myapi/protected",
75 issuer: "http://issuer",
76 algorithms: ["HS256"],
77});
78```
79
80> If the JWT has an expiration (`exp`), it will be checked.
81
82If you are using a base64 URL-encoded secret, pass a `Buffer` with `base64` encoding as the secret instead of a string:
83
84```javascript
85jwt({
86 secret: Buffer.from("shhhhhhared-secret", "base64"),
87 algorithms: ["RS256"],
88});
89```
90
91To only protect specific paths (e.g. beginning with `/api`), use [express router](https://expressjs.com/en/4x/api.html#app.use) call `use`, like so:
92
93```javascript
94app.use("/api", jwt({ secret: "shhhhhhared-secret", algorithms: ["HS256"] }));
95```
96
97Or, the other way around, if you want to make some paths unprotected, cal `unless` like so.
98
99```javascript
100app.use(
101 jwt({
102 secret: "shhhhhhared-secret",
103 algorithms: ["HS256"],
104 }).unless({ path: ["/token"] })
105);
106```
107
108This 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.
109
110> For more details on the `.unless` syntax including additional options, please see [express-unless](https://github.com/jfromaniello/express-unless).
111
112This module also support tokens signed with public/private key pairs. Instead of a secret, you can specify a Buffer with the public key
113
114```javascript
115var publicKey = fs.readFileSync("/path/to/public.pub");
116jwt({ secret: publicKey, algorithms: ["RS256"] });
117```
118
119### Customizing Token Location
120
121A custom function for extracting the token from a request can be specified with
122the `getToken` option. This is useful if you need to pass the token through a
123query parameter or a cookie. You can throw an error in this function and it will
124be handled by `express-jwt`.
125
126```javascript
127app.use(
128 jwt({
129 secret: "hello world !",
130 algorithms: ["HS256"],
131 credentialsRequired: false,
132 getToken: function fromHeaderOrQuerystring(req) {
133 if (
134 req.headers.authorization &&
135 req.headers.authorization.split(" ")[0] === "Bearer"
136 ) {
137 return req.headers.authorization.split(" ")[1];
138 } else if (req.query && req.query.token) {
139 return req.query.token;
140 }
141 return null;
142 },
143 })
144);
145```
146
147### Retrieve key dynamically
148
149If you need to obtain the key dynamically from other sources, you can pass a function in the `secret` parameter with the following parameters:
150
151- `req` (`Object`) - The express `request` object.
152- `token` (`Object`) - An object with the JWT payload and headers.
153
154For example, if the secret varies based on the [issuer](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#issDef):
155
156```javascript
157var jwt = require("express-jwt");
158var data = require("./data");
159var utilities = require("./utilities");
160
161var getSecret = async function (req, token) {
162 const issuer = token.payload.iss;
163 const tenant = await data.getTenantByIdentifier(issuer);
164 if (!tenant) {
165 throw new Error("missing_secret");
166 }
167 return utilities.decrypt(tenant.secret);
168};
169
170app.get(
171 "/protected",
172 jwt({ secret: getSecret, algorithms: ["HS256"] }),
173 function (req, res) {
174 if (!req.auth.admin) return res.sendStatus(401);
175 res.sendStatus(200);
176 }
177);
178```
179
180### Revoked tokens
181
182It 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)`:
183
184- `req` (`Object`) - The express `request` object.
185- `token` (`Object`) - An object with the JWT payload and headers.
186
187For example, if the `(iss, jti)` claim pair is used to identify a JWT:
188
189```javascript
190const jwt = require("express-jwt");
191const data = require("./data");
192
193const isRevokedCallback = async (req, token) => {
194 const issuer = token.payload.iss;
195 const tokenId = token.payload.jti;
196 const token = await data.getRevokedToken(issuer, tokenId);
197 return token !== "undefined";
198};
199
200app.get(
201 "/protected",
202 jwt({
203 secret: "shhhhhhared-secret",
204 algorithms: ["HS256"],
205 isRevoked: isRevokedCallback,
206 }),
207 function (req, res) {
208 if (!req.auth.admin) return res.sendStatus(401);
209 res.sendStatus(200);
210 }
211);
212```
213
214### Error handling
215
216The 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:
217
218```javascript
219app.use(function (err, req, res, next) {
220 if (err.name === "UnauthorizedError") {
221 res.status(401).send("invalid token...");
222 } else {
223 next(err);
224 }
225});
226```
227
228You 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`:
229
230```javascript
231app.use(
232 jwt({
233 secret: "hello world !",
234 algorithms: ["HS256"],
235 credentialsRequired: false,
236 })
237);
238```
239
240## Typescript
241
242An `ExpressJwtRequest` type is provided which extends `express.Request` with the `auth` property.
243
244```typescript
245import { expressjwt, ExpressJwtRequest } from "express-jwt";
246
247app.get(
248 "/protected",
249 expressjwt({ secret: "shhhhhhared-secret", algorithms: ["HS256"] }),
250 function (req: ExpressJwtRequest, res: express.Response) {
251 if (!req.auth.admin) return res.sendStatus(401);
252 res.sendStatus(200);
253 }
254);
255```
256
257## Migration from v6
258
2591. The middleware function is now available as a named import rather than a default one: import { expressjwt } from 'express-jwt'
2602. The decoded JWT payload is now available as req.auth rather than req.user
2613. The `secret` function had `(req, header, payload, cb)`, now it can return a promise and receives `(req, token)`. `token` has `header` and `payload`.
2624. The `isRevoked` function had `(req, payload, cb)`, now it can return a promise and receives `(req, token)`. `token` has `header` and `payload`.
263
264## Related Modules
265
266- [jsonwebtoken](https://github.com/auth0/node-jsonwebtoken) — JSON Web Token sign and verification
267- [express-jwt-permissions](https://github.com/MichielDeMey/express-jwt-permissions) - Permissions middleware for JWT tokens
268
269## Tests
270
271```
272$ npm install
273$ npm test
274```
275
276## Contributors
277
278Check them out [here](https://github.com/auth0/express-jwt/graphs/contributors)
279
280## Issue Reporting
281
282If 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.
283
284## Author
285
286[Auth0](https://auth0.com)
287
288## License
289
290This project is licensed under the MIT license. See the [LICENSE](LICENSE) file for more info.