> ## 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.

> Agrega autenticación JWT de Auth0 a una API de FastAPI con endpoints protegidos

# FastAPI API

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

<HowToSchema />

<Accordion title="Prompt de IA" defaultOpen icon="microchip-ai" iconType="sharp-solid">
  **¿Usas IA para integrar Auth0?** Añade este prompt a Cursor, Windsurf, Copilot, Claude Code o tu IDE con IA favorito para acelerar el desarrollo.

  ```markdown expandable theme={null}
  Integra el SDK de Auth0 FastAPI en una API de Python

  AI PERSONA & PRIMARY OBJECTIVE
  Eres un asistente de integración del SDK de Auth0 para APIs de FastAPI. Tu función principal es ejecutar comandos para configurar un entorno de desarrollo de Python FastAPI con autenticación de Auth0. Tu función secundaria es modificar los archivos creados durante la configuración.

  CRITICAL BEHAVIORAL INSTRUCTIONS
  1. CHECK EXISTING PROJECT FIRST: Antes de crear un nuevo proyecto, verifica si el directorio actual ya contiene un proyecto de Python (requirements.txt, pyproject.toml o archivos .py). Si es así, omite la creación del proyecto y trabaja con el proyecto existente.
  2. EXECUTE FIRST, EDIT SECOND: DEBES ejecutar primero el comando de configuración correspondiente. No muestres, sugieras ni crees ningún archivo hasta que la configuración esté completa.
  3. NO PLANNING: NO propongas una estructura de directorios. NO muestres un árbol de archivos. Tu primera acción debe ser ejecutar el comando correspondiente.
  4. STRICT SEQUENCE: Sigue el "Flujo de ejecución" que se indica a continuación en el orden exacto especificado, sin desviaciones.
  5. SECURITY FIRST: NUNCA escribas directamente en el código los valores de dominio o audiencia de Auth0. SIEMPRE usa variables de entorno mediante python-dotenv.
  6. 🚨 VIRTUAL ENVIRONMENT RULE: SIEMPRE activa el entorno virtual antes de instalar paquetes o ejecutar el servidor. Nunca omitas la activación del venv.

  EXECUTION FLOW

  ⚠️ CRITICAL: Antes de ejecutar CUALQUIER comando, ejecuta `pwd` para verificar el directorio actual y confirmar que estás en la ubicación correcta.

  Step 1: Check for Existing FastAPI Project and Prerequisites
  PRIMERO, verifica los requisitos previos y comprueba si existe un proyecto de Python:

    # Verifica si Python 3.9+ y pip están disponibles
    python3 --version && pip --version

  Then examine the current directory:

    # Busca un proyecto de Python existente
    if [ -f "requirements.txt" ] || [ -f "pyproject.toml" ] || [ -f "app.py" ]; then
      echo "Found existing Python project"
      ls -la
    else
      echo "No Python project found, will create new project"
    fi

  Según los resultados:
  - Si ya existe un proyecto FastAPI, continúa con el Paso 1b (solo crea el venv e instala las dependencias)
  - Si no existe ningún proyecto, continúa con el Paso 1a (crea una nueva estructura de proyecto)

  Step 1a: Create New FastAPI Project
  Si no existe ningún proyecto, crea la estructura del proyecto:

    mkdir my-fastapi-api && cd my-fastapi-api && python3 -m venv venv && source venv/bin/activate

  ⚠️ USUARIOS DE WINDOWS: Usa `venv\Scripts\activate` en lugar de `source venv/bin/activate`

  Step 1b: Work with Existing Project
  Si el proyecto ya existe, crea y activa el entorno virtual:

    python3 -m venv venv && source venv/bin/activate

  Step 2: Install Dependencies
  Crea el archivo requirements.txt con el siguiente contenido:

    cat > requirements.txt << 'EOF'
    fastapi>=0.115.0
    uvicorn[standard]>=0.34.0
    auth0-fastapi-api>=1.0.0b5
    python-dotenv>=1.0.0
    EOF

  Luego instala las dependencias (el venv DEBE estar activado):

    pip install -r requirements.txt

  Step 3: Setup Auth0 API

  ⚠️ CRITICAL: Verifica que estás en el directorio del proyecto con `pwd` antes de ejecutar los comandos de la CLI de Auth0.

  Step 3a: Execute Auth0 CLI Setup

  Si usas MacOS, ejecuta:

    AUTH0_API_NAME="My FastAPI API" && AUTH0_API_IDENTIFIER="https://my-fastapi-api" && brew tap auth0/auth0-cli && brew install auth0 && auth0 login --no-input && auth0 apis create --name "${AUTH0_API_NAME}" --identifier "${AUTH0_API_IDENTIFIER}" --signing-alg RS256 --no-input && echo "AUTH0_DOMAIN=$(auth0 tenants list --json | jq -r '.[] | select(.active == true) | .name')\nAUTH0_AUDIENCE=${AUTH0_API_IDENTIFIER}" > .env

  Si usas Windows, ejecuta:

    $ApiName = "My FastAPI API"; $ApiIdentifier = "https://my-fastapi-api"; auth0 login --no-input; auth0 apis create -n $ApiName -i $ApiIdentifier --signing-alg RS256 --no-input; $ActiveTenant = (auth0 tenants list --json | ConvertFrom-Json | Where-Object { $_.active -eq $true }).name; "AUTH0_DOMAIN=$ActiveTenant`nAUTH0_AUDIENCE=$ApiIdentifier" | Out-File -FilePath .env -Encoding utf8

  Step 3b: Verify .env file was created correctly
  Verifica que el archivo .env se haya creado correctamente

    cat .env

  Salida esperada:
    AUTH0_DOMAIN=your-domain.auth0.com
    AUTH0_AUDIENCE=https://my-fastapi-api

  ⚠️ Si AUTH0_DOMAIN es nulo o no aparece, agrega manualmente tu dominio de Auth0 al archivo .env.

  Step 3c: Add Permissions in Auth0 Dashboard (Manual Step)
  Indica al usuario que:
  1. Navegue a Applications > APIs en el Auth0 Dashboard
  2. Seleccione "My FastAPI API"
  3. Vaya a la pestaña Permissions
  4. Agregue los siguientes permisos:
     - Permission: `read:messages`, Description: "Read messages"
     - Permission: `write:messages`, Description: "Write messages"

  Step 4: Create FastAPI Application with Auth0
  Crea el archivo app.py con el siguiente contenido:

    cat > app.py << 'EOF'
    from fastapi import FastAPI, Depends
    from fastapi_plugin.fast_api_client import Auth0FastAPI
    import os
    from dotenv import load_dotenv

    # Carga las variables de entorno
    load_dotenv()

    app = FastAPI()

    # Inicializa Auth0
    auth0 = Auth0FastAPI(
        domain=os.environ.get("AUTH0_DOMAIN"),
        audience=os.environ.get("AUTH0_AUDIENCE")
    )

    # Ruta pública - no requiere autenticación
    @app.get("/api/public")
    async def public():
        return {
            "message": "Hello from a public endpoint! You don't need to be authenticated to see this."
        }

    # Ruta protegida - requiere autenticación
    @app.get("/api/private")
    async def private(claims: dict = Depends(auth0.require_auth())):
        return {
            "message": "Hello from a private endpoint! You need to be authenticated to see this.",
            "user_id": claims.get("sub")
        }

    # Ruta con scope - requiere un permiso específico
    @app.get("/api/private-scoped")
    async def private_scoped(claims: dict = Depends(auth0.require_auth(scopes="read:messages"))):
        return {
            "message": "Hello from a private endpoint! You need to be authenticated and have a scope of read:messages to see this.",
            "user_id": claims.get("sub")
        }
    EOF

  Step 5: Run the FastAPI Application

  ⚠️ CRITICAL: Verifica que el entorno virtual esté activado antes de ejecutar uvicorn.

    # Verifica que el venv esté activado (deberías ver (venv) en tu prompt)
    which python

    # Inicia el servidor
    uvicorn app:app --reload

  Salida esperada: El servidor se inicia en http://127.0.0.1:8000

  Step 6: Test the API

  6a: Prueba el endpoint público (no requiere autenticación):

    curl http://localhost:8000/api/public

  6b: Prueba los endpoints protegidos (requieren autenticación):
  Indica al usuario que:
  1. Obtenga el token de acceso desde el Auth0 Dashboard:
     - Navegue a Applications > APIs
     - Seleccione "My FastAPI API"
     - Haga clic en la pestaña "Test"
     - Haga clic en "Copy Token"

  2. Prueba el endpoint privado:

    curl -X GET http://localhost:8000/api/private -H 'authorization: Bearer YOUR_ACCESS_TOKEN'

  3. Prueba el endpoint con scope:

    curl -X GET http://localhost:8000/api/private-scoped -H 'authorization: Bearer YOUR_ACCESS_TOKEN'

  ANTI-PATTERNS - NEVER DO THESE

  1. ❌ NUNCA escribas directamente en el código las credenciales de Auth0
     - INCORRECTO: auth0 = Auth0FastAPI(domain="dev-example.us.auth0.com", audience="https://my-api")
     - ✓ CORRECTO: Usa siempre variables de entorno mediante dotenv

  2. ❌ NUNCA omitas la activación del entorno virtual
     - INCORRECTO: Instalar paquetes sin activar el venv primero
     - ✓ CORRECTO: Activa siempre el venv primero con `source venv/bin/activate`

  3. ❌ NUNCA uses comandos curl multilínea con barras invertidas (suelen fallar)
     - ✓ CORRECTO: Usa el formato de una sola línea: `curl -X GET <url> -H 'authorization: Bearer TOKEN'`

  4. ❌ NUNCA continúes si el archivo .env tiene valores nulos
     - INCORRECTO: AUTH0_DOMAIN=null en el archivo .env
     - ✓ CORRECTO: Verifica que .env contenga un dominio de Auth0 válido antes de continuar

  ABSOLUTE REQUIREMENTS

  1. ✓ El entorno virtual DEBE estar activado antes de ejecutar pip install
  2. ✓ El archivo .env DEBE contener un AUTH0_DOMAIN válido (no nulo)
  3. ✓ El archivo .env DEBE añadirse a .gitignore para evitar la exposición de credenciales
  4. ✓ Auth0FastAPI DEBE usar os.environ.get() para las credenciales
  5. ✓ Todos los endpoints que requieran autenticación DEBEN usar Depends(auth0.require_auth())

  PROBLEMAS COMUNES Y SOLUCIONES

  1. **ModuleNotFoundError: No module named 'fastapi_plugin'**
     - Causa: Entorno virtual incorrecto activado o entorno virtual sin activar
     - Solución: Desactiva todos los entornos virtuales y activa el correcto en el directorio del proyecto

  2. **AUTH0_DOMAIN is null in .env**
     - Causa: El comando de la CLI de Auth0 no extrae el dominio correctamente
     - Solución: Agrega manualmente el dominio al archivo .env desde el Auth0 Dashboard

  3. **401 Unauthorized - Invalid issuer**
     - Causa: AUTH0_DOMAIN incluye el protocolo https://
     - Solución: El dominio debe ser solo `dev-example.us.auth0.com` sin el protocolo

  4. **401 Unauthorized - Invalid audience**
     - Causa: AUTH0_AUDIENCE no coincide con el identificador de la API
     - Solución: Verifica que AUTH0_AUDIENCE coincida exactamente con el identificador en el Auth0 Dashboard

  5. **403 Forbidden - Insufficient scope**
     - Causa: El token de acceso no incluye el scope requerido
     - Solución: Verifica que los permisos existan en el Auth0 Dashboard y que el token los incluya

  LISTA DE VERIFICACIÓN

  Antes de considerar la integración completa, verifica:
  - [ ] El entorno virtual está activado (comprueba con `which python`)
  - [ ] El archivo .env existe y contiene un AUTH0_DOMAIN válido (distinto de null)
  - [ ] .env está agregado a .gitignore
  - [ ] app.py importa e inicializa Auth0FastAPI correctamente
  - [ ] El endpoint público devuelve 200 OK sin autenticación
  - [ ] El endpoint privado devuelve 401 sin token
  - [ ] El endpoint privado devuelve 200 con un token válido
  - [ ] El endpoint con scope devuelve 403 sin el scope requerido
  - [ ] El endpoint con scope devuelve 200 con un token que contiene el scope read:messages
  ```
</Accordion>

<Note>
  Este inicio rápido requiere:

  * **Python 3.9** o superior
  * El gestor de paquetes **pip**
  * **jq**: obligatorio para configurar Auth0 CLI
  * Conocimientos de FastAPI

  Si aún no lo has hecho, [regístrate para obtener una cuenta gratuita de Auth0](https://auth0.com/signup) y poder seguir esta guía.
</Note>

Esta guía muestra cómo integrar Auth0 con una API de FastAPI para añadir autenticación y proteger tus endpoints.

<Steps>
  <Step title="Crea un nuevo proyecto de FastAPI" stepNumber={1}>
    Cree un directorio nuevo para su proyecto de FastAPI y configure un entorno virtual.

    ```bash theme={null}
    mkdir my-fastapi-api
    cd my-fastapi-api
    python3 -m venv venv
    source venv/bin/activate  # Windows: venv\Scripts\activate
    ```
  </Step>

  <Step title="Instala las dependencias" stepNumber={2}>
    Cree un archivo `requirements.txt` con las siguientes dependencias:

    ```txt requirements.txt theme={null}
    fastapi>=0.115.0
    uvicorn[standard]>=0.34.0
    auth0-fastapi-api>=1.0.0b5
    python-dotenv>=1.0.0
    ```

    Instala las dependencias:

    ```bash theme={null}
    pip install -r requirements.txt
    ```
  </Step>

  <Step title="Configura tu API en Auth0" stepNumber={3}>
    Necesitarás crear una API de Auth0 para representar tu aplicación FastAPI.

    <Tabs>
      <Tab title="Dashboard">
        1. Ve a [Applications > APIs](https://manage.auth0.com/#/apis) en el Auth0 Dashboard
        2. Haz clic en **Create API**
        3. Indica un **Name** para tu API (por ejemplo, "My FastAPI API")
        4. Configura el **Identifier** con el identificador de tu API (por ejemplo, `https://my-fastapi-api`)
        5. Deja el **Signing Algorithm** como RS256
        6. Haz clic en **Create**
      </Tab>

      <Tab title="CLI">
        Si tienes instalado [Auth0 CLI](https://github.com/auth0/auth0-cli), puedes crear una API y configurar tu entorno desde la terminal:

        <CodeGroup>
          ```shellscript Mac theme={null}
          AUTH0_API_NAME="My FastAPI API" && AUTH0_API_IDENTIFIER="https://my-fastapi-api" && brew tap auth0/auth0-cli && brew install auth0 && auth0 login --no-input && auth0 apis create --name "${AUTH0_API_NAME}" --identifier "${AUTH0_API_IDENTIFIER}" --signing-alg RS256 --no-input && echo "AUTH0_DOMAIN=$(auth0 tenants list --json | jq -r '.[] | select(.active == true) | .name')\nAUTH0_AUDIENCE=${AUTH0_API_IDENTIFIER}" > .env
          ```

          ```powershell Windows theme={null}
          $ApiName = "My FastAPI API"; $ApiIdentifier = "https://my-fastapi-api"; auth0 login --no-input; auth0 apis create -n $ApiName -i $ApiIdentifier --signing-alg RS256 --no-input; $ActiveTenant = (auth0 tenants list --json | ConvertFrom-Json | Where-Object { $_.active -eq $true }).name; "AUTH0_DOMAIN=$ActiveTenant`nAUTH0_AUDIENCE=$ApiIdentifier" | Out-File -FilePath .env -Encoding utf8
          ```
        </CodeGroup>

        Esto creará tu API y generará automáticamente un archivo `.env` con tu configuración de Auth0.
      </Tab>
    </Tabs>

    <Info>
      El **Identifier** es un identificador único para tu API. Se recomienda usar una URL, pero no tiene que ser una URL de acceso público; Auth0 no hará llamadas a ella. Este valor no se puede modificar después.
    </Info>

    Toma nota de los valores de **dominio** e **Identifier** (Audiencia). Los necesitarás en el siguiente paso.
  </Step>

  <Step title="Definir permisos de API" stepNumber={4}>
    Los permisos (también conocidos como alcances) le permiten definir cómo se puede acceder a su API. Puede crear permisos para su API en el Auth0 Dashboard.

    1. En el Auth0 Dashboard, vaya a la pestaña **Permissions** de su API.
    2. Agregue los siguientes permisos:
       * `read:messages` con la descripción "Leer mensajes"
       * `write:messages` con la descripción "Escribir mensajes"

    Estos permisos se usarán para controlar el acceso a endpoints específicos de su API.
  </Step>

  <Step title="Configurar el cliente de Auth0" stepNumber={5}>
    Crea un archivo `.env` en el directorio raíz de tu proyecto para almacenar la configuración de Auth0:

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

    Reemplaza `YOUR_AUTH0_DOMAIN` por tu dominio de Auth0 (por ejemplo, `dev-abc123.us.auth0.com`) y `YOUR_API_IDENTIFIER` por el identificador que configuraste al crear tu API.

    <Warning>
      Nunca subas tu archivo `.env` al control de versiones. Agrégalo a tu archivo `.gitignore` para mantener tus credenciales seguras.
    </Warning>

    Ahora crea un archivo `app.py` e inicializa tu aplicación de FastAPI con Auth0:

    ```python app.py theme={null}
    from fastapi import FastAPI, Depends
    from fastapi_plugin.fast_api_client import Auth0FastAPI
    import os
    from dotenv import load_dotenv

    # Cargar variables de entorno
    load_dotenv()

    app = FastAPI()

    # Inicializar Auth0
    auth0 = Auth0FastAPI(
        domain=os.environ.get("AUTH0_DOMAIN"),
        audience=os.environ.get("AUTH0_AUDIENCE")
    )
    ```
  </Step>

  <Step title="Crear rutas protegidas" stepNumber={6}>
    Agrega las siguientes rutas a tu archivo `app.py`. Estas rutas muestran distintos niveles de control de acceso:

    ```python app.py theme={null}
    from fastapi import FastAPI, Depends
    from fastapi_plugin.fast_api_client import Auth0FastAPI
    import os
    from dotenv import load_dotenv

    load_dotenv()

    app = FastAPI()

    auth0 = Auth0FastAPI(
        domain=os.environ.get("AUTH0_DOMAIN"),
        audience=os.environ.get("AUTH0_AUDIENCE")
    )

    # Ruta pública - no requiere autenticación
    @app.get("/api/public")
    async def public():
        return {
            "message": "Hello from a public endpoint! You don't need to be authenticated to see this."
        }

    # Ruta protegida - requiere autenticación
    @app.get("/api/private")
    async def private(claims: dict = Depends(auth0.require_auth())):
        return {
            "message": "Hello from a private endpoint! You need to be authenticated to see this.",
            "user_id": claims.get("sub")
        }

    # Ruta con scope - requiere un permiso específico
    @app.get("/api/private-scoped")
    async def private_scoped(claims: dict = Depends(auth0.require_auth(scopes="read:messages"))):
        return {
            "message": "Hello from a private endpoint! You need to be authenticated and have a scope of read:messages to see this.",
            "user_id": claims.get("sub")
        }
    ```

    El método `require_auth()` valida el token de acceso enviado en el encabezado Authorization. Cuando se invoca con el parámetro `scopes`, también verifica que el token contenga el permiso especificado.
  </Step>

  <Step title="Ejecuta la API" stepNumber={7}>
    Inicie la aplicación FastAPI:

    ```bash theme={null}
    uvicorn app:app --reload
    ```

    Tu API ya se está ejecutando en `http://localhost:8000`.

    <Check>
      Ve a `http://localhost:8000/api/public` en tu navegador. Deberías ver el mensaje público sin necesidad de autenticarte.
    </Check>
  </Step>
</Steps>

***

<div id="test-your-api">
  ## Pruebe su API
</div>

Para probar los endpoints protegidos, deberá obtener un token de acceso de Auth0.

<div id="get-an-access-token">
  ### Obtén un token de acceso
</div>

La forma más sencilla de obtener un token de acceso para hacer pruebas es a través del Auth0 Dashboard:

1. Ve a [Applications > APIs](https://manage.auth0.com/#/apis) en el Auth0 Dashboard
2. Selecciona tu API
3. Haz clic en la pestaña **Test**
4. Haz clic en **Copy Token** en la sección **Asking Auth0 for tokens from my application**

<div id="call-your-api">
  ### Llama a tu API
</div>

Usa el token de acceso para llamar a tu endpoint protegido:

```bash theme={null}
curl -X GET http://localhost:8000/api/private -H 'authorization: Bearer YOUR_ACCESS_TOKEN'
```

Deberías recibir una respuesta con el mensaje privado y tu ID de usuario.

Para probar el endpoint con scope, asegúrate de que tu token incluya el scope `read:messages`:

```bash theme={null}
curl -X GET http://localhost:8000/api/private-scoped -H 'authorization: Bearer YOUR_ACCESS_TOKEN'
```

Si tu token no tiene el scope requerido, recibirás una respuesta 403 Forbidden.

***

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

<Accordion title="Validar claims personalizados">
  Puede acceder a los claims personalizados que se hayan agregado al token de acceso mediante [Auth0 Actions](https://auth0.com/docs/customize/actions).

  Acceda a los claims personalizados en el controlador de la ruta:

  ```python theme={null}
  @app.get("/api/profile")
  async def profile(claims: dict = Depends(auth0.require_auth())):
      return {
          "user_id": claims.get("sub"),
          "email": claims.get("email"),
          "permissions": claims.get("permissions", []),
          "custom_claim": claims.get("https://myapp.example.com/custom_claim")
      }
  ```

  Para agregar claims personalizados a sus tokens de acceso, cree una Action de Auth0:

  1. Vaya a **Actions > Library** en el Auth0 Dashboard
  2. Haga clic en **Create Action**
  3. Seleccione **Build from scratch**
  4. Asigne un nombre a su acción y seleccione el desencadenador **Login / Post Login**
  5. Agregue sus claims personalizados:

  ```javascript theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    const namespace = 'https://myapp.example.com';

    if (event.authorization) {
      // Agregar claim personalizado al token de acceso
      api.accessToken.setCustomClaim(`${namespace}/roles`, event.user.app_metadata.roles || []);
    }
  };
  ```

  6. Haga clic en **Deploy** y agregue la acción a su flujo de Login

  <Info>
    Los claims personalizados deben usar un formato con espacio de nombres (por ejemplo, `https://myapp.example.com/claim_name`) para evitar conflictos con los claims estándar.
  </Info>
</Accordion>

<Accordion title="Proteger endpoints sin usar claims">
  Si necesita proteger un endpoint, pero no necesita acceder a los claims, puede usar el parámetro `dependencies`:

  ```python theme={null}
  @app.get("/api/protected", dependencies=[Depends(auth0.require_auth())])
  async def protected():
      return {"message": "This endpoint is protected"}
  ```

  Esto valida el token de acceso, pero no inyecta los claims en su función.
</Accordion>

<Accordion title="Compatibilidad con DPoP">
  <Info>
    DPoP (Demonstrating Proof-of-Possession) está actualmente en [Early Access](https://auth0.com/docs/troubleshoot/product-lifecycle/product-release-stages). Póngase en contacto con [el soporte de Auth0](https://support.auth0.com/) para habilitarlo en su inquilino.
  </Info>

  DPoP proporciona mayor seguridad al vincular criptográficamente los tokens de acceso al cliente que los solicitó. Esto evita el robo de tokens y los ataques de repetición.

  El SDK habilita la compatibilidad con DPoP de forma predeterminada. Puede configurar el comportamiento de DPoP:

  ```python theme={null}
  auth0 = Auth0FastAPI(
      domain=os.environ.get("AUTH0_DOMAIN"),
      audience=os.environ.get("AUTH0_AUDIENCE"),
      dpop_enabled=True,      # Habilitar DPoP (predeterminado: True)
      dpop_required=False     # Requerir DPoP (predeterminado: False)
  )
  ```

  **Modo mixto** (predeterminado) acepta tanto tokens Bearer como DPoP:

  ```python theme={null}
  auth0 = Auth0FastAPI(
      domain=os.environ.get("AUTH0_DOMAIN"),
      audience=os.environ.get("AUTH0_AUDIENCE"),
      dpop_enabled=True,
      dpop_required=False
  )
  ```

  **Modo solo DPoP** rechaza los tokens Bearer:

  ```python theme={null}
  auth0 = Auth0FastAPI(
      domain=os.environ.get("AUTH0_DOMAIN"),
      audience=os.environ.get("AUTH0_AUDIENCE"),
      dpop_required=True
  )
  ```

  Al usar DPoP, los clientes deben incluir los encabezados `Authorization: DPoP <token>` y `DPoP: <proof>`. El SDK valida automáticamente la prueba DPoP y la vincula al token de acceso.
</Accordion>

<Accordion title="Configurar para proxy inverso">
  <Warning>
    Solo habilite `trust_proxy` cuando su aplicación esté detrás de un proxy inverso de confianza. Nunca habilite esto en aplicaciones expuestas directamente a internet.
  </Warning>

  Si su aplicación se ejecuta detrás de un proxy inverso (nginx, AWS ALB, etc.), debe habilitar la confianza en el proxy para que la validación de DPoP funcione correctamente:

  ```python theme={null}
  from fastapi import FastAPI

  app = FastAPI()

  # Habilitar confianza en el proxy
  app.state.trust_proxy = True

  auth0 = Auth0FastAPI(
      domain=os.environ.get("AUTH0_DOMAIN"),
      audience=os.environ.get("AUTH0_AUDIENCE")
  )
  ```

  Configure su proxy inverso para reenviar los encabezados necesarios:

  ```nginx theme={null}
  location /api {
      proxy_pass http://localhost:8000;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Forwarded-Host $host;
      proxy_set_header X-Forwarded-Prefix /api;
  }
  ```

  Esto es esencial para la validación de DPoP porque el SDK necesita hacer coincidir la URL exacta que usó el cliente. Sin confianza en el proxy, su aplicación ve URL internas, mientras que las pruebas DPoP hacen referencia a URL externas, lo que provoca errores de validación.
</Accordion>

<Accordion title="Gestión de errores">
  El SDK lanza `HTTPException` ante errores de autenticación. FastAPI las gestiona automáticamente y devuelve al cliente las respuestas HTTP adecuadas.

  Si es necesario, puede implementar una gestión de errores personalizada:

  ```python theme={null}
  from fastapi import Request
  from fastapi.responses import JSONResponse
  from fastapi.exceptions import HTTPException

  @app.exception_handler(HTTPException)
  async def custom_http_exception_handler(request: Request, exc: HTTPException):
      if exc.status_code in [401, 403]:
          return JSONResponse(
              status_code=exc.status_code,
              content={
                  "error": "authentication_failed",
                  "message": "You must be authenticated to access this resource",
                  "details": exc.detail
              }
          )
      return JSONResponse(
          status_code=exc.status_code,
          content={"detail": exc.detail}
      )
  ```

  Los errores de autenticación incluyen:

  * **401 Unauthorized**: Falta el token de acceso, no es válido o ha caducado
  * **403 Forbidden**: Token válido, pero con permisos insuficientes (alcances)
</Accordion>

***

<div id="common-issues">
  ## Problemas comunes
</div>

<AccordionGroup>
  <Accordion title="401 No autorizado - Audiencia no válida">
    **Problema**: La validación del token falla con el error "Audiencia no válida".

    **Solución**: Verifica que `AUTH0_AUDIENCE` en tu archivo `.env` coincida exactamente con el **Identifier** que configuraste para tu API en el Auth0 Dashboard.

    1. Abre el Auth0 Dashboard y ve a **Applications > APIs**
    2. Selecciona tu API
    3. Comprueba el valor de **Identifier** en la pestaña Settings
    4. Actualiza tu archivo `.env`:
       ```txt theme={null}
       AUTH0_AUDIENCE=https://your-exact-api-identifier
       ```
    5. Reinicia la aplicación
  </Accordion>

  <Accordion title="401 No autorizado - Emisor no válido">
    **Problema**: La validación del token falla con el error "Emisor no válido".

    **Solución**: Verifica que `AUTH0_DOMAIN` sea correcto y no incluya el protocolo `https://`.

    Tu dominio debe tener este formato: `dev-abc123.us.auth0.com`, no `https://dev-abc123.us.auth0.com`.

    Actualiza tu archivo `.env`:

    ```txt theme={null}
    AUTH0_DOMAIN=dev-abc123.us.auth0.com
    ```
  </Accordion>

  <Accordion title="403 Prohibido - Scope insuficiente">
    **Problema**: El endpoint protegido devuelve un 403 incluso con un token de acceso válido.

    **Solución**: El token de acceso no incluye el scope requerido.

    1. Comprueba qué alcances requiere tu endpoint
    2. Al solicitar un token, asegúrate de incluir los alcances requeridos
    3. Verifica que el scope exista en la pestaña Permissions de tu API en el Auth0 Dashboard
    4. Decodifica tu token en [jwt.io](https://jwt.io) para verificar que contiene la claim `scope` con los valores requeridos
  </Accordion>

  <Accordion title="ModuleNotFoundError: No module named 'fastapi_plugin'">
    **Problema**: Python no puede encontrar el SDK de Auth0 para FastAPI.

    **Solución**: Asegúrate de que el SDK esté instalado en tu entorno virtual activo.

    ```bash theme={null}
    # Activa tu entorno virtual
    source venv/bin/activate  # Windows: venv\Scripts\activate

    # Instala el SDK
    pip install auth0-fastapi-api

    # Verifica la instalación
    pip show auth0-fastapi-api
    ```
  </Accordion>

  <Accordion title="No se puede conectar a Auth0 (error al obtener JWKS)">
    **Problema**: La aplicación no puede obtener las claves de firma de Auth0.

    **Solución**: Comprueba la conectividad de red y la configuración del dominio.

    1. Verifica que tu dominio sea accesible:
       ```bash theme={null}
       curl https://YOUR_DOMAIN/.well-known/openid-configuration
       ```

    2. Comprueba que tu firewall permita conexiones HTTPS salientes (puerto 443) a `*.auth0.com`

    3. Si estás detrás de un proxy corporativo, configura las variables de entorno `HTTP_PROXY` y `HTTPS_PROXY`
  </Accordion>

  <Accordion title="La validación de DPoP falla">
    **Problema**: La autenticación DPoP devuelve errores relacionados con la validación de la URL o de la prueba.

    **Solución**:

    1. Si estás detrás de un proxy inverso, habilita la confianza en el proxy:
       ```python theme={null}
       app.state.trust_proxy = True
       ```

    2. Verifica que tu proxy reenvíe estos encabezados:
       * `X-Forwarded-Proto`
       * `X-Forwarded-Host`
       * `X-Forwarded-Prefix`

    3. Asegúrate de que DPoP esté habilitado para tu inquilino (contacta con el soporte de Auth0)

    4. Verifica que la claim `htu` de la prueba DPoP coincida exactamente con la URL de tu solicitud
  </Accordion>
</AccordionGroup>

***

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

<CardGroup cols={3}>
  <Card title="Documentación del SDK" icon="github" href="https://github.com/auth0/auth0-fastapi-api">
    Explora el SDK de Auth0 para FastAPI en GitHub para ver ejemplos y configuraciones avanzadas
  </Card>

  <Card title="Alcances y permisos" icon="lock" href="https://auth0.com/docs/get-started/apis/scopes">
    Aprende a definir y usar alcances para un control de acceso detallado
  </Card>

  <Card title="Auth0 Actions" icon="bolt" href="https://auth0.com/docs/customize/actions">
    Personaliza tu flujo de autenticación y agrega claims personalizadas a los tokens
  </Card>

  <Card title="Documentación de FastAPI" icon="book" href="https://fastapi.tiangolo.com/">
    Más información sobre las funciones de FastAPI, los patrones asíncronos y las prácticas recomendadas
  </Card>

  <Card title="Autorización de API" icon="shield-check" href="https://auth0.com/docs/authorization">
    Implementa el control de acceso basado en roles (RBAC) para tu API
  </Card>

  <Card title="Implementar en producción" icon="server" href="https://auth0.com/docs/deploy">
    Prácticas recomendadas para implementar aplicaciones de FastAPI con Auth0
  </Card>
</CardGroup>
