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

> Añade la autenticación de Auth0 a una aplicación web de Flask con inicio de sesión, rutas protegidas y perfiles de usuario

# Añade el inicio de sesión a tu aplicación Flask

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

export const AuthCodeGroup = ({children, dropdown}) => {
  const [processedChildren, setProcessedChildren] = useState(children);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      unsubscribe = window.autorun(() => {
        const processChildren = node => {
          if (typeof node === "string") {
            let processedNode = node;
            for (const [key, value] of window.rootStore.variableStore.values.entries()) {
              const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
              processedNode = processedNode.replaceAll(new RegExp(escapedKey, "g"), value);
            }
            return processedNode;
          } else if (Array.isArray(node)) {
            return node.map(processChildren);
          } else if (node && node.props && node.props.children) {
            return {
              ...node,
              props: {
                ...node.props,
                children: processChildren(node.props.children)
              }
            };
          }
          return node;
        };
        setProcessedChildren(processChildren(children));
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  return <CodeGroup dropdown={dropdown}>{processedChildren}</CodeGroup>;
};

<HowToSchema />

<Note>
  **Requisitos previos:** Antes de comenzar, asegúrese de tener instalados los siguientes componentes:

  * **[Python](https://www.python.org/downloads/)** 3.9 o posterior
  * **[pip](https://pip.pypa.io/en/stable/installation/)** 20.0 o posterior
  * **[jq](https://jqlang.org/)** - Necesario para configurar la CLI de Auth0

  **Compatibilidad de versiones de Flask:** Esta guía de inicio rápido usa **Flask 2.0+** con el extra `[async]` para habilitar la compatibilidad asíncrona.
</Note>

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

Esta guía de inicio rápido muestra cómo agregar la autenticación de Auth0 a una aplicación Flask. Crearás una aplicación web segura con funcionalidad de inicio de sesión, rutas protegidas y acceso al perfil del usuario mediante el [SDK web de Python de Auth0](https://github.com/auth0/auth0-server-python).

<Steps>
  <Step title="Configura tu entorno" stepNumber={1}>
    Crea un nuevo directorio para tu proyecto de Flask:

    ```bash theme={null}
    mkdir auth0-flask-app && cd auth0-flask-app
    ```

    Crea un entorno virtual:

    ```bash theme={null}
    python -m venv venv
    source venv/bin/activate  # En Windows: venv\Scripts\activate
    ```
  </Step>

  <Step title="Instala las dependencias" stepNumber={2}>
    Cree el archivo `requirements.txt` para registrar sus dependencias:

    ```txt requirements.txt theme={null}
    auth0-server-python>=1.0.0b7
    flask[async]>=2.0.0
    python-dotenv>=1.0.0
    ```

    El archivo `requirements.txt` enumera todas las dependencias del proyecto. Para instalarlas, ejecute:

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

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

    Puede hacerlo automáticamente ejecutando un comando de CLI o de forma manual a través del Dashboard:

    <Tabs>
      <Tab title="CLI">
        Ejecuta el siguiente comando de shell en el directorio raíz de tu proyecto para crear una aplicación de Auth0 y generar un archivo `.env`:

        <CodeGroup>
          ```shellscript Mac theme={null}
          AUTH0_APP_NAME="My Flask App" && brew tap auth0/auth0-cli && brew install auth0 && auth0 login --no-input && auth0 apps create -n "${AUTH0_APP_NAME}" -t regular -c http://localhost:5000/callback -l http://localhost:5000 -o http://localhost:5000 --reveal-secrets --json > app-details.json && CLIENT_ID=$(python3 -c "import json; print(json.load(open('app-details.json'))['client_id'])") && CLIENT_SECRET=$(python3 -c "import json; print(json.load(open('app-details.json'))['client_secret'])") && DOMAIN=$(auth0 tenants list --json | python3 -c "import sys, json; print([t['name'] for t in json.load(sys.stdin) if t.get('active')][0])") && SECRET=$(openssl rand -hex 64) && echo "AUTH0_DOMAIN=${DOMAIN}" > .env && echo "AUTH0_CLIENT_ID=${CLIENT_ID}" >> .env && echo "AUTH0_CLIENT_SECRET=${CLIENT_SECRET}" >> .env && echo "AUTH0_SECRET=${SECRET}" >> .env && echo "AUTH0_REDIRECT_URI=http://localhost:5000/callback" >> .env && rm app-details.json && echo ".env file created with your Auth0 details:" && cat .env
          ```

          ```shellscript Windows theme={null}
          $AppName = "My Flask App"; winget install Auth0.CLI; auth0 login --no-input; auth0 apps create -n "$AppName" -t regular -c http://localhost:5000/callback -l http://localhost:5000 -o http://localhost:5000 --reveal-secrets --json | Set-Content -Path app-details.json; $ClientId = (Get-Content -Raw app-details.json | ConvertFrom-Json).client_id; $ClientSecret = (Get-Content -Raw app-details.json | ConvertFrom-Json).client_secret; $Domain = (auth0 tenants list --json | ConvertFrom-Json | Where-Object { $_.active -eq $true }).name; $Secret = [System.Convert]::ToHexString([System.Security.Cryptography.RandomNumberGenerator]::GetBytes(64)).ToLower(); Set-Content -Path .env -Value "AUTH0_DOMAIN=$Domain"; Add-Content -Path .env -Value "AUTH0_CLIENT_ID=$ClientId"; Add-Content -Path .env -Value "AUTH0_CLIENT_SECRET=$ClientSecret"; Add-Content -Path .env -Value "AUTH0_SECRET=$Secret"; Add-Content -Path .env -Value "AUTH0_REDIRECT_URI=http://localhost:5000/callback"; Remove-Item app-details.json; Write-Output ".env file created with your Auth0 details:"; Get-Content .env
          ```
        </CodeGroup>
      </Tab>

      <Tab title="Dashboard">
        Antes de comenzar, crea un archivo `.env` en la raíz de tu proyecto:

        ```bash .env theme={null}
        # Configuración de Auth0
        AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN
        AUTH0_CLIENT_ID=YOUR_CLIENT_ID
        AUTH0_CLIENT_SECRET=YOUR_CLIENT_SECRET
        AUTH0_SECRET=YOUR_GENERATED_SECRET
        AUTH0_REDIRECT_URI=http://localhost:5000/callback
        ```

        1. Ve a [Auth0 Dashboard](https://manage.auth0.com/dashboard/) → **Applications** → **Applications**
        2. Haz clic en **Create Application**
        3. Asigna un nombre a tu aplicación (por ejemplo, "My Flask App") y selecciona **Regular Web Application**
        4. Haz clic en **Create**
        5. En la pestaña **Settings**, configura lo siguiente:
           * **Allowed Callback URLs**: `http://localhost:5000/callback`
           * **Allowed Logout URLs**: `http://localhost:5000`
           * **Allowed Web Origins**: `http://localhost:5000`
        6. Haz clic en **Save Changes**
        7. Reemplaza `YOUR_AUTH0_DOMAIN` en `.env` por tu **dominio** de la pestaña **Settings** (por ejemplo, `your-tenant.auth0.com`)
        8. Reemplaza `YOUR_CLIENT_ID` en `.env` por tu **ID de cliente**
        9. Reemplaza `YOUR_CLIENT_SECRET` en `.env` por tu **Secreto del cliente**

        Genera un secreto seguro para `AUTH0_SECRET`:

        ```bash theme={null}
        openssl rand -hex 64
        ```

        <Info>
          **Importante:** Nunca subas tu archivo `.env` al control de versiones. Agrégalo a `.gitignore`.
        </Info>
      </Tab>
    </Tabs>
  </Step>

  <Step title="Crear la configuración de autenticación, las rutas y las plantillas" stepNumber={4}>
    Crear archivos

    ```bash theme={null}
    mkdir templates static && touch app.py auth.py templates/index.html templates/profile.html static/style.css
    ```

    Y agrega los siguientes fragmentos de código:

    <AuthCodeGroup>
      ```python auth.py expandable lines theme={null}
      import os
      from auth0_server_python.auth_server.server_client import ServerClient
      from dotenv import load_dotenv

      load_dotenv()

      # Almacenamiento simple en memoria para desarrollo
      # Para producción, use Redis, PostgreSQL u otro almacenamiento persistente
      class MemoryStateStore:
          """In-memory state store for session data (development only)"""
          def __init__(self):
              self._data = {}
          
          async def get(self, key, options=None):
              return self._data.get(key)
          
          async def set(self, key, value, options=None):
              self._data[key] = value
          
          async def delete(self, key, options=None):
              self._data.pop(key, None)
          
          async def delete_by_logout_token(self, claims, options=None):
              # Para soporte de logout por backchannel
              pass

      class MemoryTransactionStore:
          """In-memory transaction store for OAuth flows (development only)"""
          def __init__(self):
              self._data = {}
          
          async def get(self, key, options=None):
              return self._data.get(key)
          
          async def set(self, key, value, options=None):
              self._data[key] = value
          
          async def delete(self, key, options=None):
              self._data.pop(key, None)

      # Inicializar los almacenes
      state_store = MemoryStateStore()
      transaction_store = MemoryTransactionStore()

      # Inicializar el ServerClient de Auth0
      auth0 = ServerClient(
          domain=os.getenv('AUTH0_DOMAIN'),
          client_id=os.getenv('AUTH0_CLIENT_ID'),
          client_secret=os.getenv('AUTH0_CLIENT_SECRET'),
          secret=os.getenv('AUTH0_SECRET'),
          redirect_uri=os.getenv('AUTH0_REDIRECT_URI'),
          state_store=state_store,
          transaction_store=transaction_store,
          authorization_params={
              'scope': 'openid profile email',
              'audience': os.getenv('AUTH0_AUDIENCE', '')  # Opcional: para acceso a la API
          }
      )
      ```

      ```python app.py expandable lines theme={null}
      import os
      from flask import Flask, redirect, render_template, request, url_for, g
      from auth0_server_python.auth_types import LogoutOptions
      from auth import auth0
      from dotenv import load_dotenv

      load_dotenv()

      app = Flask(__name__)
      app.secret_key = os.getenv('AUTH0_SECRET')

      # Configurar sesión para Auth0
      app.config.update(
          SESSION_COOKIE_SECURE=False,  # Establecer en True en producción con HTTPS
          SESSION_COOKIE_HTTPONLY=True,
          SESSION_COOKIE_SAMESITE='Lax',
      )

      @app.before_request
      def store_request_response():
          """Make request/response available for Auth0 SDK"""
          g.store_options = {"request": request}

      @app.route('/')
      async def index():
          """Home page - shows login button or user profile"""
          user = await auth0.get_user(g.store_options)
          return render_template('index.html', user=user)

      @app.route('/login')
      async def login():
          """Redirect to Auth0 login"""
          authorization_url = await auth0.start_interactive_login({}, g.store_options)
          return redirect(authorization_url)

      @app.route('/callback')
      async def callback():
          """Handle Auth0 callback after login"""
          try:
              result = await auth0.complete_interactive_login(str(request.url), g.store_options)
              return redirect(url_for('index'))
          except Exception as e:
              return f"Authentication error: {str(e)}", 400

      @app.route('/profile')
      async def profile():
          """Protected route - shows user profile"""
          user = await auth0.get_user(g.store_options)
          
          if not user:
              return redirect(url_for('login'))
          
          return render_template('profile.html', user=user)

      @app.route('/logout')
      async def logout():
          """Logout and redirect to Auth0 logout"""
          options = LogoutOptions(return_to=url_for("index", _external=True))
          logout_url = await auth0.logout(options, g.store_options)
          return redirect(logout_url)

      if __name__ == '__main__':
          app.run(debug=True, port=5000)
      ```

      ```html templates/index.html expandable lines theme={null}
      <!DOCTYPE html>
      <html lang="en">
      <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Flask + Auth0</title>
      <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
      </head>
      <body>
      <div class="container">
          <div class="card">
              <img src="https://cdn.auth0.com/quantum-assets/dist/latest/logos/auth0/auth0-lockup-en-ondark.png"
                   alt="Auth0 Logo" class="logo">
              <h1>Flask + Auth0</h1>
              
              {% if user %}
                  <div class="logged-in">
                      <p class="success">✅ Successfully logged in!</p>
                      <div class="user-info">
                          {% if user.picture %}
                          <img src="{{ user.picture }}" alt="Profile" class="profile-pic">
                          {% endif %}
                          <h2>{{ user.name }}</h2>
                          <p>{{ user.email }}</p>
                      </div>
                      <a href="/profile" class="button">View Full Profile</a>
                      <a href="/logout" class="button logout">Log Out</a>
                  </div>
              {% else %}
                  <div class="logged-out">
                      <p>Welcome! Please log in to access your protected content.</p>
                      <a href="/login" class="button">Log In</a>
                  </div>
              {% endif %}
          </div>
      </div>
      </body>
      </html>
      ```

      ```html templates/profile.html expandable lines theme={null}
      <!DOCTYPE html>
      <html lang="en">
      <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>User Profile - Flask + Auth0</title>
      <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
      </head>
      <body>
      <div class="container">
          <div class="card">
              <img src="https://cdn.auth0.com/quantum-assets/dist/latest/logos/auth0/auth0-lockup-en-ondark.png"
                   alt="Auth0 Logo" class="logo">
              <h1>User Profile</h1>
              
              <div class="profile-details">
                  {% if user.picture %}
                  <img src="{{ user.picture }}" alt="Profile" class="profile-pic-large">
                  {% endif %}
                  
                  <div class="profile-info">
                      <h2>{{ user.name }}</h2>
                      <p class="email">{{ user.email }}</p>
                      
                      <div class="profile-data">
                          <h3>Profile Information</h3>
                          <dl>
                              <dt>User ID:</dt>
                              <dd>{{ user.sub }}</dd>
                              
                              {% if user.nickname %}
                              <dt>Nickname:</dt>
                              <dd>{{ user.nickname }}</dd>
                              {% endif %}
                              
                              {% if user.updated_at %}
                              <dt>Last Updated:</dt>
                              <dd>{{ user.updated_at }}</dd>
                              {% endif %}
                          </dl>
                      </div>
                  </div>
              </div>
              
              <div class="actions">
                  <a href="/" class="button">Back to Home</a>
                  <a href="/logout" class="button logout">Log Out</a>
              </div>
          </div>
      </div>
      </body>
      </html>
      ```

      ```css static/style.css expandable lines theme={null}
      @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');

      * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
      }

      body {
      font-family: 'Inter', sans-serif;
      background: linear-gradient(135deg, #1a1e27 0%, #2d313c 100%);
      min-height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
      color: #e2e8f0;
      padding: 20px;
      }

      .container {
      width: 100%;
      max-width: 600px;
      }

      .card {
      background-color: #262a33;
      border-radius: 20px;
      box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.05);
      padding: 3rem;
      animation: fadeInScale 0.6s ease-out;
      }

      @keyframes fadeInScale {
      from {
          opacity: 0;
          transform: scale(0.95);
      }
      to {
          opacity: 1;
          transform: scale(1);
      }
      }

      .logo {
      width: 160px;
      margin: 0 auto 2rem;
      display: block;
      animation: slideDown 0.8s ease-out;
      }

      @keyframes slideDown {
      from {
          opacity: 0;
          transform: translateY(-30px);
      }
      to {
          opacity: 1;
          transform: translateY(0);
      }
      }

      h1 {
      font-size: 2.5rem;
      font-weight: 700;
      text-align: center;
      margin-bottom: 2rem;
      color: #f7fafc;
      text-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
      }

      h2 {
      font-size: 1.8rem;
      font-weight: 600;
      margin: 0.5rem 0;
      color: #f7fafc;
      }

      h3 {
      font-size: 1.3rem;
      font-weight: 600;
      margin-top: 1.5rem;
      margin-bottom: 1rem;
      color: #cbd5e0;
      }

      .logged-in, .logged-out {
      text-align: center;
      }

      .logged-out p {
      font-size: 1.2rem;
      color: #cbd5e0;
      margin-bottom: 2rem;
      line-height: 1.6;
      }

      .success {
      font-size: 1.5rem;
      color: #68d391;
      font-weight: 600;
      margin-bottom: 1.5rem;
      }

      .user-info {
      background-color: #2d313c;
      border-radius: 15px;
      padding: 2rem;
      margin: 2rem 0;
      }

      .profile-pic {
      width: 80px;
      height: 80px;
      border-radius: 50%;
      margin-bottom: 1rem;
      border: 3px solid #63b3ed;
      object-fit: cover;
      }

      .profile-pic-large {
      width: 120px;
      height: 120px;
      border-radius: 50%;
      margin-bottom: 1rem;
      border: 4px solid #63b3ed;
      object-fit: cover;
      }

      .user-info p, .email {
      color: #a0aec0;
      font-size: 1.1rem;
      }

      .button {
      display: inline-block;
      padding: 1rem 2.5rem;
      font-size: 1.1rem;
      font-weight: 600;
      border-radius: 10px;
      border: none;
      cursor: pointer;
      transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
      text-decoration: none;
      text-transform: uppercase;
      letter-spacing: 0.08em;
      margin: 0.5rem;
      background-color: #63b3ed;
      color: #1a1e27;
      box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
      }

      .button:hover {
      background-color: #4299e1;
      transform: translateY(-3px);
      box-shadow: 0 12px 25px rgba(0, 0, 0, 0.5);
      }

      .button.logout {
      background-color: #fc8181;
      }

      .button.logout:hover {
      background-color: #e53e3e;
      }

      .profile-details {
      text-align: center;
      }

      .profile-info {
      background-color: #2d313c;
      border-radius: 15px;
      padding: 2rem;
      margin-top: 1.5rem;
      }

      .profile-data {
      margin-top: 2rem;
      text-align: left;
      }

      .profile-data dl {
      display: grid;
      grid-template-columns: 150px 1fr;
      gap: 1rem;
      margin-top: 1rem;
      }

      .profile-data dt {
      font-weight: 600;
      color: #cbd5e0;
      }

      .profile-data dd {
      color: #a0aec0;
      word-break: break-all;
      }

      .actions {
      margin-top: 2rem;
      display: flex;
      justify-content: center;
      flex-wrap: wrap;
      }

      @media (max-width: 600px) {
      .card {
          padding: 2rem;
      }

      h1 {
          font-size: 2rem;
      }

      .button {
          padding: 0.8rem 2rem;
          font-size: 1rem;
      }

      .logo {
          width: 120px;
      }

      .profile-data dl {
          grid-template-columns: 1fr;
          gap: 0.5rem;
      }

      .profile-data dt {
          margin-top: 1rem;
      }
      }
      ```
    </AuthCodeGroup>

    <Info>
      **Solo para desarrollo:** Este ejemplo usa clases simples de almacenamiento en memoria (`MemoryStateStore` y `MemoryTransactionStore`) solo con fines de demostración. Estos almacenamientos perderán todos los datos de sesión cuando la aplicación se reinicie y no funcionarán en implementaciones de varias instancias.

      **Para aplicaciones de producción**, debe implementar almacenamiento persistente. El SDK es independiente del framework y requiere que proporcione implementaciones personalizadas de `StateStore` y `TransactionStore`. Consulte los [ejemplos oficiales de almacenamiento del SDK](https://github.com/auth0/auth0-server-python/blob/main/examples/ConfigureStore.md) para obtener instrucciones detalladas sobre cómo implementar Redis, PostgreSQL u otros backends de almacenamiento persistente.
    </Info>
  </Step>

  <Step title="Ejecuta tu aplicación" stepNumber={5}>
    Inicia el servidor de desarrollo de Flask:

    ```bash theme={null}
    python app.py
    ```

    Tu aplicación estará disponible en [http://localhost:5000](http://localhost:5000). El SDK de Auth0 gestiona automáticamente las rutas de autenticación.
  </Step>
</Steps>

<Check>
  **Punto de control**

  Ahora deberías tener una página de inicio de sesión de Auth0 completamente funcional ejecutándose en [localhost](http://localhost:5000/)
</Check>

***

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

<Accordion title="Obtención de tokens de API">
  Si necesita llamar a una API protegida, recupere un token de acceso:

  ```python theme={null}
  @app.route('/api-call')
  @require_auth
  async def api_call():
      try:
          # Obtener un token de acceso para su API
          access_token = await auth0.get_access_token(
              audience='https://your-api.example.com',
              store_options=g.store_options
          )
          
          # Usar el token para llamar a su API
          # headers = {'Authorization': f'Bearer {access_token}'}
          # response = requests.get('https://your-api.example.com/data', headers=headers)
          
          return f"Access token retrieved: {access_token[:20]}..."
      except Exception as e:
          return f"Error getting access token: {str(e)}", 500
  ```

  <Info>
    Para usar esta función, debe:

    1. Configurar `AUTH0_AUDIENCE` en su archivo `.env`
    2. Incluir `offline_access` en sus alcances (para tokens de actualización)
    3. Actualizar `authorization_params` en `auth.py`:
       ```python theme={null}
       authorization_params={
           'scope': 'openid profile email offline_access',
           'audience': os.getenv('AUTH0_AUDIENCE')
       }
       ```
  </Info>
</Accordion>

<Accordion title="Configuración de almacenamiento personalizada">
  De forma predeterminada, el SDK usa almacenamiento basado en cookies. En entornos de producción con necesidades específicas (escalado horizontal, uso compartido de sesiones entre servicios), puede configurar backends de almacenamiento personalizados, como Redis o PostgreSQL.

  **Cuándo usar almacenamiento personalizado:**

  * Necesita compartir sesiones entre varios servidores
  * Tiene datos de sesión de gran tamaño que superan los límites de tamaño de las cookies
  * Necesita administración centralizada de sesiones para el cierre de sesión por backchannel

  **Ejemplo con Redis:**

  ```python auth.py theme={null}
  from auth0_server_python.stores.redis_state_store import RedisStateStore
  import redis.asyncio as redis

  # Inicializar almacenamiento de estado personalizado
  redis_client = redis.from_url(os.getenv('REDIS_URL', 'redis://localhost:6379'))
  state_store = RedisStateStore(
      secret=os.getenv('AUTH0_SECRET'),
      redis_client=redis_client
  )

  # Pasar a ServerClient
  auth0 = ServerClient(
      domain=os.getenv('AUTH0_DOMAIN'),
      client_id=os.getenv('AUTH0_CLIENT_ID'),
      client_secret=os.getenv('AUTH0_CLIENT_SECRET'),
      secret=os.getenv('AUTH0_SECRET'),
      redirect_uri=os.getenv('AUTH0_REDIRECT_URI'),
      state_store=state_store,  # Almacenamiento personalizado
      authorization_params={'scope': 'openid profile email'}
  )
  ```

  <Info>
    Para la mayoría de las aplicaciones, el almacenamiento predeterminado basado en cookies es suficiente. El almacenamiento personalizado requiere implementar la interfaz `StateStore`. Consulte los [ejemplos del SDK](https://github.com/auth0/auth0-server-python/blob/main/examples/ConfigureStore.md) para ver implementaciones detalladas.
  </Info>
</Accordion>

***

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

<AccordionGroup>
  <Accordion title="MissingRequiredArgumentError">
    **Problema:** Aparece "MissingRequiredArgumentError: secret" al iniciar la aplicación

    **Causa:** Falta la variable de entorno `AUTH0_SECRET` o no se está cargando correctamente.

    **Solución:**

    1. Verifique que el archivo `.env` exista en la raíz del proyecto
    2. Asegúrese de que `python-dotenv` esté instalado: `pip install python-dotenv`
    3. Genere un nuevo secreto si es necesario: `openssl rand -hex 64`
    4. Añádalo a `.env`: `AUTH0_SECRET=your_generated_secret`
    5. Reinicie la aplicación Flask
  </Accordion>

  <Accordion title="Error de URL de callback inválida">
    **Problema:** Aparece el error "Callback URL mismatch" o "invalid\_request" durante el inicio de sesión

    **Causa:** El URI de redirección en tu código no coincide con el que está registrado en Auth0 Dashboard.

    **Solución:**

    1. Revisa tu archivo `.env`: `AUTH0_REDIRECT_URI=http://localhost:5000/callback`
    2. Ve a [Auth0 Dashboard](https://manage.auth0.com/dashboard/) → Applications → Your App → Settings
    3. Agrega `http://localhost:5000/callback` a **Allowed Callback URLs**
    4. Haz clic en **Save Changes**
    5. Reinicia tu aplicación Flask
  </Accordion>

  <Accordion title="Errores en el bucle de eventos de AsyncIO">
    **Problema:** Aparece "RuntimeError: This event loop is already running" u otros errores asíncronos similares

    **Causa:** La compatibilidad asíncrona de Flask 2.0+ puede presentar problemas con determinadas configuraciones.

    **Solución:**

    Instale Flask con compatibilidad asíncrona:

    ```bash theme={null}
    pip install "flask[async]"
    ```

    Luego, reinicia la aplicación Flask.
  </Accordion>

  <Accordion title="Errores de «módulo no encontrado»">
    **Problema:** Aparece "ModuleNotFoundError: No module named 'auth0\_server\_python'" o un mensaje similar

    **Causa:** El SDK no está instalado o el entorno virtual no está activado.

    **Solución:**

    1. Asegúrese de que su entorno virtual esté activado:
       ```bash theme={null}
       source venv/bin/activate  # macOS/Linux
       # o
       venv\Scripts\activate  # Windows
       ```
    2. Instale el SDK:
       ```bash theme={null}
       pip install auth0-server-python "flask[async]" python-dotenv
       ```
    3. Verifique la instalación:

    ```bash theme={null}
    pip list | grep auth0
    ```
  </Accordion>

  <Accordion title="Error de ClaimDecodingFailed">
    **Problema:** Ves el error "ClaimDecodingFailed" o "Failed to decode claims" durante la autenticación

    **Causa:** El token de ID o el token de acceso recibido de Auth0 no se pudo decodificar correctamente, normalmente por una de estas razones:

    * Formato de JWT no válido
    * Datos de sesión dañados
    * Algoritmos de firma incompatibles
    * Desajuste de reloj entre tu servidor y Auth0

    **Solución:**

    1. Asegúrate de que `AUTH0_CLIENT_SECRET` sea correcto en el archivo `.env`
    2. Comprueba que la hora del sistema esté sincronizada (NTP):
       ```bash theme={null}
       # macOS
       sudo sntp -sS time.apple.com

       # Linux
       sudo ntpdate -s time.nist.gov
       ```
    3. Borra las cookies del navegador y reinicia la autenticación
    4. Verifica que `AUTH0_DOMAIN` no incluya el prefijo `https://`
    5. Comprueba que Auth0 Dashboard → Applications → Your App → Settings → Advanced → OAuth → JsonWebToken Signature Algorithm coincida con la configuración de tu SDK
  </Accordion>

  <Accordion title="Token caducado o inválido">
    **Problema:** Aparece el error "Token has expired" o "invalid\_token"

    **Causa:** El token de acceso o el token de ID ha superado su tiempo de validez, o la sesión ha expirado.

    **Solución:**

    1. El SDK gestiona automáticamente la renovación del token si incluye el scope `offline_access`:
       ```python theme={null}
       authorization_params={
           'scope': 'openid profile email offline_access',
       }
       ```
    2. En el caso de las API, asegúrese de solicitar tokens nuevos:
       ```python theme={null}
       access_token = await auth0.get_access_token(
           audience='https://your-api.example.com',
           force_refresh=True  # Forzar la renovación si es necesario
       )
       ```
    3. Ajuste el tiempo de validez de los tokens en Auth0 Dashboard → Applications → Your App → Settings → Advanced → OAuth
    4. Implemente un manejo de errores adecuado para redirigir a los usuarios al inicio de sesión cuando los tokens expiren
  </Accordion>

  <Accordion title="CORS y errores entre orígenes">
    **Problema:** Aparecen errores de CORS o "Blocked by CORS policy" en la consola del navegador

    **Causa:** El origen de tu aplicación no está configurado correctamente en Auth0.

    **Solución:**

    1. Añade tu origen en Auth0 Dashboard → Applications → Your App → Settings:
       * **Allowed Web Origins**: `http://localhost:5000`
       * **Allowed Callback URLs**: `http://localhost:5000/callback`
       * **Allowed Logout URLs**: `http://localhost:5000`
    2. Para producción, añade las URL de producción:
       ```
       https://yourdomain.com
       https://yourdomain.com/callback
       ```
    3. Asegúrate de que tu aplicación Flask tenga una configuración de CORS adecuada si llamas a las API de Auth0 desde JavaScript del frontend:
       ```python theme={null}
       from flask_cors import CORS
       CORS(app, origins=['http://localhost:5000'])
       ```
  </Accordion>

  <Accordion title="Se superó el límite de tasa">
    **Problema:** Ves errores de "Demasiadas solicitudes" o "Se superó el límite de tasa"

    **Causa:** Tu aplicación ha superado los límites de tasa de Auth0 para las solicitudes de autenticación.

    **Solución:**

    1. Revisa Auth0 Dashboard → Monitoring → Logs para consultar los detalles del límite de tasa
    2. Implementa retroceso exponencial para los reintentos:
       ```python theme={null}
       import time
       from auth0_server_python.error import ApiError

       async def login_with_retry():
           max_retries = 3
           for attempt in range(max_retries):
               try:
                   return await auth0.start_interactive_login({}, g.store_options)
               except ApiError as e:
                   if e.status_code == 429 and attempt < max_retries - 1:
                       wait_time = 2 ** attempt
                       time.sleep(wait_time)
                   else:
                       raise
       ```
    3. Revisa los límites de tu plan de suscripción de Auth0
    4. Optimiza el flujo de autenticación para reducir las solicitudes de tokens innecesarias
    5. Almacena los tokens en caché adecuadamente en lugar de solicitar nuevos con frecuencia
  </Accordion>
</AccordionGroup>
