UNPKG

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