> ## Documentation Index
> Fetch the complete documentation index at: https://translations.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Esta guía muestra cómo proteger endpoints de API de Fastify mediante tokens de acceso JWT con el SDK de API de Auth0 para Fastify.

# Proteja su API de Fastify

export const HowToSchema = () => <script type="application/ld+json">
    {'{"@context":"https://schema.org","@type":"HowTo"}'}
  </script>;

<HowToSchema />

<Accordion title="Use la IA para integrar Auth0" icon="microchip-ai" iconType="solid" defaultOpen>
  Si usa un asistente de programación con IA como Claude Code, Cursor o GitHub Copilot, puede añadir automáticamente la autenticación de Auth0 a su API en cuestión de minutos mediante [agent skills](https://agentskills.io/home).

  **Instalar:**

  ```bash theme={null}
  npx skills add auth0/agent-skills --skill auth0-quickstart --skill auth0-fastify-api
  ```

  **Luego, pídale a su asistente de IA:**

  ```text theme={null}
  Add Auth0 JWT authentication to my Fastify API
  ```

  Su asistente de IA creará automáticamente su API de Auth0, recuperará las credenciales, instalará `@auth0/auth0-fastify-api`, configurará el plugin y protegerá los endpoints de su API con validación de JWT. [Documentación completa de agent skills →](/es/docs/quickstart/agent-skills)
</Accordion>

<Note>
  **Requisitos previos:** Antes de comenzar, asegúrese de tener instalado lo siguiente:

  * **[Node.js](https://nodejs.org/en/download)** 20 LTS o una versión posterior
  * **[npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)** 10+ o **[yarn](https://classic.yarnpkg.com/lang/en/docs/install/)** 1.22+ o **[pnpm](https://pnpm.io/installation)** 8+

  Verifique la instalación: `node --version && npm --version`

  **Compatibilidad de versiones de Fastify:** Esta guía de inicio rápido funciona con **Fastify 5.x** y versiones posteriores.
</Note>

<div id="get-started">
  ## Primeros pasos
</div>

Esta guía de inicio rápido muestra cómo proteger los endpoints de una API de Fastify con tokens de acceso JWT. Crearás una API segura que valida los tokens de acceso de Auth0 y concede acceso a recursos protegidos.

<Steps>
  <Step title="Crear un proyecto nuevo" stepNumber={1}>
    Crea un directorio nuevo para tu API de Fastify e inicializa un proyecto de Node.js.

    ```shellscript theme={null}
    mkdir auth0-fastify-api && cd auth0-fastify-api
    ```

    Inicializar el proyecto

    ```shellscript theme={null}
    npm init -y
    ```

    Cree la estructura del proyecto

    ```shellscript theme={null}
    touch server.js .env
    ```
  </Step>

  <Step title="Instala el SDK de la API de Auth0 para Fastify" stepNumber={2}>
    Instale las dependencias requeridas

    ```shellscript theme={null}
    npm install @auth0/auth0-fastify-api fastify dotenv
    ```

    Actualiza tu `package.json` para agregar scripts de inicio:

    ```json package.json theme={null}
    {
      "name": "auth0-fastify-api",
      "version": "1.0.0",
      "type": "module",
      "main": "server.js",
      "scripts": {
        "start": "node server.js",
        "dev": "node --watch server.js"
      },
      "dependencies": {
        "@auth0/auth0-fastify-api": "^1.2.0",
        "dotenv": "^16.3.1",
        "fastify": "^5.0.0"
      }
    }
    ```
  </Step>

  <Step title="Configura tu API de Auth0" stepNumber={3}>
    A continuación, debes crear una nueva API en tu inquilino de Auth0 y agregar las variables de entorno a tu proyecto.

    Tienes dos opciones para configurar tu API de Auth0: usar un comando de la CLI o configurarla manualmente desde el Dashboard:

    <Tabs>
      <Tab title="CLI">
        Ejecuta el siguiente comando en el directorio raíz de tu proyecto para crear una API de Auth0:

        <CodeGroup>
          ```shellscript Mac theme={null}
          # Instala Auth0 CLI (si aún no está instalado)
          brew tap auth0/auth0-cli && brew install auth0

          # Crea la API de Auth0
          auth0 apis create \
            --name "My Fastify API" \
            --identifier https://my-fastify-api.example.com
          ```

          ```powershell Windows theme={null}
          # Instala Auth0 CLI (si aún no está instalado)
          scoop bucket add auth0 https://github.com/auth0/scoop-auth0-cli.git
          scoop install auth0

          # Crea la API de Auth0
          auth0 apis create `
            --name "My Fastify API" `
            --identifier https://my-fastify-api.example.com
          ```
        </CodeGroup>

        Después de crearla, copia los valores de **Identifier** y **dominio**, y luego crea tu archivo `.env`:

        ```bash .env theme={null}
        AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN
        AUTH0_AUDIENCE=YOUR_API_IDENTIFIER
        ```

        <Note>
          Este comando hará lo siguiente:

          1. Comprobará si has iniciado sesión (y te pedirá que lo hagas si es necesario)
          2. Creará una API de Auth0 con el identificador especificado
          3. Mostrará los detalles de la API, incluidos el dominio y el identificador
        </Note>
      </Tab>

      <Tab title="Dashboard">
        1. Ve al [Auth0 Dashboard](https://manage.auth0.com/dashboard/)
        2. Navega a **Applications** → **APIs** → **Create API**
        3. Introduce un nombre para tu API (por ejemplo, "My Fastify API")
        4. Establece el **Identifier** (por ejemplo, `https://my-fastify-api.example.com`)
           * Esta es la audiencia de tu API y debe tener un formato de URL válido
           * No necesita ser una URL real; es solo un identificador
        5. Deja **Signing Algorithm** como **RS256**
        6. Haz clic en **Create**
        7. Copia el valor de **Identifier** de la pestaña **Settings**

        Crea tu archivo `.env` con los siguientes valores:

        ```bash .env theme={null}
        AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN
        AUTH0_AUDIENCE=YOUR_API_IDENTIFIER
        ```

        <Warning>
          Reemplaza `YOUR_AUTH0_DOMAIN` por el dominio de tu inquilino de Auth0 (por ejemplo, `dev-abc123.us.auth0.com`) y `YOUR_API_IDENTIFIER` por el identificador de tu API en el dashboard (por ejemplo, `https://my-fastify-api.example.com`).
        </Warning>
      </Tab>
    </Tabs>

    <Tip>
      Verifica que tu archivo `.env` exista: `cat .env` (Mac/Linux) o `type .env` (Windows)
    </Tip>
  </Step>

  <Step title="Configurar el plugin de la API de Auth0" stepNumber={4}>
    Cree su servidor Fastify y registre el complemento de la API de Auth0:

    ```javascript server.js {1-3,6-7,10-13,16-17} lines theme={null}
    import 'dotenv/config';
    import Fastify from 'fastify';
    import fastifyAuth0Api from '@auth0/auth0-fastify-api';

    const fastify = Fastify({ logger: true });
    const port = process.env.PORT || 3001;

    // Registrar el plugin de API de Auth0
    await fastify.register(fastifyAuth0Api, {
      domain: process.env.AUTH0_DOMAIN,
      audience: process.env.AUTH0_AUDIENCE,
    });

    // Iniciar el servidor
    fastify.listen({ port }, (err) => {
      if (err) {
        fastify.log.error(err);
        process.exit(1);
      }
      fastify.log.info(`API server running at http://localhost:${port}`);
    });
    ```

    **Qué hace esto:**

    * Registra el complemento de la API de Auth0 con tu dominio de Auth0 y la audiencia de la API
    * Configura la validación de JWT para las solicitudes entrantes
    * Pone el preHandler `requireAuth()` a disposición para proteger rutas
  </Step>

  <Step title="Crear rutas de API" stepNumber={5}>
    Agrega rutas públicas y protegidas a tu archivo `server.js`:

    ```javascript server.js expandable lines theme={null}
    import 'dotenv/config';
    import Fastify from 'fastify';
    import fastifyAuth0Api from '@auth0/auth0-fastify-api';

    const fastify = Fastify({ logger: true });
    const port = process.env.PORT || 3001;

    // Registrar el plugin de Auth0 API
    await fastify.register(fastifyAuth0Api, {
      domain: process.env.AUTH0_DOMAIN,
      audience: process.env.AUTH0_AUDIENCE,
    });

    // Ruta pública - no requiere autenticación
    fastify.get('/api/public', async (request, reply) => {
      return {
        message: 'Hello from a public endpoint! You don\'t need to be authenticated to see this.',
        timestamp: new Date().toISOString(),
      };
    });

    // Ruta protegida - requiere un token de acceso válido
    fastify.get('/api/private', {
      preHandler: fastify.requireAuth()
    }, async (request, reply) => {
      return {
        message: 'Hello from a protected endpoint! You successfully authenticated.',
        user: request.user.sub,
        timestamp: new Date().toISOString(),
      };
    });

    // Ruta protegida - devuelve información del usuario desde el token
    fastify.get('/api/profile', {
      preHandler: fastify.requireAuth()
    }, async (request, reply) => {
      return {
        message: 'Your user profile from the access token',
        profile: request.user,
      };
    });

    // Iniciar servidor
    fastify.listen({ port }, (err) => {
      if (err) {
        fastify.log.error(err);
        process.exit(1);
      }
      fastify.log.info(`API server running at http://localhost:${port}`);
    });
    ```

    **Puntos clave:**

    * Las rutas públicas no requieren autenticación
    * Las rutas protegidas usan `preHandler: fastify.requireAuth()` para exigir un JWT válido
    * `request.user` contiene las claims del JWT decodificado para las solicitudes autenticadas
    * La claim `sub` contiene el identificador único del usuario
  </Step>

  <Step title="Inicia tu API" stepNumber={6}>
    Inicie el servidor de desarrollo:

    ```shellscript theme={null}
    npm run dev
    ```

    Tu API ya se está ejecutando en [http://localhost:3001](http://localhost:3001).

    <Info>
      La opción `--watch` en Node.js 20+ reinicia automáticamente el servidor cuando cambian los archivos.
    </Info>
  </Step>

  <Step title="Pruebe su API" stepNumber={7}>
    Pruebe el endpoint público (no requiere autenticación):

    ```bash theme={null}
    curl http://localhost:3001/api/public
    ```

    Deberías ver:

    ```json theme={null}
    {
      "message": "Hello from a public endpoint! You don't need to be authenticated to see this.",
      "timestamp": "2024-01-15T10:30:00.000Z"
    }
    ```

    Pruebe el endpoint protegido sin un token (debería fallar):

    ```bash theme={null}
    curl http://localhost:3001/api/private
    ```

    Debería aparecer un error 401 Unauthorized:

    ```json theme={null}
    {
      "error": "Unauthorized",
      "message": "No authorization token was found"
    }
    ```

    Para probar con un token válido, necesitas:

    1. Crear una aplicación cliente (web o móvil) que autentique usuarios
    2. Configurar el cliente para solicitar un token de acceso para tu API (mediante el parámetro `audience`)
    3. Usar ese token de acceso en el encabezado `Authorization`

    Ejemplo con un token:

    ```bash theme={null}
    curl http://localhost:3001/api/private \
      -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
    ```
  </Step>
</Steps>

<Check>
  **Punto de control**

  Ahora deberías tener una API protegida. Tu API:

  1. Acepta solicitudes a endpoints públicos sin autenticación
  2. Rechaza solicitudes a endpoints protegidos sin un token válido
  3. Valida los tokens JWT con tu dominio de Auth0 y la audiencia
  4. Proporciona información del usuario a partir de los claims del token mediante `request.user`
</Check>

***

<div id="advanced-usage">
  ## Uso avanzado
</div>

<Accordion title="Claims personalizados del token con TypeScript">
  Amplía la interfaz `Token` para añadir seguridad de tipos a los claims personalizados de tus tokens de acceso:

  ```typescript server.ts theme={null}
  import '@auth0/auth0-fastify-api';

  // Amplía la interfaz Token con tus claims personalizados
  declare module '@auth0/auth0-fastify-api' {
    interface Token {
      sub: string;
      permissions?: string[];
      'https://myapp.com/roles'?: string[];
      email?: string;
      email_verified?: boolean;
    }
  }
  ```

  Ahora TypeScript reconocerá tus claims personalizados:

  ```typescript server.ts theme={null}
  fastify.get('/api/profile', {
    preHandler: fastify.requireAuth()
  }, async (request, reply) => {
    // TypeScript reconoce estas propiedades
    const userRoles = request.user['https://myapp.com/roles']; // string[] | undefined
    const permissions = request.user.permissions; // string[] | undefined
    const email = request.user.email; // string | undefined

    return {
      userId: request.user.sub,
      roles: userRoles || [],
      permissions: permissions || [],
      email: email,
    };
  });
  ```

  <Note>
    Los claims personalizados deben usar URL con espacio de nombres (por ejemplo, `https://myapp.com/roles`), a menos que sean claims estándar de OIDC. [Más información sobre los claims personalizados](https://auth0.com/docs/secure/tokens/json-web-tokens/create-custom-claims).
  </Note>
</Accordion>

<Accordion title="Autorización basada en permisos">
  Comprueba permisos específicos en el token de acceso:

  ```javascript server.js theme={null}
  // Middleware para comprobar un permiso específico
  function requirePermission(permission) {
    return async (request, reply) => {
      const permissions = request.user.permissions || [];

      if (!permissions.includes(permission)) {
        return reply.status(403).send({
          error: 'Forbidden',
          message: `Missing required permission: ${permission}`
        });
      }
    };
  }

  // Ruta que requiere el permiso 'read:messages'
  fastify.get('/api/messages', {
    preHandler: [
      fastify.requireAuth(),
      requirePermission('read:messages')
    ]
  }, async (request, reply) => {
    return {
      messages: ['Message 1', 'Message 2', 'Message 3']
    };
  });

  // Ruta que requiere el permiso 'write:messages'
  fastify.post('/api/messages', {
    preHandler: [
      fastify.requireAuth(),
      requirePermission('write:messages')
    ]
  }, async (request, reply) => {
    return {
      message: 'Message created successfully',
      id: 'msg_123'
    };
  });
  ```

  <Note>
    Los permisos deben configurarse en la configuración de la API de Auth0 y concederse a los clientes. [Más información sobre los permisos de API](https://auth0.com/docs/manage-users/access-control/configure-core-rbac/rbac-users/assign-permissions-users).
  </Note>
</Accordion>

<Accordion title="Autorización basada en roles">
  Implemente el control de acceso basado en roles mediante claims personalizados:

  ```javascript server.js theme={null}
  // Middleware para comprobar un rol específico
  function requireRole(role) {
    return async (request, reply) => {
      const roles = request.user['https://myapp.com/roles'] || [];

      if (!roles.includes(role)) {
        return reply.status(403).send({
          error: 'Forbidden',
          message: `Missing required role: ${role}`
        });
      }
    };
  }

  // Ruta solo para administradores
  fastify.get('/api/admin/users', {
    preHandler: [
      fastify.requireAuth(),
      requireRole('admin')
    ]
  }, async (request, reply) => {
    return {
      users: [
        { id: 1, name: 'User 1' },
        { id: 2, name: 'User 2' }
      ]
    };
  });

  // Ruta para manager o admin
  function requireAnyRole(...roles) {
    return async (request, reply) => {
      const userRoles = request.user['https://myapp.com/roles'] || [];
      const hasRole = roles.some(role => userRoles.includes(role));

      if (!hasRole) {
        return reply.status(403).send({
          error: 'Forbidden',
          message: `Missing required role. Need one of: ${roles.join(', ')}`
        });
      }
    };
  }

  fastify.get('/api/reports', {
    preHandler: [
      fastify.requireAuth(),
      requireAnyRole('admin', 'manager')
    ]
  }, async (request, reply) => {
    return { reports: [] };
  });
  ```

  <Note>
    Los roles deben agregarse a los tokens mediante Auth0 Actions. [Aprenda a agregar roles a los tokens](https://auth0.com/docs/customize/actions/flows-and-triggers/login-flow/add-user-roles-to-id-and-access-tokens).
  </Note>
</Accordion>

<Accordion title="Configuración de CORS">
  Habilite CORS para permitir solicitudes desde aplicaciones web:

  ```bash theme={null}
  npm install @fastify/cors
  ```

  ```javascript server.js theme={null}
  import cors from '@fastify/cors';

  await fastify.register(cors, {
    origin: ['http://localhost:3000', 'http://localhost:5173'], // URLs de su aplicación web
    credentials: true,
  });
  ```

  Para producción, especifique los orígenes exactos:

  ```javascript server.js theme={null}
  await fastify.register(cors, {
    origin: [
      'https://myapp.com',
      'https://www.myapp.com'
    ],
    credentials: true,
    methods: ['GET', 'POST', 'PUT', 'DELETE'],
  });
  ```
</Accordion>

<Accordion title="Manejo de errores">
  Agregue un manejo de errores completo para los errores de autenticación:

  ```javascript server.js theme={null}
  // Manejador de errores personalizado
  fastify.setErrorHandler((error, request, reply) => {
    fastify.log.error(error);

    // Manejar errores de validación de JWT
    if (error.statusCode === 401) {
      return reply.status(401).send({
        error: 'Unauthorized',
        message: error.message || 'Invalid or missing access token',
        code: 'UNAUTHORIZED'
      });
    }

    // Manejar errores de permisos/roles
    if (error.statusCode === 403) {
      return reply.status(403).send({
        error: 'Forbidden',
        message: error.message || 'Insufficient permissions',
        code: 'FORBIDDEN'
      });
    }

    // Manejar otros errores
    return reply.status(error.statusCode || 500).send({
      error: 'Internal Server Error',
      message: 'An unexpected error occurred',
      code: 'INTERNAL_ERROR'
    });
  });

  // Manejador para rutas no encontradas
  fastify.setNotFoundHandler((request, reply) => {
    return reply.status(404).send({
      error: 'Not Found',
      message: `Route ${request.method} ${request.url} not found`,
      code: 'NOT_FOUND'
    });
  });
  ```
</Accordion>

<Accordion title="Limitación de tasa">
  Protege tu API frente a abusos mediante la limitación de tasa:

  ```bash theme={null}
  npm install @fastify/rate-limit
  ```

  ```javascript server.js theme={null}
  import rateLimit from '@fastify/rate-limit';

  await fastify.register(rateLimit, {
    max: 100, // Número máximo de solicitudes
    timeWindow: '1 minute', // Ventana de tiempo
    errorResponseBuilder: (request, context) => {
      return {
        error: 'Too Many Requests',
        message: `Rate limit exceeded. Try again in ${context.after}`,
        retryAfter: context.after
      };
    }
  });

  // Aplica límites más estrictos a rutas específicas
  fastify.get('/api/expensive-operation', {
    preHandler: fastify.requireAuth(),
    config: {
      rateLimit: {
        max: 10,
        timeWindow: '1 minute'
      }
    }
  }, async (request, reply) => {
    return { result: 'expensive operation result' };
  });
  ```
</Accordion>

***

<div id="troubleshooting">
  ## Solución de problemas
</div>

<AccordionGroup>
  <Accordion title="Problemas comunes y soluciones">
    ### "No authorization token was found"

    **Problema:** La API no puede encontrar el token de acceso en la solicitud.

    **Soluciones:**

    1. Asegúrate de que la cabecera `Authorization` esté presente: `Authorization: Bearer YOUR_TOKEN`
    2. Comprueba que "Bearer" esté incluido antes del token
    3. Verifica que el token no haya expirado

    ### "Invalid token" o "jwt malformed"

    **Problema:** El formato del token no es válido.

    **Soluciones:**

    1. Asegúrate de que estás usando un **token de acceso**, no un token de ID
    2. El token debe obtenerse con el parámetro `audience` de tu API
    3. Comprueba que el token sea un JWT válido (debe tener tres partes separadas por puntos)

    ### "Invalid signature"

    **Problema:** La firma del token no coincide.

    **Soluciones:**

    1. Verifica que `AUTH0_DOMAIN` coincida con el dominio que emitió el token
    2. Asegúrate de usar el algoritmo de firma RS256 (predeterminado)
    3. Comprueba que el token no se haya modificado

    ### "Invalid audience"

    **Problema:** La audiencia del token no coincide con tu API.

    **Solución:** La aplicación cliente debe solicitar un token con la audiencia correcta:

    ```javascript theme={null}
    // En tu aplicación cliente
    const token = await getAccessTokenSilently({
      authorizationParams: {
        audience: 'https://my-fastify-api.example.com' // Debe coincidir con el identificador de tu API
      }
    });
    ```

    ### Errores de CORS en el navegador

    **Problema:** El navegador bloquea las solicitudes a la API debido a la política de CORS.

    **Solución:** Instala y configura `@fastify/cors`:

    ```bash theme={null}
    npm install @fastify/cors
    ```

    ```javascript theme={null}
    import cors from '@fastify/cors';

    await fastify.register(cors, {
      origin: 'http://localhost:3000', // La URL de tu frontend
      credentials: true
    });
    ```
  </Accordion>
</AccordionGroup>

***

<div id="next-steps">
  ## Próximos pasos
</div>

Ahora que tiene una API protegida, le recomendamos explorar lo siguiente:

* **[Inicio rápido para aplicaciones web con Fastify](/es/docs/quickstart/webapp/fastify)** - Cree una aplicación web que llame a su API
* **[Control de acceso basado en roles](https://auth0.com/docs/manage-users/access-control/rbac)** - Implemente permisos granulares
* **[Prácticas recomendadas de autorización de API](https://auth0.com/docs/secure/tokens/access-tokens)** - Obtenga más información sobre las prácticas recomendadas para los tokens de acceso
* **[Supervise su API](https://auth0.com/docs/deploy-monitor/logs)** - Configure el registro y la supervisión

***

<div id="resources">
  ## Recursos
</div>

* **[auth0-fastify-api GitHub](https://github.com/auth0/auth0-fastify/tree/main/packages/auth0-fastify-api)** - Código fuente y ejemplos
* **[Documentación de Fastify](https://fastify.dev/)** - Más información sobre Fastify
* **[Autenticación de API de Auth0](https://auth0.com/docs/secure/tokens/access-tokens)** - Información sobre los tokens de acceso
* **[Comunidad de Auth0](https://community.auth0.com/)** - Obtén ayuda de la comunidad
