This example shows how to use @auth0/auth0-express
to log a user in, request an access token for an API (audience), and call a
resource server on the user's behalf.
The resource server is the existing Express API example
in this repo, which is protected by
@auth0/auth0-express-api. You run it as a
separate service alongside this web app.
Why a separate service?
@auth0/auth0-expressand@auth0/auth0-express-apieach augment the global ExpressRequesttype with an incompatiblereq.auth0shape, so they cannot be compiled together in one app. A web app and a resource server are separate concerns anyway — this example models that by calling the API example over HTTP.
From the repository root:
npm install
npm run buildThis example needs an Auth0 Regular Web Application (for the web app) and an
Auth0 API (the audience). Configure both this example and the
example-express-api to use the same API.
Rename .env.example to .env here and fill in the values:
AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN
AUTH0_CLIENT_ID=YOUR_CLIENT_ID
AUTH0_CLIENT_SECRET=YOUR_CLIENT_SECRET
AUTH0_SESSION_SECRET=A_LONG_RANDOM_SECRET
APP_BASE_URL=http://localhost:3000
AUTH0_AUDIENCE=YOUR_API_AUDIENCE
API_BASE_URL=http://localhost:3001AUTH0_AUDIENCE must be the identifier of the API registered in your Auth0
tenant. The resource server validates tokens against this same audience.
Important
In the Auth0 Dashboard, add http://localhost:3000/auth/callback to Allowed
Callback URLs and http://localhost:3000 to Allowed Logout URLs.
Start the resource server (the API example) on port 3001 in one terminal:
# in examples/example-express-api (configure its .env with the same AUTH0_AUDIENCE)
PORT=3001 npm startStart this web app on port 3000 in another terminal:
# in examples/example-express-web-call-api
npm startOpen http://localhost:3000, log in, then visit Call API (/call-api). The
web app requests an access token for AUTH0_AUDIENCE and calls
GET /api/private on the resource server with it, then renders the response.
npm testThe test mocks Auth0 (discovery, JWKS, token endpoint) and the downstream API,
then drives a full login and the /call-api flow with supertest — no live
services required.