Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/auth0/express-jwt
connect/express middleware that validates a JsonWebToken (JWT) and set the req.user with the attributes
https://github.com/auth0/express-jwt
express-jwt jwt
Last synced: 6 days ago
JSON representation
connect/express middleware that validates a JsonWebToken (JWT) and set the req.user with the attributes
- Host: GitHub
- URL: https://github.com/auth0/express-jwt
- Owner: auth0
- License: mit
- Created: 2013-10-22T19:45:55.000Z (about 11 years ago)
- Default Branch: master
- Last Pushed: 2024-07-15T12:12:04.000Z (6 months ago)
- Last Synced: 2024-10-29T11:29:01.621Z (3 months ago)
- Topics: express-jwt, jwt
- Language: TypeScript
- Size: 786 KB
- Stars: 4,488
- Watchers: 154
- Forks: 444
- Open Issues: 62
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
- awesome-jwt - express-jwt - Connect/express middleware that validates a JsonWebToken (JWT) and set the req.user with the attributes. (Libraries / Node.js)
README
# express-jwt
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.
## Install
```
$ npm install express-jwt
```## API
`expressjwt(options)`
Options has the following parameters:
- `secret: jwt.Secret | GetVerificationKey` (required): The secret as a string or a function to retrieve the secret.
- `getToken?: TokenGetter` (optional): A function that receives the express `Request` and returns the token, by default it looks in the `Authorization` header.
- `isRevoked?: IsRevoked` (optional): A function to verify if a token is revoked.
- `onExpired?: ExpirationHandler` (optional): A function to handle expired tokens.
- `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.
- `requestProperty?: string` (optional): Name of the property in the request object where the payload is set. Default to `req.auth`.
- Plus... all the options available in the [jsonwebtoken verify function](https://github.com/auth0/node-jsonwebtoken#jwtverifytoken-secretorpublickey-options-callback).The available functions have the following interface:
- `GetVerificationKey = (req: express.Request, token: jwt.Jwt | undefined) => Promise;`
- `IsRevoked = (req: express.Request, token: jwt.Jwt | undefined) => Promise;`
- `TokenGetter = (req: express.Request) => string | Promise | undefined;`## Usage
Basic usage using an HS256 secret:
```javascript
var { expressjwt: jwt } = require("express-jwt");
// or ES6
// import { expressjwt, ExpressJwtRequest } from "express-jwt";app.get(
"/protected",
jwt({ secret: "shhhhhhared-secret", algorithms: ["HS256"] }),
function (req, res) {
if (!req.auth.admin) return res.sendStatus(401);
res.sendStatus(200);
}
);
```The decoded JWT payload is available on the request via the `auth` property.
> 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/).
### Required Parameters
The `algorithms` parameter is required to prevent potential downgrade attacks when providing third party libraries as **secrets**.
:warning: **Do not mix symmetric and asymmetric (ie HS256/RS256) algorithms**: Mixing algorithms without further validation can potentially result in downgrade vulnerabilities.
```javascript
jwt({
secret: "shhhhhhared-secret",
algorithms: ["HS256"],
//algorithms: ['RS256']
});
```### Additional Options
You can specify audience and/or issuer as well, which is highly recommended for security purposes:
```javascript
jwt({
secret: "shhhhhhared-secret",
audience: "http://myapi/protected",
issuer: "http://issuer",
algorithms: ["HS256"],
});
```> If the JWT has an expiration (`exp`), it will be checked.
If you are using a base64 URL-encoded secret, pass a `Buffer` with `base64` encoding as the secret instead of a string:
```javascript
jwt({
secret: Buffer.from("shhhhhhared-secret", "base64"),
algorithms: ["RS256"],
});
```To 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:
```javascript
app.use("/api", jwt({ secret: "shhhhhhared-secret", algorithms: ["HS256"] }));
```Or, the other way around, if you want to make some paths unprotected, call `unless` like so.
```javascript
app.use(
jwt({
secret: "shhhhhhared-secret",
algorithms: ["HS256"],
}).unless({ path: ["/token"] })
);
```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.
> For more details on the `.unless` syntax including additional options, please see [express-unless](https://github.com/jfromaniello/express-unless).
This module also support tokens signed with public/private key pairs. Instead of a secret, you can specify a Buffer with the public key
```javascript
var publicKey = fs.readFileSync("/path/to/public.pub");
jwt({ secret: publicKey, algorithms: ["RS256"] });
```### Customizing Token Location
A custom function for extracting the token from a request can be specified with
the `getToken` option. This is useful if you need to pass the token through a
query parameter or a cookie. You can throw an error in this function and it will
be handled by `express-jwt`.```javascript
app.use(
jwt({
secret: "hello world !",
algorithms: ["HS256"],
credentialsRequired: false,
getToken: function fromHeaderOrQuerystring(req) {
if (
req.headers.authorization &&
req.headers.authorization.split(" ")[0] === "Bearer"
) {
return req.headers.authorization.split(" ")[1];
} else if (req.query && req.query.token) {
return req.query.token;
}
return null;
},
})
);
```### Retrieve key dynamically
If you need to obtain the key dynamically from other sources, you can pass a function in the `secret` parameter with the following parameters:
- `req` (`Object`) - The express `request` object.
- `token` (`Object`) - An object with the JWT payload and headers.For example, if the secret varies based on the [issuer](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#issDef):
```javascript
var jwt = require("express-jwt");
var data = require("./data");
var utilities = require("./utilities");var getSecret = async function (req, token) {
const issuer = token.payload.iss;
const tenant = await data.getTenantByIdentifier(issuer);
if (!tenant) {
throw new Error("missing_secret");
}
return utilities.decrypt(tenant.secret);
};app.get(
"/protected",
jwt({ secret: getSecret, algorithms: ["HS256"] }),
function (req, res) {
if (!req.auth.admin) return res.sendStatus(401);
res.sendStatus(200);
}
);
```### Secret rotation
The getSecret callback could also be used in cases where the same issuer might issue tokens with different keys at certain point:
```js
var getSecret = async function (req, token) {
const { iss } = token.payload;
const { kid } = token.header;
// get the verification key by a given key-id and issuer.
return verificationKey;
};
```### Revoked tokens
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)`:
- `req` (`Object`) - The express `request` object.
- `token` (`Object`) - An object with the JWT payload and headers.For example, if the `(iss, jti)` claim pair is used to identify a JWT:
```javascript
const jwt = require("express-jwt");
const data = require("./data");const isRevokedCallback = async (req, token) => {
const issuer = token.payload.iss;
const tokenId = token.payload.jti;
const token = await data.getRevokedToken(issuer, tokenId);
return token !== "undefined";
};app.get(
"/protected",
jwt({
secret: "shhhhhhared-secret",
algorithms: ["HS256"],
isRevoked: isRevokedCallback,
}),
function (req, res) {
if (!req.auth.admin) return res.sendStatus(401);
res.sendStatus(200);
}
);
```### Handling expired tokens
You can handle expired tokens as follows:
```javascript
jwt({
secret: "shhhhhhared-secret",
algorithms: ["HS256"],
onExpired: async (req, err) => {
if (new Date() - err.inner.expiredAt < 5000) { return;}
throw err;
},,
})
```### Error handling
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:
```javascript
app.use(function (err, req, res, next) {
if (err.name === "UnauthorizedError") {
res.status(401).send("invalid token...");
} else {
next(err);
}
});
```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`:
```javascript
app.use(
jwt({
secret: "hello world !",
algorithms: ["HS256"],
credentialsRequired: false,
})
);
```## Typescript
A `Request` type is provided from `express-jwt`, which extends `express.Request` with the `auth` property. It could be aliased, like how `JWTRequest` is below.
```typescript
import { expressjwt, Request as JWTRequest } from "express-jwt";app.get(
"/protected",
expressjwt({ secret: "shhhhhhared-secret", algorithms: ["HS256"] }),
function (req: JWTRequest, res: express.Response) {
if (!req.auth?.admin) return res.sendStatus(401);
res.sendStatus(200);
}
);
```## Migration from v6
1. The middleware function is now available as a named import rather than a default one: import { expressjwt } from 'express-jwt'
2. The decoded JWT payload is now available as req.auth rather than req.user
3. The `secret` function had `(req, header, payload, cb)`, now it can return a promise and receives `(req, token)`. `token` has `header` and `payload`.
4. The `isRevoked` function had `(req, payload, cb)`, now it can return a promise and receives `(req, token)`. `token` has `header` and `payload`.## Related Modules
- [jsonwebtoken](https://github.com/auth0/node-jsonwebtoken) — JSON Web Token sign and verification
- [express-jwt-permissions](https://github.com/MichielDeMey/express-jwt-permissions) - Permissions middleware for JWT tokens## Tests
```
$ npm install
$ npm test
```## Contributors
Check them out [here](https://github.com/auth0/express-jwt/graphs/contributors)
## Issue 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.
## Author
[Auth0](https://auth0.com)
## License
This project is licensed under the MIT license. See the [LICENSE](LICENSE) file for more info.