Protect Fastify API endpoints with JWT access token validation using @auth0/auth0-fastify-api.
auth0-quickstart skill first@auth0/auth0-fastify for session-based authauth0-react, auth0-vue, or auth0-angular for client-side authauth0-nextjs skillauth0-react-native for React Native/Expobash
npm install @auth0/auth0-fastify-api fastify dotenv
You need an API (not Application) in Auth0:
bash
# Using Auth0 CLI
auth0 apis create \
--name "My Fastify API" \
--identifier https://my-api.example.com
Or create manually in Auth0 Dashboard → Applications → APIs
Create .env:
bash
AUTH0_DOMAIN=your-tenant.auth0.com
AUTH0_AUDIENCE=https://my-api.example.com
Create your Fastify server ( server.js):
javascript
import 'dotenv/config';
import Fastify from 'fastify';
import fastifyAuth0Api from '@auth0/auth0-fastify-api';
const fastify = Fastify({ logger: true });
// Register Auth0 API plugin
await fastify.register(fastifyAuth0Api, {
domain: process.env.AUTH0_DOMAIN,
audience: process.env.AUTH0_AUDIENCE,
});
fastify.listen({ port: 3001 });
javascript
// Public route - no authentication
fastify.get('/api/public', async (request, reply) => {
return {
message: 'Hello from a public endpoint!',
timestamp: new Date().toISOString(),
};
});
// Protected route - requires valid JWT
fastify.get('/api/private', {
preHandler: fastify.requireAuth()
}, async (request, reply) => {
return {
message: 'Hello from a protected endpoint!',
user: request.user.sub,
timestamp: new Date().toISOString(),
};
});
// Protected route with user info
fastify.get('/api/profile', {
preHandler: fastify.requireAuth()
}, async (request, reply) => {
return {
profile: request.user, // JWT claims
};
});
Test public endpoint:
bash
curl http://localhost:3001/api/public
Test protected endpoint (requires access token):
bash
curl http://localhost:3001/api/private \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
MistakeFixCreated Application instead of API in Auth0Must create API resource in Auth0 Dashboard → Applications → APIsMissing Authorization headerInclude Authorization: Bearer <token> in all protected endpoint requestsWrong audience in tokenClient must request token with matching audience parameterUsing ID token instead of access tokenMust use access token for API auth, not ID tokenNot handling 401/403 errorsImplement proper error handling for unauthorized/forbidden responses
auth0-quickstart - Basic Auth0 setupauth0-fastify - For server-rendered Fastify web apps with sessionsauth0-mfa - Add Multi-Factor Authenticationauth0-cli - Manage Auth0 resources from the terminalPlugin Options:
domain - Auth0 tenant domain (required)audience - API identifier from Auth0 API settings (required)Request Properties:
request.user - Decoded JWT claims objectrequest.user.sub - User ID (subject)Middleware:
fastify.requireAuth() - Protect route with JWT validationfastify.requireAuth({ scopes: 'read:data' }) - Require specific scopefastify.requireAuth({ scopes: ['read:data', 'write:data'] }) - Require specific scopesCommon Use Cases:
preHandler: fastify.requireAuth() (see Step 5)request.user.subrequest.user['namespace/claim']