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

> Migra tu conexión de federación SAML existente de un dominio personalizado heredado de Auth0 a uno nuevo, para que tus inquilinos puedan aprovechar las capacidades de Multiple Custom Domain (MCD).

# Migración de SAML para dominios personalizados

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>;
};

export const AuthCodeBlock = ({filename, icon, language, highlight, children}) => {
  const [displayText, setDisplayText] = useState(children);
  const [copyText, setCopyText] = useState(children);
  const wrapperRef = React.useRef(null);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      if (!window.autorun || !window.rootStore) {
        return;
      }
      unsubscribe = window.autorun(() => {
        let processedChildrenForDisplay = children;
        let processedChildrenForCopy = children;
        for (const [key, value] of window.rootStore.variableStore.values.entries()) {
          const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
          let displayValue = value;
          if (key === "{yourClientSecret}" && value !== "{yourClientSecret}") {
            displayValue = value.substring(0, 3) + "*****ENMASCARADO*****";
          }
          processedChildrenForDisplay = processedChildrenForDisplay.replaceAll(new RegExp(escapedKey, "g"), displayValue);
          processedChildrenForCopy = processedChildrenForCopy.replaceAll(new RegExp(escapedKey, "g"), value);
        }
        setDisplayText(processedChildrenForDisplay);
        setCopyText(processedChildrenForCopy);
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  useEffect(() => {
    if (!wrapperRef.current) return;
    const originalWriteText = navigator.clipboard.writeText.bind(navigator.clipboard);
    let isOverriding = false;
    const handleClick = e => {
      const button = e.target.closest('[data-testid="copy-code-button"]');
      if (!button || !wrapperRef.current.contains(button)) return;
      isOverriding = true;
      navigator.clipboard.writeText = text => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
          return originalWriteText(copyText);
        }
        return originalWriteText(text);
      };
      setTimeout(() => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
        }
      }, 100);
    };
    const wrapper = wrapperRef.current;
    wrapper.addEventListener('click', handleClick, true);
    return () => {
      wrapper.removeEventListener('click', handleClick, true);
      if (navigator.clipboard.writeText !== originalWriteText) {
        navigator.clipboard.writeText = originalWriteText;
      }
    };
  }, [copyText]);
  return <div ref={wrapperRef}>
      <CodeBlock filename={filename} icon={icon} language={language} lines highlight={highlight}>
        {displayText}
      </CodeBlock>
    </div>;
};

Migra tu Conexión de federación SAML existente de un dominio personalizado heredado de Auth0 a uno nuevo, para que tus inquilinos puedan aprovechar las capacidades de Multiple Custom Domain (MCD).

Los Proveedores de identidad (IdP) externos suelen estar configurados de forma fija con tu dominio anterior, por lo que debes implementar un proxy inverso inteligente que intercepte la respuesta SAML enviada a ese dominio y la redirija de forma segura a un nuevo dominio personalizado.

Esto garantiza una migración sin interrupciones para los usuarios federados y te permite usar de inmediato tu nuevo dominio sin tener que esperar actualizaciones de configuración obligatorias por parte de tu IdP.

<div id="prerequisites">
  ## Requisitos previos
</div>

Este proceso requiere configurar los componentes de Auth0 mediante Terraform y desplegar un Cloudflare Worker para la lógica de proxy.

Antes de comenzar la migración, revise los siguientes requisitos:

* Un inquilino con plan Enterprise y MCD habilitado.
* Dos dominios personalizados verificados configurados en su inquilino de Auth0:
  1. **Dominio heredado anterior** (para el proxy)
  2. **Nuevo dominio de destino** (para la aplicación)
* Terraform CLI y `Node.js/npm` instalados.
* Una cuenta de Cloudflare con acceso al dominio que hospeda sus dominios personalizados.

<div id="how-it-works">
  ## Cómo funciona
</div>

Esta estrategia de migración utiliza un proxy inverso inteligente para hacer de puente entre tu dominio personalizado heredado y tu nuevo dominio. Este proxy se implementa en el dominio anterior para interceptar la respuesta de autenticación SAML enviada por tu Proveedor de identidad (IdP) externo.

Esto es necesario porque la configuración del IdP está codificada de forma fija en el endpoint de tu dominio anterior. El proxy modifica los campos de control de la carga útil de SAML (como `Destination` y `Recipient`) para que reflejen con precisión el nuevo dominio personalizado.

Por último, el proxy reenvía esta carga útil corregida al endpoint de inicio de sesión del nuevo dominio. Esto permite cambiar a tu nuevo dominio sin tiempo de inactividad y sin requerir cambios de configuración manuales por parte de tus socios de IdP.

<div id="setup-and-configuration">
  ## Preparación y configuración
</div>

Para preparar y configurar la migración:

1. Clona el repositorio de migración:

```bash theme={null}
git clone https://github.com/abbaspour/auth0-mcd-federation-migration.git
cd auth0-mcd-federation-migration
```

2. Instale las dependencias:

```bash theme={null}
npm install
```

3. Cree un archivo `terraform.auto.tfvars` en su directorio `tf` con las credenciales necesarias y la información del dominio:

```bash theme={null}
# Variables del Proveedor de servicios (SP) de Auth0
auth0_domain = "your-sp-tenant.auth0.com"
auth0_existing_custom_domain = "oldfed.example.com"
auth0_new_custom_domain = "id.example2.com"
auth0_tf_client_id = "your-sp-client-id"
auth0_tf_client_secret = "your-sp-client-secret"

# Variables del Proveedor de identidad (IdP) de Auth0
auth0_idp_domain = "your-idp-tenant.auth0.com"
auth0_idp_tf_client_id = "your-idp-client-id"
auth0_idp_tf_client_secret = "your-idp-client-secret"

# Variables de Cloudflare
cloudflare_api_key = "your-cloudflare-api-key"
cloudflare_email = "your-cloudflare-email"
cloudflare_zone_id = "your-cloudflare-zone-id"
```

4. Inicialice Terraform y aplíquelo:

```bash theme={null}
cd tf
terraform init
terraform apply
```

Esto crea la aplicación y la conexión de SAML necesarias, configura el DNS mediante Cloudflare y prepara las variables de entorno para el worker.

<div id="deploy-the-cloudflare-worker">
  ### Despliega el worker de Cloudflare
</div>

Este proxy se encarga de la interceptación de la respuesta SAML y de la lógica de redirección. Para desplegarlo:

1. Despliega el proxy de Cloudflare:

```bash theme={null}
cd ..
npx wrangler deploy
```

2. El worker recibe automáticamente las variables de entorno necesarias (como `AUTH0_EDGE_LOCATION` y `NEW_SP_DOMAIN`) desde la salida de Terraform.

<div id="temporarily-update-saml-connection-parameters">
  ### Actualizar temporalmente los parámetros de la conexión SAML
</div>

Tu dominio anterior recibe la respuesta SAML antes de reenviarla al dominio nuevo. Por lo tanto, los parámetros de validación esperados de la conexión SAML deben apuntar temporalmente a la URL de devolución de llamada del dominio anterior para evitar errores por discrepancias.

1. Obtén un token de acceso de Management API para el inquilino de tu proveedor de servicios, con los alcances `read:connections` y `update:connections`:

   ```bash theme={null}
   cd bin/
   export access_token='<sp-tenant-management-api-token>'
   ```

2. Actualiza la URL de destino:

   ```bash theme={null}
   ./sp-set-destination-url.sh -i <saml-connection-id> -d https://oldfed.example.com/login/callback
   ```

3. Actualiza la URL del destinatario:

   ```bash theme={null}
   ./sp-set-recipient-url.sh -i <saml-connection-id> -r https://oldfed.example.com/login/callback
   ```
