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

> Aprende cómo funcionan las claves de acceso y WebAuthn con varios dominios personalizados en Auth0.

# Claves de acceso con varios dominios personalizados

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

Las [claves de acceso](/es/docs/secure/multi-factor-authentication/fido-authentication-with-webauthn) proporcionan una experiencia de autenticación sin contraseña y resistente al phishing mediante WebAuthn. Al usar [varios dominios personalizados](/es/docs/customize/custom-domains/multiple-custom-domains), las claves de acceso deben inscribirse para cada dominio debido al modelo de seguridad de WebAuthn.

<div id="how-passkeys-work-with-custom-domains">
  ## Cómo funcionan las claves de acceso con dominios personalizados
</div>

<div id="webauthn-relying-party-id-rp-id">
  ### ID de parte de confianza (RP ID) de WebAuthn
</div>

WebAuthn usa un identificador de parte de confianza (RP ID) para definir el alcance de las credenciales de las claves de acceso. El RP ID determina lo siguiente:

* **Dónde se pueden usar las claves de acceso**: Las claves de acceso están vinculadas al dominio en el que se crearon
* **Límites de seguridad**: Evita que las claves de acceso se usen en dominios no autorizados
* **Experiencia del usuario**: Los usuarios deben inscribir las claves de acceso por separado para cada dominio personalizado

<div id="per-domain-enrollment">
  ### Inscripción por dominio
</div>

Con varios dominios personalizados, cada dominio tiene su propio RP ID, lo que significa lo siguiente:

* Una clave de acceso inscrita en `login.brand1.com` **no** puede usarse en `login.brand2.com`
* Los usuarios que se autentican a través de distintos dominios personalizados deben inscribir una clave de acceso para cada dominio
* Las claves de acceso de cada dominio se administran de forma independiente

<div id="understanding-the-passkey-user-experience">
  ## Comprender la experiencia del usuario con las claves de acceso
</div>

<div id="single-brand-single-domain">
  ### Marca única, dominio único
</div>

**Configuración**: Un dominio personalizado para una sola marca

**Experiencia del usuario**:

1. El usuario visita `login.example.com`
2. El usuario inscribe una clave de acceso
3. El usuario puede usar la clave de acceso en todos los inicios de sesión futuros mediante `login.example.com`

**Complejidad**: Baja - experiencia con clave de acceso sencilla

<div id="multi-brand-separate-domains">
  ### Varias marcas, dominios separados
</div>

**Configuración**: Varias marcas, cada una con su propio dominio personalizado

**Experiencia del usuario**:

1. El usuario visita `login.brand1.com` e inscribe una clave de acceso
2. Más tarde, el mismo usuario visita `login.brand2.com` (una marca diferente)
3. La clave de acceso inscrita previamente no está disponible
4. El usuario debe inscribir una nueva clave de acceso para `login.brand2.com`

**Complejidad**: Media: los usuarios necesitan claves de acceso independientes para cada marca

**Práctica recomendada**: Comunique a los usuarios que cada marca requiere la inscripción por separado de una clave de acceso

<div id="multi-tenant-with-common-domain">
  ### Multiinquilino con dominio común
</div>

**Configuración**: Varios clientes con un dominio personalizado común para servicios compartidos.

**Experiencia del usuario**:

1. La mayoría de los usuarios se autentican a través del dominio común
2. Los usuarios solo tienen que inscribir las claves de acceso una vez para el dominio común
3. Las claves de acceso funcionan de forma consistente en la mayoría de los escenarios de autenticación
4. Los casos especiales (dominios específicos del cliente) requieren una inscripción por separado

**Complejidad**: Baja a media: la mayoría de los usuarios tienen una experiencia consistente

<div id="configuration">
  ## Configuration
</div>

<div id="enable-passkeys-for-your-tenant">
  ### Habilite las claves de acceso para su inquilino
</div>

Antes de usar claves de acceso con dominios personalizados, asegúrese de que las claves de acceso estén habilitadas:

1. Vaya a **Auth0 Dashboard** > **Security** > **Multi-factor Auth**
2. Habilite **WebAuthn con claves de seguridad FIDO**
3. Configure los ajustes de las claves de acceso

<div id="configure-custom-domains-for-passkeys">
  ### Configurar dominios personalizados para claves de acceso
</div>

Cada dominio personalizado tiene automáticamente su propio RP ID:

* **Formato del RP ID**: El propio dominio personalizado (por ejemplo, `login.example.com`)
* **No se requiere ninguna configuración adicional**: Auth0 configura automáticamente el RP ID para cada dominio personalizado verificado

<div id="verify-rp-id-configuration">
  ### Verificar la configuración del RP ID
</div>

Para verificar el RP ID de un dominio personalizado:

1. Vaya a **Auth0 Dashboard** > **Marca** > **Dominios personalizados**
2. Seleccione su dominio personalizado
3. En los detalles del dominio, verá el RP ID

<div id="implementation-patterns">
  ## Patrones de implementación
</div>

<div id="prompt-for-passkey-enrollment-per-domain">
  ### Solicitar inscripción de claves de acceso por dominio
</div>

Indique a los usuarios que registren una clave de acceso para cada dominio personalizado que utilicen:

```javascript theme={null}
import { createAuth0Client } from '@auth0/auth0-spa-js';

async function setupPasskeyEnrollment() {
  const auth0 = await createAuth0Client({
    domain: 'login.example.com',
    clientId: 'YOUR_CLIENT_ID'
  });

  // Verificar si el usuario está autenticado
  const isAuthenticated = await auth0.isAuthenticated();

  if (isAuthenticated) {
    // Verificar si la passkey está inscrita para este dominio
    const user = await auth0.getUser();

    if (!user.passkey_enrolled) {
      // Solicitar al usuario que inscriba una passkey
      showPasskeyEnrollmentPrompt();
    }
  }
}

function showPasskeyEnrollmentPrompt() {
  // Mostrar interfaz para fomentar la inscripción de passkey
  const banner = document.createElement('div');
  banner.innerHTML = `
    <div class="passkey-prompt">
      <p>Set up passkey for faster, more secure login on this site</p>
      <button onclick="enrollPasskey()">Set Up Passkey</button>
    </div>
  `;
  document.body.prepend(banner);
}
```

<div id="track-passkey-enrollment-by-domain">
  ### Seguimiento de la inscripción de claves de acceso por dominio
</div>

Almacene los dominios en los que un usuario ha inscrito claves de acceso:

```javascript theme={null}
// En tu Auth0 Action (Post-Login)
exports.onExecutePostLogin = async (event, api) => {
  const domain = event.custom_domain?.domain;
  const authMethods = event.authentication?.methods || [];

  // Verificar si el usuario se autenticó con passkey
  const usedPasskey = authMethods.some(method =>
    method.name === 'webauthn' || method.name === 'passkey'
  );

  if (usedPasskey) {
    // Registrar en qué dominios el usuario tiene passkeys inscritas
    const enrolledDomains = event.user.app_metadata?.passkey_domains || [];

    if (domain && !enrolledDomains.includes(domain)) {
      enrolledDomains.push(domain);
      api.user.setAppMetadata('passkey_domains', enrolledDomains);
    }

    // Agregar claim al token
    api.idToken.setCustomClaim('passkey_enrolled', true);
    api.idToken.setCustomClaim('passkey_domain', domain);
  } else {
    // El usuario no utilizó passkey
    api.idToken.setCustomClaim('passkey_enrolled', false);
  }
};
```

Luego, en tu aplicación:

```javascript theme={null}
async function checkPasskeyEnrollment() {
  const auth0 = await createAuth0Client({
    domain: window.CUSTOM_DOMAIN,
    clientId: 'YOUR_CLIENT_ID'
  });

  const isAuthenticated = await auth0.isAuthenticated();

  if (isAuthenticated) {
    const user = await auth0.getUser();
    const claims = await auth0.getIdTokenClaims();

    // Verificar si la passkey está inscrita para el dominio actual
    const passkeyEnrolledHere = claims.passkey_enrolled &&
                                 claims.passkey_domain === window.CUSTOM_DOMAIN;

    if (!passkeyEnrolledHere) {
      // Solicitar al usuario que inscriba la passkey para este dominio
      promptPasskeyEnrollment();
    }
  }
}
```

<div id="domain-specific-enrollment-pages">
  ### Páginas de inscripción específicas para cada dominio
</div>

Cree páginas de inscripción específicas para cada dominio personalizado:

```javascript theme={null}
// Página de inscripción para la marca 1
// URL: https://login.brand1.com/enroll-passkey

import { createAuth0Client } from '@auth0/auth0-spa-js';

async function enrollPasskeyForBrand1() {
  const auth0 = await createAuth0Client({
    domain: 'login.brand1.com',
    clientId: 'YOUR_CLIENT_ID'
  });

  try {
    // Disparar la inscripción de passkey
    await auth0.loginWithPopup({
      authorizationParams: {
        acr_values: 'http://schemas.openid.net/pape/policies/2007/06/multi-factor',
        prompt: 'login'
      }
    });

    alert('Passkey enrolled successfully for Brand 1!');
  } catch (error) {
    console.error('Passkey enrollment failed:', error);
  }
}
```

<div id="contextual-enrollment-prompts">
  ### Pantallas contextuales de inscripción
</div>

Muestra pantallas de inscripción de claves de acceso según el comportamiento del usuario. Consideraciones clave:

* Registra cuándo los usuarios descartan las pantallas de inscripción (guárdalo en `localStorage`)
* Consulta `logins_count` en los metadatos del usuario para mostrar las pantallas después de varias visitas
* Verifica que la clave de acceso no esté ya inscrita para el dominio actual

```javascript theme={null}
async function shouldShowEnrollmentPrompt(auth0, customDomain) {
  const storageKey = `passkey_prompt_dismissed_${customDomain}`;

  // No mostrar si el usuario lo descartó
  if (localStorage.getItem(storageKey)) return false;

  const claims = await auth0.getIdTokenClaims();
  const passkeyEnrolled = claims.passkey_enrolled &&
                          claims.passkey_domain === customDomain;

  if (passkeyEnrolled) return false;

  // Mostrar la pantalla después del 3er login
  const user = await auth0.getUser();
  return (user.logins_count || 0) >= 3;
}
```

<div id="user-communication">
  ## Comunicación con los usuarios
</div>

<div id="inform-users-about-per-domain-enrollment">
  ### Informa a los usuarios sobre la inscripción por dominio
</div>

Comunica claramente a los usuarios que las claves de acceso son específicas de cada dominio:

**Ejemplo de mensaje**:

> "Por seguridad, las claves de acceso son específicas de cada portal de inicio de sesión. Tendrás que configurar una clave de acceso por separado para la página de inicio de sesión de cada marca que uses."

**Ejemplo de pantalla de inscripción**:

```html theme={null}
<div class="passkey-info-banner">
  <h3>Set up faster login with passkey</h3>
  <p>
    This passkey will work for login.example.com.
    If you use other login portals, you'll need to set up passkeys separately for each one.
  </p>
  <button onclick="enrollPasskey()">Set Up Passkey</button>
  <button onclick="dismissPrompt()">Not Now</button>
</div>
```

<div id="help-documentation">
  ### Documentación de ayuda
</div>

Incluya documentación de ayuda clara:

**Ejemplo de entrada de preguntas frecuentes**:

**P: ¿Por qué debo configurar una clave de acceso otra vez?**

R: Por seguridad, las claves de acceso están vinculadas a dominios específicos. Si inicia sesión a través de un portal distinto (por ejemplo, Marca A frente a Marca B), deberá configurar una clave de acceso para cada uno. Esto ayuda a mantener seguras sus cuentas, ya que garantiza que las claves de acceso solo funcionen donde corresponde.

**P: ¿Necesito un dispositivo distinto para cada clave de acceso?**

R: ¡No! Puede usar el mismo dispositivo (teléfono, computadora o llave de hardware) para claves de acceso en distintos dominios. Cada clave de acceso es simplemente una credencial independiente almacenada en su dispositivo.

<div id="limitations-and-considerations">
  ## Limitaciones y consideraciones
</div>

<div id="current-limitations">
  ### Limitaciones actuales
</div>

<table class="table">
  <thead>
    <tr>
      <th><strong>Limitación</strong></th>
      <th><strong>Impacto</strong></th>
      <th><strong>Solución alternativa</strong></th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>No se pueden compartir claves de acceso entre dominios</td>
      <td>Los usuarios deben inscribirse por separado para usar claves de acceso en cada dominio personalizado</td>
      <td>Use un dominio común para la mayoría de las autenticaciones o guíe a los usuarios para que se inscriban en cada dominio</td>
    </tr>

    <tr>
      <td>No se pueden transferir claves de acceso entre dominios</td>
      <td>Migrar a un nuevo dominio personalizado requiere volver a inscribirse</td>
      <td>Planifique la migración cuidadosamente, comuníquese con los usuarios y proporcione un flujo para volver a inscribirse</td>
    </tr>

    <tr>
      <td>Los orígenes relacionados aún no son compatibles</td>
      <td>No se pueden compartir claves de acceso entre subdominios o dominios relacionados</td>
      <td>Está previsto para una futura versión; por ahora, use la inscripción por dominio</td>
    </tr>
  </tbody>
</table>

<div id="related-origins-future-feature">
  ### Orígenes relacionados (función futura)
</div>

Auth0 tiene previsto ofrecer compatibilidad con orígenes relacionados de WebAuthn, lo que permitirá compartir claves de acceso entre dominios especificados. Esta función:

* Le permitirá configurar dominios como "relacionados" para claves de acceso
* Permitirá a los usuarios usar en `login.brand2.com` una clave de acceso inscrita en `login.brand1.com` si ambos están configurados como relacionados
* Ofrecerá mayor flexibilidad para implementaciones con varias marcas

**Estado**: Previsto para una versión posterior a GA

<div id="migration-scenarios">
  ## Escenarios de migración
</div>

<div id="migrating-from-single-custom-domain-to-multiple">
  ### Migración de un único dominio personalizado a varios
</div>

**Antes**: Un único dominio personalizado con claves de acceso ya inscritas

**Después**: Varios dominios personalizados para diferentes marcas

**Desafío**: Las claves de acceso existentes solo funcionan en el dominio original

**Enfoque de migración**:

1. **Mantenga activo el dominio original**: Mantenga el dominio personalizado original como dominio común
2. **Despliegue gradual**: Introduzca nuevos dominios personalizados de forma gradual
3. **Notificación al usuario**: Informe a los usuarios de que tendrán que inscribir claves de acceso en los nuevos dominios
4. **Proporcione un flujo de reinscripción**: Facilite que los usuarios inscriban claves de acceso en los nuevos dominios
5. **Supervise la adopción**: Haga un seguimiento de las tasas de inscripción de claves de acceso por dominio

**Plantilla de comunicación**:

> "¡Estamos incorporando páginas de inicio de sesión específicas de cada marca! Tu clave de acceso actual seguirá funcionando en \[original domain]. Cuando visites nuestras nuevas páginas de inicio de sesión, se te pedirá que configures una clave de acceso también allí para iniciar sesión más rápido."

<div id="migrating-between-custom-domains">
  ### Migración entre dominios personalizados
</div>

**Escenario**: Cambiar de `old-domain.com` a `new-domain.com`

**Desafío**: Las claves de acceso no se pueden transferir

**Pasos de migración**:

1. **Funcionamiento en paralelo**: Mantén ambos dominios activos simultáneamente durante la transición
2. **Detectar claves de acceso ya inscritas**: Identifica qué usuarios tienen claves de acceso en el dominio anterior
3. **Solicitar una nueva inscripción**: Cuando los usuarios inicien sesión a través del dominio nuevo, solicita la inscripción de claves de acceso
4. **Período de gracia**: Mantén activo el dominio anterior durante un período de transición
5. **Retirar el dominio anterior**: Tras la adopción, desactiva el dominio anterior

```javascript theme={null}
// En tu Auth0 Action
exports.onExecutePostLogin = async (event, api) => {
  const domain = event.custom_domain?.domain;
  const oldDomain = 'old-domain.com';
  const newDomain = 'new-domain.com';

  // Verificar si el usuario tenía una passkey en el dominio anterior
  const hadOldPasskey = event.user.app_metadata?.passkey_domains?.includes(oldDomain);

  // El usuario está en el nuevo dominio pero aún no tiene una passkey inscrita
  if (domain === newDomain && hadOldPasskey) {
    const newDomainPasskeys = event.user.app_metadata?.passkey_domains?.includes(newDomain);

    if (!newDomainPasskeys) {
      // Establecer un indicador para solicitar la reinscripción
      api.idToken.setCustomClaim('should_enroll_passkey', true);
      api.idToken.setCustomClaim('migrated_from', oldDomain);
    }
  }
};
```

<div id="testing">
  ## Pruebas
</div>

<div id="test-passkey-enrollment-per-domain">
  ### Probar la inscripción de claves de acceso para cada dominio
</div>

1. **Configurar dominios personalizados de prueba**: Configure varios dominios personalizados en un inquilino de desarrollo
2. **Probar el flujo de inscripción**: Inscriba una clave de acceso a través de un dominio personalizado
3. **Verificar el aislamiento**: Confirme que la clave de acceso no funcione en otros dominios personalizados
4. **Probar la reinscripción**: Inscriba claves de acceso en dominios adicionales
5. **Pruebas en distintos navegadores**: Pruebe en distintos navegadores y dispositivos

<div id="automated-testing">
  ### Pruebas automatizadas
</div>

```javascript theme={null}
describe('Passkey Enrollment with Multiple Custom Domains', () => {
  it('should enroll passkey on domain 1', async () => {
    await navigateTo('https://login.brand1.com');
    await login();
    await enrollPasskey();
    expect(await isPasskeyEnrolled()).toBe(true);
  });

  it('should not have passkey on domain 2', async () => {
    await navigateTo('https://login.brand2.com');
    await login();
    expect(await isPasskeyEnrolled()).toBe(false);
  });

  it('should enroll separate passkey on domain 2', async () => {
    await navigateTo('https://login.brand2.com');
    await login();
    await enrollPasskey();
    expect(await isPasskeyEnrolled()).toBe(true);
  });
});
```

<div id="best-practices">
  ## Prácticas recomendadas
</div>

1. **Use un dominio común**: Use un dominio personalizado común para minimizar la cantidad de dominios que requieren inscripción de claves de acceso
2. **Comunicación clara**: Informe a los usuarios sobre los requisitos de inscripción por dominio
3. **Muestre estratégicamente las pantallas**: Muestre las pantallas de inscripción después de que los usuarios demuestren interacción (por ejemplo, 3 o más inicios de sesión)
4. **Realice un seguimiento de la inscripción**: Supervise qué usuarios han inscrito claves de acceso en cada dominio
5. **Proporcione ayuda**: Ofrezca documentación clara y soporte para la gestión de claves de acceso
6. **Pruebe exhaustivamente**: Pruebe los flujos de claves de acceso en todos los dominios personalizados antes de la implementación en producción
7. **Planifique las migraciones**: Al cambiar los dominios personalizados, planifique la reinscripción de los usuarios
8. **Supervise la adopción**: Realice un seguimiento de las tasas de inscripción y uso de claves de acceso por dominio

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

<div id="passkey-not-working-on-custom-domain">
  ### La clave de acceso no funciona en el dominio personalizado
</div>

**Síntomas**: El usuario inscribió una clave de acceso, pero no puede usarla

**Posibles causas**:

* El usuario está en un dominio personalizado distinto de aquel en el que se inscribió
* Problemas de compatibilidad con el navegador
* La clave de acceso se eliminó del dispositivo

**Resolución**:

1. Confirme que el usuario esté en el dominio personalizado correcto
2. Compruebe la compatibilidad del navegador con WebAuthn
3. Indique al usuario que vuelva a inscribir la clave de acceso si es necesario

<div id="user-confused-about-multiple-enrollments">
  ### El usuario se confunde con varias inscripciones
</div>

**Síntomas**: El usuario indica que "la clave de acceso no funciona" al cambiar de dominio

**Causa**: El usuario no entiende que la inscripción es por dominio

**Resolución**:

1. Proporcione mensajes claros sobre las claves de acceso por dominio
2. Muestre en qué dominios el usuario tiene claves de acceso inscritas
3. Solicite la inscripción cuando el usuario visite un dominio nuevo

<div id="learn-more">
  ## Más información
</div>

* [Múltiples dominios personalizados](/es/docs/customize/custom-domains/multiple-custom-domains)
* [Especificación de WebAuthn](https://www.w3.org/TR/webauthn/)
* [Passkeys.dev](https://passkeys.dev/)
