Claude
Skills
Sign in
Back

express-oauth2-jwt-bearer

Included with Lifetime
$97 forever

Use when adding Auth0 token validation to Express or Node.js APIs - integrates express-oauth2-jwt-bearer SDK to protect Node.js API endpoints with JWT Bearer authentication, scope-based RBAC, claim validation, and optional DPoP support

Backend & APIsscripts

What this skill does


# Node OAuth2 JWT Bearer Integration

The `express-oauth2-jwt-bearer` package provides Express middleware for validating Auth0 JWT Bearer access tokens. It handles token extraction, signature verification, audience and issuer validation, and expiry checks per RFC 6750 — letting you focus on business logic rather than JWT parsing.

> **Agent instruction:** Before providing SDK setup instructions, fetch the latest release version by running:
> ```bash
> gh api repos/auth0/node-oauth2-jwt-bearer/releases/latest --jq '.tag_name'
> ```
> Use the returned version in all `package.json` dependency lines instead of any hardcoded version below.

## Prerequisites

- **Node.js** 18+ (20+ recommended; required for bootstrap script automation)
- **Express** 4.x or 5.x
- **npm** or **yarn**
- An **Auth0 account** with a configured API (Resource Server)
- **Auth0 CLI** (for automatic setup): `npm install -g @auth0/auth0-cli`

## When NOT to Use

| Use Case | Recommended Skill |
|----------|------------------|
| Building a server-side web app with login UI (Express sessions) | `auth0-express` |
| Building a Next.js app with server-side auth | `auth0-nextjs` |
| Building a React/Angular/Vue SPA | `auth0-react`, `auth0-angular`, `auth0-vue` |
| Building a React Native or mobile app | `auth0-react-native`, `auth0-android`, `auth0-swift` |
| ASP.NET Core Web API | `auth0-aspnetcore-api` |
| Go API with JWT middleware | `go-jwt-middleware` |
| Python API (Flask/FastAPI) | `auth0-api-python` |
| Node.js API using the older `express-jwt` package | `express-jwt` |

## Quick Start Workflow

> **Agent instruction:** Follow these steps to integrate `express-oauth2-jwt-bearer` into the user's Node.js API project.
>
> 1. **Fetch latest version** (see instruction above).
>
> 2. **Install the SDK:**
>    ```bash
>    npm install express-oauth2-jwt-bearer
>    ```
>
> 3. **Configure Auth0** — follow `references/setup.md`. If the user already provided their Auth0 Domain and API Audience in the prompt, use them directly — skip the bootstrap script and do NOT call `AskUserQuestion` to re-confirm. Otherwise, offer automatic setup via bootstrap script or manual setup.
>
> 4. **Set up middleware** — add to `app.js` or `server.js`:
>    ```javascript
>    import { auth } from 'express-oauth2-jwt-bearer';
>
>    const checkJwt = auth({
>      issuerBaseURL: `https://${process.env.AUTH0_DOMAIN}`,
>      audience: process.env.AUTH0_AUDIENCE,
>    });
>
>    app.use(checkJwt); // apply globally, or per-route
>    ```
>
> 5. **Protect endpoints** — apply middleware globally or to specific routes:
>    ```javascript
>    // Global protection
>    app.use(checkJwt);
>
>    // Or per-route
>    app.get('/api/private', checkJwt, (req, res) => {
>      res.json({ sub: req.auth.payload.sub });
>    });
>    ```
>
> 6. **Add RBAC** (optional) — use `requiredScopes()` or `claimIncludes()` for permission-based access:
>    ```javascript
>    import { auth, requiredScopes, claimIncludes } from 'express-oauth2-jwt-bearer';
>
>    app.get('/api/messages', checkJwt, requiredScopes('read:messages'), (req, res) => {
>      res.json({ messages: [] });
>    });
>    ```
>    > **Important:** `requiredScopes` accepts a single argument — a space-separated string or an array. Do NOT pass multiple string arguments: `requiredScopes('read:msg', 'write:msg')` silently ignores everything after the first. Use `requiredScopes('read:msg write:msg')` or `requiredScopes(['read:msg', 'write:msg'])` instead.
>
> 7. **Verify the integration** — build and test:
>    ```bash
>    node server.js
>    curl http://localhost:3000/api/private         # should return 401
>    curl -H "Authorization: Bearer <token>" http://localhost:3000/api/private  # should return 200
>    ```
>
> 8. **Failcheck:** If the server fails to start or tokens are rejected unexpectedly, check `references/api.md` for common issues. After 5-6 failed iterations, use `AskUserQuestion` to ask the user for more details about their environment.

## Detailed Documentation

- **[Setup Guide](./references/setup.md)** — Auth0 API registration, .env configuration, bootstrap script for automated setup, and secret management
- **[Integration Patterns](./references/integration.md)** — Protected endpoints, RBAC with scopes and claims, DPoP, CORS setup, error handling, and testing with curl
- **[API Reference & Testing](./references/api.md)** — Full configuration options, claims reference, complete code example, testing checklist, and common issues

## Common Mistakes

| Mistake | Symptom | Fix |
|---------|---------|-----|
| Created an **Application** instead of an **API** in Auth0 Dashboard | Token validation fails; wrong audience | Create a new **API** (Resource Server) in Auth0 Dashboard → APIs |
| Audience doesn't match API identifier exactly | `401 Unauthorized` — "Audience mismatch" | Copy the exact API Identifier string from Auth0 Dashboard → APIs |
| Domain includes `https://` prefix | `Error: Invalid URL` at startup | Use hostname only: `your-tenant.us.auth0.com`, not `https://...` |
| Checking `scope` claim instead of `permissions` for RBAC | 403 always returned or permissions ignored | Use `requiredScopes()` for scope-based RBAC; use `claimIncludes('permissions', 'read:data')` for Auth0 RBAC permission claims |
| CORS not configured before auth middleware | Preflight OPTIONS requests return 401 | Add `cors()` middleware before `auth()` in the middleware chain |
| `.env` file not loaded | `undefined` for domain/audience | Add `import 'dotenv/config'` at the top of the entry file |
| `req.auth` is undefined | `TypeError: Cannot read properties of undefined` | Verify `checkJwt` middleware runs before the handler |

## Related Skills

- **[auth0-express](../auth0-express)** — For Express web apps with login UI (sessions, cookies)
- **[auth0-nextjs](../auth0-nextjs)** — For Next.js server-side web apps
- **[auth0-aspnetcore-api](../auth0-aspnetcore-api)** — BACKEND_API reference implementation for .NET
- **[go-jwt-middleware](../go-jwt-middleware)** — JWT middleware for Go APIs
- **[auth0-api-python](../auth0-api-python)** — JWT validation for Python APIs (Flask/FastAPI)
- **[auth0-cli](../auth0-cli)** — Manage Auth0 resources from the terminal

## Quick Reference

### Core Middleware

| Function | Description | Returns |
|----------|-------------|---------|
| `auth(options?)` | JWT Bearer validation middleware | `Handler` — 401 if token invalid/missing |
| `requiredScopes(scopes)` | Validates token has all required scopes | `Handler` — 403 if scopes missing |
| `scopeIncludesAny(scopes)` | Validates token has at least one scope | `Handler` — 403 if no match |
| `claimEquals(claim, value)` | Validates a claim equals a value | `Handler` — 401 if mismatch |
| `claimIncludes(claim, ...values)` | Validates claim includes all values | `Handler` — 401 if incomplete |
| `claimCheck(fn, desc?)` | Custom claim validation function | `Handler` — 401 if fn returns false |

### Configuration Options

| Option | Type | Description |
|--------|------|-------------|
| `issuerBaseURL` | `string` | Auth0 domain with `https://` (required unless using env vars) |
| `audience` | `string` | API Identifier from Auth0 Dashboard (required unless using env vars) |
| `tokenSigningAlg` | `string` | Signing algorithm (default: `RS256`; use `HS256` for symmetric) |
| `authRequired` | `boolean` | Set `false` to make authentication optional (default: `true`) |
| `clockTolerance` | `number` | Clock skew tolerance in seconds (no default; undefined unless set) |
| `dpop` | `DPoPOptions` | DPoP configuration (see integration.md) |

### Environment Variables

| Variable | Description |
|----------|-------------|
| `ISSUER_BASE_URL` | Auth0 domain with `https://` (auto-detected by SDK) |
| `AUDIENCE` | API Identifier (auto-detected by SDK) |

### Request Object

After successful validation, `req.auth` contains:
```typescript
req.auth.payload    // Decoded JWT payload (sub, iss, aud, exp, permissions, 

Related in Backend & APIs