-
Notifications
You must be signed in to change notification settings - Fork 23
feat: improve auth0-fastify skill score (81% β 93%) #113
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,6 +1,6 @@ | ||||||||||||||||
| --- | ||||||||||||||||
| name: auth0-fastify | ||||||||||||||||
| description: Use when adding authentication (login, logout, protected routes) to Fastify web applications - integrates @auth0/auth0-fastify for session-based auth. For stateless Fastify APIs use auth0-fastify-api instead. | ||||||||||||||||
| description: "Use when adding authentication to Fastify web applications β integrates @auth0/auth0-fastify for session-based login, logout, OAuth callback handling, user profile retrieval, and access token management. Registers /auth/login, /auth/logout, and /auth/callback routes automatically. For stateless Fastify APIs receiving JWT Bearer tokens, use auth0-fastify-api instead." | ||||||||||||||||
| license: Apache-2.0 | ||||||||||||||||
| metadata: | ||||||||||||||||
| author: Auth0 <support@auth0.com> | ||||||||||||||||
|
|
@@ -12,26 +12,12 @@ metadata: | |||||||||||||||
|
|
||||||||||||||||
| # Auth0 Fastify Integration | ||||||||||||||||
|
|
||||||||||||||||
| Add authentication to Fastify web applications using @auth0/auth0-fastify. | ||||||||||||||||
| Add session-based authentication to Fastify web applications using @auth0/auth0-fastify. | ||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. session-based sounds confusing when the SDK supports stateless and statefull configurations, where in stateful everything stays in the cookie. |
||||||||||||||||
|
|
||||||||||||||||
| --- | ||||||||||||||||
|
|
||||||||||||||||
| ## Prerequisites | ||||||||||||||||
|
|
||||||||||||||||
| - Fastify application (v5.x or newer) | ||||||||||||||||
| - Node.js 20 LTS or newer | ||||||||||||||||
| - Auth0 account and application configured | ||||||||||||||||
| - If you don't have Auth0 set up yet, use the `auth0-quickstart` skill first | ||||||||||||||||
|
|
||||||||||||||||
| ## When NOT to Use | ||||||||||||||||
|
|
||||||||||||||||
| - **Single Page Applications** - Use `auth0-react`, `auth0-vue`, or `auth0-angular` for client-side auth | ||||||||||||||||
| - **Next.js applications** - Use `auth0-nextjs` skill which handles both client and server | ||||||||||||||||
| - **Mobile applications** - Use `auth0-react-native` for React Native/Expo | ||||||||||||||||
| - **Stateless APIs** - Use `@auth0/auth0-fastify-api` instead for JWT validation without sessions | ||||||||||||||||
| - **Microservices** - Use JWT validation for service-to-service auth | ||||||||||||||||
|
|
||||||||||||||||
| --- | ||||||||||||||||
| > **Agent instruction:** Before providing SDK setup instructions, fetch the latest release version by running: | ||||||||||||||||
| > ``` | ||||||||||||||||
| > gh api repos/auth0/auth0-fastify/releases/latest --jq '.tag_name' | ||||||||||||||||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||||||||||||||||
| > ``` | ||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the intention with removing prerequisites and when NOT to use here?
Comment on lines
+17
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add blank line before the fenced code block. Markdown specification requires blank lines around fenced code blocks. Add a blank line between line 17 and line 18 to resolve the MD031 linting warning. π Proposed fix > **Agent instruction:** Before providing SDK setup instructions, fetch the latest release version by running:
+>
> ```bash
> gh api repos/auth0/auth0-fastify/releases/latest --jq '.tag_name'
> ```As per coding guidelines, static analysis flagged: MD031 blanks-around-fences. π Committable suggestion
Suggested change
π§° Toolsπͺ markdownlint-cli2 (0.22.1)[warning] 18-18: Fenced code blocks should be surrounded by blank lines (MD031, blanks-around-fences) π€ Prompt for AI Agents |
||||||||||||||||
|
|
||||||||||||||||
| ## Quick Start Workflow | ||||||||||||||||
|
|
||||||||||||||||
|
|
@@ -43,7 +29,9 @@ npm install @auth0/auth0-fastify fastify @fastify/view ejs dotenv | |||||||||||||||
|
|
||||||||||||||||
| ### 2. Configure Environment | ||||||||||||||||
|
|
||||||||||||||||
| Create `.env`: | ||||||||||||||||
| **For automated setup with Auth0 CLI**, see [Setup Guide](references/setup.md). | ||||||||||||||||
|
|
||||||||||||||||
| **For manual setup**, create `.env`: | ||||||||||||||||
|
|
||||||||||||||||
| ```bash | ||||||||||||||||
| AUTH0_DOMAIN=your-tenant.auth0.com | ||||||||||||||||
|
|
@@ -55,6 +43,8 @@ APP_BASE_URL=http://localhost:3000 | |||||||||||||||
|
|
||||||||||||||||
| Generate secret: `openssl rand -hex 64` | ||||||||||||||||
|
|
||||||||||||||||
| **Verify before proceeding:** In the Auth0 Dashboard, confirm the application is set to **Regular Web Application** (not SPA) and that `http://localhost:3000/auth/callback` is listed in Allowed Callback URLs, `http://localhost:3000` in Allowed Logout URLs and Allowed Web Origins. | ||||||||||||||||
|
|
||||||||||||||||
| ### 3. Configure Auth Plugin | ||||||||||||||||
|
|
||||||||||||||||
| Create your Fastify server (`server.js`): | ||||||||||||||||
|
|
@@ -68,13 +58,11 @@ import ejs from 'ejs'; | |||||||||||||||
|
|
||||||||||||||||
| const fastify = Fastify({ logger: true }); | ||||||||||||||||
|
|
||||||||||||||||
| // Register view engine | ||||||||||||||||
| await fastify.register(fastifyView, { | ||||||||||||||||
| engine: { ejs }, | ||||||||||||||||
| root: './views', | ||||||||||||||||
| }); | ||||||||||||||||
|
|
||||||||||||||||
| // Configure Auth0 plugin | ||||||||||||||||
| await fastify.register(fastifyAuth0, { | ||||||||||||||||
| domain: process.env.AUTH0_DOMAIN, | ||||||||||||||||
| clientId: process.env.AUTH0_CLIENT_ID, | ||||||||||||||||
|
|
@@ -86,10 +74,10 @@ await fastify.register(fastifyAuth0, { | |||||||||||||||
| fastify.listen({ port: 3000 }); | ||||||||||||||||
| ``` | ||||||||||||||||
|
|
||||||||||||||||
| This automatically creates: | ||||||||||||||||
| - `/auth/login` - Login endpoint | ||||||||||||||||
| - `/auth/logout` - Logout endpoint | ||||||||||||||||
| - `/auth/callback` - OAuth callback | ||||||||||||||||
| This automatically registers: | ||||||||||||||||
| - `/auth/login` β Redirects to Auth0 Universal Login | ||||||||||||||||
| - `/auth/logout` β Clears session and redirects to Auth0 logout | ||||||||||||||||
| - `/auth/callback` β Handles OAuth callback and creates session | ||||||||||||||||
|
|
||||||||||||||||
| ### 4. Add Routes | ||||||||||||||||
|
|
||||||||||||||||
|
|
@@ -118,59 +106,36 @@ fastify.get('/profile', { | |||||||||||||||
|
|
||||||||||||||||
| ### 5. Test Authentication | ||||||||||||||||
|
|
||||||||||||||||
| Start your server: | ||||||||||||||||
|
|
||||||||||||||||
| ```bash | ||||||||||||||||
| node server.js | ||||||||||||||||
| ``` | ||||||||||||||||
|
|
||||||||||||||||
| Visit `http://localhost:3000` and test the login flow. | ||||||||||||||||
| Visit `http://localhost:3000` and verify: | ||||||||||||||||
| 1. Clicking login redirects to Auth0 Universal Login | ||||||||||||||||
| 2. After login, you are redirected back with a valid session | ||||||||||||||||
| 3. `/profile` shows user info when authenticated | ||||||||||||||||
| 4. Logout clears the session and redirects home | ||||||||||||||||
|
|
||||||||||||||||
| If login redirects fail, check the server logs for callback URL mismatch errors β the most common cause is a missing or incorrect Allowed Callback URL in the Auth0 Dashboard. | ||||||||||||||||
|
|
||||||||||||||||
| --- | ||||||||||||||||
|
|
||||||||||||||||
| ## Common Mistakes | ||||||||||||||||
|
|
||||||||||||||||
| | Mistake | Fix | | ||||||||||||||||
| |---------|-----| | ||||||||||||||||
| | Forgot to add callback URL in Auth0 Dashboard | Add `/auth/callback` path to Allowed Callback URLs (e.g., `http://localhost:3000/auth/callback`) | | ||||||||||||||||
| | Missing or weak SESSION_SECRET | Generate secure 64-char secret with `openssl rand -hex 64` and store in .env | | ||||||||||||||||
| | App created as SPA type in Auth0 | Must be Regular Web Application type for server-side auth | | ||||||||||||||||
| | Session secret exposed in code | Always use environment variables, never hardcode secrets | | ||||||||||||||||
| | Wrong appBaseUrl for production | Update APP_BASE_URL to match your production domain | | ||||||||||||||||
| | Not awaiting fastify.register | Fastify v4+ requires awaiting plugin registration | | ||||||||||||||||
| | Callback URL mismatch | Add `http://localhost:3000/auth/callback` to Allowed Callback URLs in Auth0 Dashboard | | ||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why did we remove common mistakes? |
||||||||||||||||
| | App created as SPA type | Must be **Regular Web Application** for server-side session auth | | ||||||||||||||||
| | Weak SESSION_SECRET | Generate with `openssl rand -hex 64` β minimum 64 characters | | ||||||||||||||||
| | Not awaiting `fastify.register` | Fastify v4+ requires `await` on plugin registration | | ||||||||||||||||
|
|
||||||||||||||||
| --- | ||||||||||||||||
|
|
||||||||||||||||
| ## Related Skills | ||||||||||||||||
|
|
||||||||||||||||
| - `auth0-quickstart` - Basic Auth0 setup | ||||||||||||||||
| - `auth0-migration` - Migrate from another auth provider | ||||||||||||||||
| - `auth0-mfa` - Add Multi-Factor Authentication | ||||||||||||||||
| - `auth0-cli` - Manage Auth0 resources from the terminal | ||||||||||||||||
|
|
||||||||||||||||
| --- | ||||||||||||||||
| ## Detailed Documentation | ||||||||||||||||
|
|
||||||||||||||||
| ## Quick Reference | ||||||||||||||||
|
|
||||||||||||||||
| **Plugin Options:** | ||||||||||||||||
| - `domain` - Auth0 tenant domain (required) | ||||||||||||||||
| - `clientId` - Auth0 client ID (required) | ||||||||||||||||
| - `clientSecret` - Auth0 client secret (required) | ||||||||||||||||
| - `appBaseUrl` - Application URL (required) | ||||||||||||||||
| - `sessionSecret` - Session encryption secret (required, min 64 chars) | ||||||||||||||||
| - `audience` - API audience (optional, for calling APIs) | ||||||||||||||||
|
|
||||||||||||||||
| **Client Methods:** | ||||||||||||||||
| - `fastify.auth0Client.getSession({ request, reply })` - Get user session | ||||||||||||||||
| - `fastify.auth0Client.getUser({ request, reply })` - Get user profile | ||||||||||||||||
| - `fastify.auth0Client.getAccessToken({ request, reply })` - Get access token | ||||||||||||||||
| - `fastify.auth0Client.logout(options, { request, reply })` - Logout user | ||||||||||||||||
|
|
||||||||||||||||
| **Common Use Cases:** | ||||||||||||||||
| - Protected routes β Use `preHandler` to check session (see Step 4) | ||||||||||||||||
| - Check auth status β `!!session` | ||||||||||||||||
| - Get user info β `getUser({ request, reply })` | ||||||||||||||||
| - Call APIs β `getAccessToken({ request, reply })` | ||||||||||||||||
| - **[Setup Guide](references/setup.md)** β Automated setup with Auth0 CLI, environment configuration | ||||||||||||||||
| - **[Integration Guide](references/integration.md)** β Protected routes with preHandlers, calling APIs with access tokens, error handling | ||||||||||||||||
| - **[API Reference](references/api.md)** β Plugin options, client methods, session management | ||||||||||||||||
|
|
||||||||||||||||
| --- | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| # API Reference | ||
|
|
||
| ## Plugin Options | ||
|
|
||
| | Option | Required | Description | | ||
| |--------|----------|-------------| | ||
| | `domain` | Yes | Auth0 tenant domain | | ||
| | `clientId` | Yes | Auth0 application Client ID | | ||
| | `clientSecret` | Yes | Auth0 application Client Secret | | ||
| | `appBaseUrl` | Yes | Application URL (e.g. `http://localhost:3000`) | | ||
| | `sessionSecret` | Yes | Session encryption secret (min 64 chars) | | ||
| | `audience` | No | API audience identifier β required when calling protected APIs | | ||
| | `routes` | No | Customize auth route paths (default: `/auth/login`, `/auth/logout`, `/auth/callback`) | | ||
|
|
||
| ## Client Methods | ||
|
|
||
| All methods are available on `fastify.auth0Client` after plugin registration. | ||
|
|
||
| | Method | Returns | Description | | ||
| |--------|---------|-------------| | ||
| | `getSession({ request, reply })` | `Session \| null` | Returns the current user session, or `null` if not authenticated | | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no |
||
| | `getUser({ request, reply })` | `UserProfile` | Returns the authenticated user's profile (name, email, picture) | | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no |
||
| | `getAccessToken({ request, reply })` | `{ token }` | Returns an access token for calling protected APIs | | ||
| | `logout(options, { request, reply })` | `void` | Clears the session and redirects to Auth0 logout | | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| # Integration Guide | ||
|
|
||
| ## Protected Routes | ||
|
|
||
| Use a `preHandler` hook to require authentication on any route: | ||
|
|
||
| ```javascript | ||
| fastify.get('/dashboard', { | ||
| preHandler: async (request, reply) => { | ||
| const session = await fastify.auth0Client.getSession({ request, reply }); | ||
| if (!session) { | ||
| return reply.redirect('/auth/login'); | ||
| } | ||
| } | ||
| }, async (request, reply) => { | ||
| const user = await fastify.auth0Client.getUser({ request, reply }); | ||
| return reply.view('views/dashboard.ejs', { user }); | ||
| }); | ||
| ``` | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| ## Calling a Protected API | ||
|
|
||
| To call an external API protected by Auth0, configure an `audience` and retrieve the access token: | ||
|
|
||
| ```javascript | ||
| // In plugin registration, add audience: | ||
| await fastify.register(fastifyAuth0, { | ||
| domain: process.env.AUTH0_DOMAIN, | ||
| clientId: process.env.AUTH0_CLIENT_ID, | ||
| clientSecret: process.env.AUTH0_CLIENT_SECRET, | ||
| appBaseUrl: process.env.APP_BASE_URL, | ||
| sessionSecret: process.env.SESSION_SECRET, | ||
| audience: process.env.AUTH0_AUDIENCE, | ||
| }); | ||
|
|
||
| // In a route handler: | ||
| fastify.get('/api-data', { | ||
| preHandler: async (request, reply) => { | ||
| const session = await fastify.auth0Client.getSession({ request, reply }); | ||
| if (!session) return reply.redirect('/auth/login'); | ||
| } | ||
| }, async (request, reply) => { | ||
| const { token } = await fastify.auth0Client.getAccessToken({ request, reply }); | ||
| const response = await fetch('https://api.example.com/data', { | ||
| headers: { Authorization: `Bearer ${token}` }, | ||
| }); | ||
| const data = await response.json(); | ||
| return reply.view('views/data.ejs', { data }); | ||
| }); | ||
| ``` | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| ## Error Handling | ||
|
|
||
| Handle authentication errors by checking the session state and server logs: | ||
|
|
||
| ```javascript | ||
| fastify.setErrorHandler(async (error, request, reply) => { | ||
| if (error.statusCode === 401) { | ||
| return reply.redirect('/auth/login'); | ||
| } | ||
| fastify.log.error(error); | ||
| return reply.status(500).send({ error: 'Internal Server Error' }); | ||
| }); | ||
| ``` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| # Setup Guide | ||
|
|
||
| ## Automated Setup with Auth0 CLI | ||
|
|
||
| ```bash | ||
| # 1. Authenticate | ||
| auth0 login | ||
|
|
||
| # 2. Create a Regular Web Application | ||
| auth0 apps create \ | ||
| --name "My Fastify App" \ | ||
| --type regular \ | ||
| --callbacks "http://localhost:3000/auth/callback" \ | ||
| --logout-urls "http://localhost:3000" \ | ||
| --origins "http://localhost:3000" \ | ||
| --reveal-secrets | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are we, by default, exposing the secret to the agent as opposed to how we do it in other skills? |
||
|
|
||
| # 3. Copy the Domain, Client ID, and Client Secret from the output into .env | ||
| ``` | ||
|
|
||
| ## Environment Variables | ||
|
|
||
| | Variable | Description | | ||
| |----------|-------------| | ||
| | `AUTH0_DOMAIN` | Auth0 tenant domain (e.g. `dev-abc123.us.auth0.com`) β no `https://` prefix | | ||
| | `AUTH0_CLIENT_ID` | Application Client ID from Auth0 Dashboard | | ||
| | `AUTH0_CLIENT_SECRET` | Application Client Secret β never commit to source control | | ||
| | `SESSION_SECRET` | Encryption key for session cookies β generate with `openssl rand -hex 64` | | ||
| | `APP_BASE_URL` | Full application URL including protocol and port (e.g. `http://localhost:3000`) | | ||
|
|
||
| ## Production Configuration | ||
|
|
||
| Update `.env` for production: | ||
|
|
||
| ```bash | ||
| AUTH0_DOMAIN=your-tenant.auth0.com | ||
| AUTH0_CLIENT_ID=your-production-client-id | ||
| AUTH0_CLIENT_SECRET=your-production-client-secret | ||
| SESSION_SECRET=<new-production-secret> | ||
| APP_BASE_URL=https://your-production-domain.com | ||
| ``` | ||
|
|
||
| Update the Auth0 Dashboard to include your production callback URL (`https://your-production-domain.com/auth/callback`) in Allowed Callback URLs and your production domain in Allowed Logout URLs and Allowed Web Origins. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to include the routes it registered in the skills description?
This is not correct, Fastify API handles more than just Bearer tokens.