Auth0 has released express-oauth2-jwt-bearer, a new Express SDK that makes it super easy to protect APIs with JWT Bearer Tokens. Let's take an overview of its features.
Why a New Express SDK?
Auth0’s previous advice for protecting Express APIs was with a combination of three SDKs: express-jwt, express-jwt-authz, and jwks-rsa. And whilst these work well and are popular SDKs, we felt the developer experience could be improved.
We first wanted to simplify the process of protecting an Express API by reducing the number of dependencies from three to one. This also reduces the install size from ~2 MB to ~500 KB. You can see the benefit by comparing our QuickStart before and after implementing the new SDK, as shown in the following screenshot:
We also wanted to teach the developer community how to protect their APIs with authorization standards like OAuth2.0 rather than a collection of libraries representing token formats, algorithms, and industry abbreviations (jwt
, jwks
, rsa
, and authz
).
This is why the project's first incarnation, express-oauth2-bearer, was released experimentally to support our excellent Identity Labs series (express-oauth2-bearer will now be deprecated in favor of express-oauth2-jwt-bearer).
The Role of Standards
express-oauth2-jwt-bearer protects Express APIs using a combination of the well-established OAuth2 Bearer Token Usage spec and the new specification of JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens.
While there’s always been a clear path for developers to acquire an Access Token from a request using the Bearer Token Usage spec, they’ve relied on best practice and industry convention when determining how to verify their authenticity.
With JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens spec, they are able to leverage new standards to consume Access Token JWTs in an interoperable manner. express-oauth2-jwt-bearer partially implements the JWT Profile for OAuth 2.0 Access Tokens specification. It implements the full specification when you enable the strict
option. Also, it is deeply customizable so that you can use it across a broad range of Identity Providers.
Protect an Express API with JWT Bearer Tokens
express-oauth2-jwt-bearer uses a similar mechanism to OpenID Connect Discovery to configure itself, so it’s easy to set up with minimal effort. In just a few lines of code, you can easily add it to your API to protect it with Access Tokens issued by Auth0, for example.
To easily protect your Express API with Auth0, start by installing the SDK using npm or yarn, as in the following example:
npm install express-oauth2-jwt-bearer
You can initialize the SDK in code or via environment variables. For the latter, the minimal .env
file would look like the following:
ISSUER_BASE_URL=https://<YOUR_TENANT>.auth0.com
AUDIENCE=<YOUR_API_IDENTIFIER>
Replace <YOUR_TENANT>
and <YOUR_API_IDENTIFIER>
with the values of your Auth0 tenant name and API identifier that you’ll find in the Auth0 Dashboard.
Then add the express-oauth2-jwt-bearer middleware to your API like so:
const express = require('express');
const { auth } = require('express-oauth2-jwt-bearer');
require('dotenv').config(); // Load the .env variables
const app = express();
app.use(auth());
app.get('/api/private', (req, res) => {
res.json({ message: `Hello ${req.auth.payload.sub}!` });
});
app.listen(3000, () => console.log('listening at http://localhost:3000'))
You can then start your API and test it using curl:
curl http://localhost:3000/api/private \
--header 'Authorization: Bearer ${YOUR_JWT_ACCESS_TOKEN}'
If you’re wondering where to get an Access Token from, you can get one for testing purposes from the Test tab of your API configuration in the Auth0 Dashboard, as shown in the following picture:
Check out express-openid-connect to see an example of how to programmatically obtain an Access Token to call external APIs.
Checking for Required Scopes
If you want to additionally check the Access Token’s scopes for a specific route you can use the requiredScopes
middleware, as shown below:
const express = require('express');
const { auth, requiredScopes } = require('express-oauth2-jwt-bearer');
require('dotenv').config();
const app = express();
const checkJwt = auth();
app.get('/api/private-scoped', checkJwt, requiredScopes('read:msg'), (req, res) => {
res.json({
message: 'You need to be authenticated and have a scope of read:messages to see this.'
});
});
You can also check custom claims in the Access Token using claimCheck, claimEquals, and claimIncludes (see the docs for the full API).
Under the Hood
express-oauth2-jwt-bearer is a small Express wrapper around two framework agnostic packages:
- oauth2-bearer: it gets Bearer tokens from a request and issues errors per the Bearer Token Usage spec.
- access-token-jwt: it verifies and decodes Access Token JWTs following the JWT Profile for OAuth 2.0 Access Tokens spec using the jose library.
The following diagram shows the dependencies among these packages:
What’s Happening to express-jwt
, express-jwt-authz
, and jwks-rsa
?
express-jwt, express-jwt-authz and jwks-rsa are well used and loved by many Auth0 customers and remain fully supported. There’s no need to rush to update your existing apps. We will keep fixing bugs and patching them. We plan to stop adding new features to these SDKs, though, and the bar for the bugs we fix will be tuned accordingly.
If you are about to start a new Express API project, we recommend using express-oauth2-jwt-bearer, as it will be our target for all innovation for authorization on the Node.js platform for the foreseeable future.
What’s Next
oauth2-bearer and access-token-jwt are as yet unpublished and currently just share space in the node-oauth2-jwt-bearer monorepo. However, you can see how they could easily be used standalone or to create simple wrappers for other Node.js server frameworks like Koa.js, Nest.js, Hapi.js. You can also use them in a range of serverless platforms, which we’ll be reviewing as part of our roadmap going forward.
If you have feedback or notice any issues hit us up via the issues list or the Auth0 community.
Happy coding!