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

> Describe cómo crear tus propios flujos de MFA con SMS o voz como factores de autenticación.

# Inscribir y desafiar autenticadores por correo electrónico

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

Auth0 proporciona un flujo integrado de inscripción y autenticación con <Tooltip tip="Autenticación multifactor (MFA): proceso de autenticación del usuario que utiliza un factor además de username y contraseña, como un code por SMS." cta="Ver glosario" href="/es/docs/glossary?term=MFA">MFA</Tooltip> mediante [Universal Login](/es/docs/authenticate/login/auth0-universal-login). Sin embargo, si desea crear su propia interfaz de usuario, puede usar la [MFA API](/es/docs/secure/multi-factor-authentication/multi-factor-authentication-developer-resources/mfa-api) para hacerlo.

Cuando el correo electrónico está habilitado como factor, todos los usuarios con correo electrónico verificado podrán usarlo para completar la MFA.

<Card title="La disponibilidad varía según el plan de Auth0">
  Tanto su implementación específica de inicio de sesión como su plan de Auth0 o acuerdo personalizado afectan la disponibilidad de esta función. Para obtener más información, consulte [Pricing](https://auth0.com/pricing).
</Card>

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

Antes de poder usar las API de MFA, deberás habilitar el tipo de concesión de MFA para tu aplicación. Ve a [Auth0 Dashboard > Applications > Advanced Settings > Grant Types](https://manage.auth0.com/#/applications) y selecciona **MFA**.

* [Configurar el correo electrónico](/es/docs/secure/multi-factor-authentication/multi-factor-authentication-factors/configure-email-notifications-for-mfa) como factor en Auth0 Dashboard o mediante la [Management API](https://auth0.com/docs/api/management/v2#!/Guardian/put_factors_by_name).

<div id="enroll-with-email">
  ## Inscripción con correo electrónico
</div>

Para permitir que los usuarios inscriban direcciones de correo electrónico además del correo electrónico verificado en su identidad principal, debe completar los siguientes pasos.

<div id="get-mfa-token">
  ### Obtener un token de MFA
</div>

Según en qué momento actives la inscripción, puedes obtener un <Tooltip tip="Token de acceso: credencial de autorización, en forma de una cadena opaca o JWT, que se utiliza para acceder a una API." cta="Ver glosario" href="/es/docs/glossary?term=access+token">token de acceso</Tooltip> para usar la API de MFA de distintas maneras:

* Si realizas la inscripción durante la autenticación, consulta [Autenticarse con Resource Owner Password Grant y MFA](/es/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa).
* Si quieres permitir que el usuario inscriba un factor en cualquier momento, consulta [Administrar inscripciones de factores de MFA](/es/docs/secure/multi-factor-authentication/manage-mfa-auth0-apis/manage-authenticator-factors-mfa-api).

<div id="enroll-authenticator">
  ### Inscribir autenticador
</div>

Realice una solicitud `POST` al endpoint MFA Associate para inscribir el autenticador del usuario. El token de portador que requiere este endpoint es el token de MFA obtenido en el paso anterior.

Use los siguientes parámetros:

| Parámetro              | Valor                                                                |
| ---------------------- | -------------------------------------------------------------------- |
| `authentication_types` | `[oob]`                                                              |
| `oob_channels`         | `[email]`                                                            |
| `email`                | `email@address.com`, la dirección de correo electrónico del usuario. |

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url 'https://{yourDomain}/mfa/associate' \
    --header 'authorization: Bearer MFA_TOKEN' \
    --header 'content-type: application/json' \
    --data '{ "authenticator_types": ["oob"], "oob_channels": ["email"], "email" : "email@address.com" }'
  ```

  ```csharp C# theme={null}
  var client = new RestClient("https://{yourDomain}/mfa/associate");
  var request = new RestRequest(Method.POST);
  request.AddHeader("authorization", "Bearer MFA_TOKEN");
  request.AddHeader("content-type", "application/json");
  request.AddParameter("application/json", "{ "authenticator_types": ["oob"], "oob_channels": ["email"], "email" : "email@address.com" }", ParameterType.RequestBody);
  IRestResponse response = client.Execute(request);
  ```

  ```go Go theme={null}
  package main

  import (
  	"fmt"
  	"strings"
  	"net/http"
  	"io/ioutil"
  )

  func main() {

  	url := "https://{yourDomain}/mfa/associate"

  	payload := strings.NewReader("{ "authenticator_types": ["oob"], "oob_channels": ["email"], "email" : "email@address.com" }")

  	req, _ := http.NewRequest("POST", url, payload)

  	req.Header.Add("authorization", "Bearer MFA_TOKEN")
  	req.Header.Add("content-type", "application/json")

  	res, _ := http.DefaultClient.Do(req)

  	defer res.Body.Close()
  	body, _ := ioutil.ReadAll(res.Body)

  	fmt.Println(res)
  	fmt.Println(string(body))

  }
  ```

  ```java Java theme={null}
  HttpResponse<String> response = Unirest.post("https://{yourDomain}/mfa/associate")
    .header("authorization", "Bearer MFA_TOKEN")
    .header("content-type", "application/json")
    .body("{ "authenticator_types": ["oob"], "oob_channels": ["email"], "email" : "email@address.com" }")
    .asString();
  ```

  ```javascript Node.JS theme={null}
  var axios = require("axios").default;

  var options = {
    method: 'POST',
    url: 'https://{yourDomain}/mfa/associate',
    headers: {authorization: 'Bearer MFA_TOKEN', 'content-type': 'application/json'},
    data: {
      authenticator_types: ['oob'],
      oob_channels: ['email'],
      email: 'email@address.com'
    }
  };

  axios.request(options).then(function (response) {
    console.log(response.data);
  }).catch(function (error) {
    console.error(error);
  });
  ```

  ```php PHP theme={null}
  $curl = curl_init();

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://{yourDomain}/mfa/associate",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_POSTFIELDS => "{ "authenticator_types": ["oob"], "oob_channels": ["email"], "email" : "email@address.com" }",
    CURLOPT_HTTPHEADER => [
      "authorization: Bearer MFA_TOKEN",
      "content-type: application/json"
    ],
  ]);

  $response = curl_exec($curl);
  $err = curl_error($curl);

  curl_close($curl);

  if ($err) {
    echo "cURL Error #:" . $err;
  } else {
    echo $response;
  }
  ```

  ```python Python theme={null}
  import http.client

  conn = http.client.HTTPSConnection("")

  payload = "{ "authenticator_types": ["oob"], "oob_channels": ["email"], "email" : "email@address.com" }"

  headers = {
      'authorization': "Bearer MFA_TOKEN",
      'content-type': "application/json"
      }

  conn.request("POST", "/{yourDomain}/mfa/associate", payload, headers)

  res = conn.getresponse()
  data = res.read()

  print(data.decode("utf-8"))
  ```

  ```ruby Ruby theme={null}
  require 'uri'
  require 'net/http'
  require 'openssl'

  url = URI("https://{yourDomain}/mfa/associate")

  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE

  request = Net::HTTP::Post.new(url)
  request["authorization"] = 'Bearer MFA_TOKEN'
  request["content-type"] = 'application/json'
  request.body = "{ "authenticator_types": ["oob"], "oob_channels": ["email"], "email" : "email@address.com" }"

  response = http.request(request)
  puts response.read_body
  ```
</AuthCodeGroup>

Si la operación se completa correctamente, recibirá una respuesta como esta:

```json lines theme={null}
{
    "authenticator_type": "oob",
    "binding_method": "prompt",
    "oob_code" : "Fe26..nWE",
    "oob_channel": "email",
    "recovery_codes": [ "N3BGPZZWJ85JLCNPZBDW6QXC" ]
  }
```

Si recibes el error `User is already enrolled`, significa que el usuario ya tiene un factor de MFA inscrito. Antes de asociar otro factor al usuario, debes solicitar una verificación con el factor existente.

Si es la primera vez que el usuario asocia un autenticador, verás que la respuesta incluye `recovery_codes`. Los códigos de recuperación se usan para acceder a la cuenta del usuario en caso de que pierda acceso a la cuenta o al dispositivo que utiliza para la autenticación de segundo factor. Son códigos de un solo uso, y se generan nuevos según sea necesario.

<div id="confirm-email-enrollment">
  ### Confirmar la inscripción por correo electrónico
</div>

El usuario debería recibir un correo electrónico con el code de 6 dígitos, que puede introducir en la aplicación.

Para completar la inscripción, haz una solicitud `POST` al endpoint [**`/oath/token`**](https://auth0.com/docs/api/authentication#get-token). Incluye el `oob_code` devuelto en la respuesta anterior y el `binding_code` con el valor del mensaje de correo electrónico.

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url 'https://{yourDomain}/oauth/token' \
    --data grant_type=http://auth0.com/oauth/grant-type/mfa-oob \
    --data 'mfa_token={mfaToken}' \
    --data 'oob_code={oobCode}' \
    --data 'binding_code={userEmailOtpCode}' \
    --data 'client_id={yourClientId}' \
    --data 'client_secret={yourClientSecret}'
  ```

  ```csharp C# theme={null}
  var client = new RestClient("https://{yourDomain}/oauth/token");
  var request = new RestRequest(Method.POST);
  request.AddParameter("undefined", "grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-oob&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=%7BuserEmailOtpCode%7D&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D", ParameterType.RequestBody);
  IRestResponse response = client.Execute(request);
  ```

  ```go Go theme={null}
  package main

  import (
  	"fmt"
  	"strings"
  	"net/http"
  	"io/ioutil"
  )

  func main() {

  	url := "https://{yourDomain}/oauth/token"

  	payload := strings.NewReader("grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-oob&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=%7BuserEmailOtpCode%7D&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D")

  	req, _ := http.NewRequest("POST", url, payload)

  	res, _ := http.DefaultClient.Do(req)

  	defer res.Body.Close()
  	body, _ := ioutil.ReadAll(res.Body)

  	fmt.Println(res)
  	fmt.Println(string(body))

  }
  ```

  ```java Java theme={null}
  HttpResponse<String> response = Unirest.post("https://{yourDomain}/oauth/token")
    .body("grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-oob&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=%7BuserEmailOtpCode%7D&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D")
    .asString();
  ```

  ```javascript Node.JS theme={null}
  var axios = require("axios").default;

  var options = {
    method: 'POST',
    url: 'https://{yourDomain}/oauth/token',
    data: new URLSearchParams({
      grant_type: 'http://auth0.com/oauth/grant-type/mfa-oob',
      mfa_token: '{mfaToken}',
      oob_code: '{oobCode}',
      binding_code: '{userEmailOtpCode}',
      client_id: '{yourClientId}',
      client_secret: '{yourClientSecret}'
    })
  };

  axios.request(options).then(function (response) {
    console.log(response.data);
  }).catch(function (error) {
    console.error(error);
  });
  ```

  ```php PHP theme={null}
  $curl = curl_init();

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://{yourDomain}/oauth/token",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_POSTFIELDS => "grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-oob&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=%7BuserEmailOtpCode%7D&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D",
  ]);

  $response = curl_exec($curl);
  $err = curl_error($curl);

  curl_close($curl);

  if ($err) {
    echo "cURL Error #:" . $err;
  } else {
    echo $response;
  }
  ```

  ```python Python theme={null}
  import http.client

  conn = http.client.HTTPSConnection("")

  payload = "grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-oob&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=%7BuserEmailOtpCode%7D&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D"

  conn.request("POST", "/{yourDomain}/oauth/token", payload)

  res = conn.getresponse()
  data = res.read()

  print(data.decode("utf-8"))
  ```

  ```ruby Ruby theme={null}
  require 'uri'
  require 'net/http'
  require 'openssl'

  url = URI("https://{yourDomain}/oauth/token")

  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE

  request = Net::HTTP::Post.new(url)
  request.body = "grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-oob&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=%7BuserEmailOtpCode%7D&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D"

  response = http.request(request)
  puts response.read_body
  ```
</AuthCodeGroup>

Si la llamada se realiza correctamente, recibirás una respuesta con el siguiente formato, que incluye el token de acceso:

```json lines theme={null}
{
  "id_token": "eyJ...i",
  "access_token": "eyJ...i",
  "expires_in": 600,
  "scope": "openid profile",
  "token_type": "Bearer"
}
```

En este punto, el autenticador ya está completamente asociado y listo para usarse, y usted ya dispone de los tokens de autenticación del usuario.

Puede comprobar en cualquier momento si se ha confirmado un autenticador llamando al endpoint MFA Authenticators. Si el autenticador está confirmado, el valor devuelto para `active` es `true`.

Opcionalmente, puede personalizar los correos electrónicos que reciben los usuarios. Consulte [Personalizar las plantillas de correo electrónico](/es/docs/customize/email/email-templates) para obtener más información.

<div id="challenge-with-email">
  ## Desafío con correo electrónico
</div>

<div id="get-mfa-token">
  ### Obtener un token de MFA
</div>

Obtén un token de MFA siguiendo los pasos descritos en [Autenticación con Resource Owner Password Grant y MFA](/es/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa).

<div id="retrieve-enrolled-authenticators">
  ### Obtener los autenticadores inscritos
</div>

Para plantear un desafío al usuario, necesitas el `authenticator_id` del factor que quieres usar para el desafío. Puedes listar todos los autenticadores inscritos mediante el endpoint MFA Authenticators:

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url 'https://{yourDomain}/mfa/authenticators' \
    --header 'authorization: Bearer MFA_TOKEN' \
    --header 'content-type: application/json'
  ```

  ```csharp C# theme={null}
  var client = new RestClient("https://{yourDomain}/mfa/authenticators");
  var request = new RestRequest(Method.GET);
  request.AddHeader("authorization", "Bearer MFA_TOKEN");
  request.AddHeader("content-type", "application/json");
  IRestResponse response = client.Execute(request);
  ```

  ```go Go theme={null}
  package main

  import (
  	"fmt"
  	"net/http"
  	"io/ioutil"
  )

  func main() {

  	url := "https://{yourDomain}/mfa/authenticators"

  	req, _ := http.NewRequest("GET", url, nil)

  	req.Header.Add("authorization", "Bearer MFA_TOKEN")
  	req.Header.Add("content-type", "application/json")

  	res, _ := http.DefaultClient.Do(req)

  	defer res.Body.Close()
  	body, _ := ioutil.ReadAll(res.Body)

  	fmt.Println(res)
  	fmt.Println(string(body))

  }
  ```

  ```java Java theme={null}
  HttpResponse<String> response = Unirest.get("https://{yourDomain}/mfa/authenticators")
    .header("authorization", "Bearer MFA_TOKEN")
    .header("content-type", "application/json")
    .asString();
  ```

  ```javascript Node.JS theme={null}
  var axios = require("axios").default;

  var options = {
    method: 'GET',
    url: 'https://{yourDomain}/mfa/authenticators',
    headers: {authorization: 'Bearer MFA_TOKEN', 'content-type': 'application/json'}
  };

  axios.request(options).then(function (response) {
    console.log(response.data);
  }).catch(function (error) {
    console.error(error);
  });
  ```

  ```php PHP theme={null}
  $curl = curl_init();

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://{yourDomain}/mfa/authenticators",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_HTTPHEADER => [
      "authorization: Bearer MFA_TOKEN",
      "content-type: application/json"
    ],
  ]);

  $response = curl_exec($curl);
  $err = curl_error($curl);

  curl_close($curl);

  if ($err) {
    echo "cURL Error #:" . $err;
  } else {
    echo $response;
  }
  ```

  ```python Python theme={null}
  import http.client

  conn = http.client.HTTPSConnection("")

  headers = {
      'authorization': "Bearer MFA_TOKEN",
      'content-type': "application/json"
      }

  conn.request("GET", "/{yourDomain}/mfa/authenticators", headers=headers)

  res = conn.getresponse()
  data = res.read()

  print(data.decode("utf-8"))
  ```

  ```ruby Ruby theme={null}
  require 'uri'
  require 'net/http'
  require 'openssl'

  url = URI("https://{yourDomain}/mfa/authenticators")

  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE

  request = Net::HTTP::Get.new(url)
  request["authorization"] = 'Bearer MFA_TOKEN'
  request["content-type"] = 'application/json'

  response = http.request(request)
  puts response.read_body
  ```
</AuthCodeGroup>

<div id="challenge-user-with-otp">
  ### Solicitar un OTP al usuario
</div>

Para iniciar un desafío por correo electrónico, envía una solicitud `POST` al endpoint de desafío de MFA con el `authenticator_id` correspondiente y el `mfa_token`.

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url 'https://{yourDomain}/mfa/challenge' \
    --data '{  "client_id": "{yourClientId}",  "client_secret": "{yourClientSecret}",  "challenge_type": "oob",  "authenticator_id": "email|dev_NU1Ofuw3Cw0XCt5x", "mfa_token": "{mfaToken}" }'
  ```

  ```csharp C# theme={null}
  var client = new RestClient("https://{yourDomain}/mfa/challenge");
  var request = new RestRequest(Method.POST);
  request.AddParameter("undefined", "{  "client_id": "{yourClientId}",  "client_secret": "{yourClientSecret}",  "challenge_type": "oob",  "authenticator_id": "email|dev_NU1Ofuw3Cw0XCt5x", "mfa_token": "{mfaToken}" }", ParameterType.RequestBody);
  IRestResponse response = client.Execute(request);
  ```

  ```go Go theme={null}
  package main

  import (
  	"fmt"
  	"strings"
  	"net/http"
  	"io/ioutil"
  )

  func main() {

  	url := "https://{yourDomain}/mfa/challenge"

  	payload := strings.NewReader("{  "client_id": "{yourClientId}",  "client_secret": "{yourClientSecret}",  "challenge_type": "oob",  "authenticator_id": "email|dev_NU1Ofuw3Cw0XCt5x", "mfa_token": "{mfaToken}" }")

  	req, _ := http.NewRequest("POST", url, payload)

  	res, _ := http.DefaultClient.Do(req)

  	defer res.Body.Close()
  	body, _ := ioutil.ReadAll(res.Body)

  	fmt.Println(res)
  	fmt.Println(string(body))

  }
  ```

  ```java Java theme={null}
  HttpResponse<String> response = Unirest.post("https://{yourDomain}/mfa/challenge")
    .body("{  "client_id": "{yourClientId}",  "client_secret": "{yourClientSecret}",  "challenge_type": "oob",  "authenticator_id": "email|dev_NU1Ofuw3Cw0XCt5x", "mfa_token": "{mfaToken}" }")
    .asString();
  ```

  ```javascript Node.JS theme={null}
  var axios = require("axios").default;

  var options = {
    method: 'POST',
    url: 'https://{yourDomain}/mfa/challenge',
    data: {
      client_id: '{yourClientId}',
      client_secret: '{yourClientSecret}',
      challenge_type: 'oob',
      authenticator_id: 'email|dev_NU1Ofuw3Cw0XCt5x',
      mfa_token: '{mfaToken}'
    }
  };

  axios.request(options).then(function (response) {
    console.log(response.data);
  }).catch(function (error) {
    console.error(error);
  });
  ```

  ```php PHP theme={null}
  $curl = curl_init();

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://{yourDomain}/mfa/challenge",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_POSTFIELDS => "{  "client_id": "{yourClientId}",  "client_secret": "{yourClientSecret}",  "challenge_type": "oob",  "authenticator_id": "email|dev_NU1Ofuw3Cw0XCt5x", "mfa_token": "{mfaToken}" }",
  ]);

  $response = curl_exec($curl);
  $err = curl_error($curl);

  curl_close($curl);

  if ($err) {
    echo "cURL Error #:" . $err;
  } else {
    echo $response;
  }
  ```

  ```python Python theme={null}
  import http.client

  conn = http.client.HTTPSConnection("")

  payload = "{  "client_id": "{yourClientId}",  "client_secret": "{yourClientSecret}",  "challenge_type": "oob",  "authenticator_id": "email|dev_NU1Ofuw3Cw0XCt5x", "mfa_token": "{mfaToken}" }"

  conn.request("POST", "/{yourDomain}/mfa/challenge", payload)

  res = conn.getresponse()
  data = res.read()

  print(data.decode("utf-8"))
  ```

  ```ruby Ruby theme={null}
  require 'uri'
  require 'net/http'
  require 'openssl'

  url = URI("https://{yourDomain}/mfa/challenge")

  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE

  request = Net::HTTP::Post.new(url)
  request.body = "{  "client_id": "{yourClientId}",  "client_secret": "{yourClientSecret}",  "challenge_type": "oob",  "authenticator_id": "email|dev_NU1Ofuw3Cw0XCt5x", "mfa_token": "{mfaToken}" }"

  response = http.request(request)
  puts response.read_body
  ```
</AuthCodeGroup>

<div id="complete-authentication-using-received-code">
  ### Complete la autenticación con el code recibido
</div>

Si la operación se realiza correctamente, recibirá la siguiente respuesta:

```json lines theme={null}
{
  "challenge_type": "oob",
  "oob_code": "abcd1234...",
  "binding_method": "prompt"
}
```

La aplicación debe solicitar al usuario el código y enviarlo como parte de la solicitud en el parámetro `binding_code` en la siguiente llamada al endpoint `oauth``/token`:

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url 'https://{yourDomain}/oauth/token' \
    --header 'content-type: application/x-www-form-urlencoded' \
    --data grant_type=http://auth0.com/oauth/grant-type/mfa-oob \
    --data 'client_id={yourClientId}' \
    --data 'client_secret={yourClientSecret}' \
    --data 'mfa_token={mfaToken}' \
    --data 'oob_code={oobCode}' \
    --data 'binding_code={userEmailOtpCode}'
  ```

  ```csharp C# theme={null}
  var client = new RestClient("https://{yourDomain}/oauth/token");
  var request = new RestRequest(Method.POST);
  request.AddHeader("content-type", "application/x-www-form-urlencoded");
  request.AddParameter("application/x-www-form-urlencoded", "grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=%7BuserEmailOtpCode%7D", ParameterType.RequestBody);
  IRestResponse response = client.Execute(request);
  ```

  ```go Go theme={null}
  package main

  import (
  	"fmt"
  	"strings"
  	"net/http"
  	"io/ioutil"
  )

  func main() {

  	url := "https://{yourDomain}/oauth/token"

  	payload := strings.NewReader("grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=%7BuserEmailOtpCode%7D")

  	req, _ := http.NewRequest("POST", url, payload)

  	req.Header.Add("content-type", "application/x-www-form-urlencoded")

  	res, _ := http.DefaultClient.Do(req)

  	defer res.Body.Close()
  	body, _ := ioutil.ReadAll(res.Body)

  	fmt.Println(res)
  	fmt.Println(string(body))

  }
  ```

  ```java Java theme={null}
  HttpResponse<String> response = Unirest.post("https://{yourDomain}/oauth/token")
    .header("content-type", "application/x-www-form-urlencoded")
    .body("grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=%7BuserEmailOtpCode%7D")
    .asString();
  ```

  ```javascript Node.JS theme={null}
  var axios = require("axios").default;

  var options = {
    method: 'POST',
    url: 'https://{yourDomain}/oauth/token',
    headers: {'content-type': 'application/x-www-form-urlencoded'},
    data: new URLSearchParams({
      grant_type: 'http://auth0.com/oauth/grant-type/mfa-oob',
      client_id: '{yourClientId}',
      client_secret: '{yourClientSecret}',
      mfa_token: '{mfaToken}',
      oob_code: '{oobCode}',
      binding_code: '{userEmailOtpCode}'
    })
  };

  axios.request(options).then(function (response) {
    console.log(response.data);
  }).catch(function (error) {
    console.error(error);
  });
  ```

  ```php PHP theme={null}
  $curl = curl_init();

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://{yourDomain}/oauth/token",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_POSTFIELDS => "grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=%7BuserEmailOtpCode%7D",
    CURLOPT_HTTPHEADER => [
      "content-type: application/x-www-form-urlencoded"
    ],
  ]);

  $response = curl_exec($curl);
  $err = curl_error($curl);

  curl_close($curl);

  if ($err) {
    echo "cURL Error #:" . $err;
  } else {
    echo $response;
  }
  ```

  ```python Python theme={null}
  import http.client

  conn = http.client.HTTPSConnection("")

  payload = "grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=%7BuserEmailOtpCode%7D"

  headers = { 'content-type': "application/x-www-form-urlencoded" }

  conn.request("POST", "/{yourDomain}/oauth/token", payload, headers)

  res = conn.getresponse()
  data = res.read()

  print(data.decode("utf-8"))
  ```

  ```ruby Ruby theme={null}
  require 'uri'
  require 'net/http'
  require 'openssl'

  url = URI("https://{yourDomain}/oauth/token")

  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE

  request = Net::HTTP::Post.new(url)
  request["content-type"] = 'application/x-www-form-urlencoded'
  request.body = "grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-oob&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&mfa_token=%7BmfaToken%7D&oob_code=%7BoobCode%7D&binding_code=%7BuserEmailOtpCode%7D"

  response = http.request(request)
  puts response.read_body
  ```
</AuthCodeGroup>

Si la llamada se realizó correctamente, recibirás una respuesta con el siguiente formato, que contiene el token de acceso:

```json lines theme={null}
{
  "id_token": "eyJ...i",
  "access_token": "eyJ...i",
  "expires_in": 600,
  "scope": "openid profile",
  "token_type": "Bearer"
}
```

<div id="customize-mfa">
  ## Personalizar MFA
</div>

<Warning>
  La MFA personalizable con los flujos Resource Owner Password Grant, Embedded o Token de actualización está en acceso anticipado. Al usar esta función, acepta los términos aplicables de la prueba gratuita del [Master Subscription Agreement](https://www.okta.com/legal/) de Okta. Para obtener más información sobre las etapas de lanzamiento de Auth0, consulte [Product Release Stages](/es/docs/troubleshoot/product-lifecycle/product-release-stages). Para participar en el acceso anticipado, póngase en contacto con [Soporte de Auth0](https://support.auth0.com/).
</Warning>

La MFA personalizable permite a los usuarios inscribirse y realizar desafíos con los factores que elijan y que sean compatibles con su aplicación.

Durante la autenticación en el endpoint `oauth/token`, la respuesta devuelve el error `mfa_required`, que incluye el `mfa_token` para usar la API de MFA y el parámetro `mfa_requirements` con una lista de autenticadores:

```json theme={null}
{
  "error": "mfa_required",
  "error_description": "Multifactor authentication required",
  "mfa_token": "Fe26...Ha",
  "mfa_requirements": {
    "challenge": [
      { "type": "otp" },
      { "type": "push-notification" },
      { "type": "phone" },
      { "type": "recovery-code" }
      { "type": "email"} //solo funciona con challenge
    ]
  }
}
```

Usa `mfa_token` para llamar al endpoint [`mfa/authenticator`](/es/docs/api/authentication/muti-factor-authentication/list-authenticators), obtener una lista de todos los factores en los que el usuario se ha inscrito y seleccionar el mismo tipo que admite tu aplicación. También debes obtener el `authenticator_type` correspondiente para generar desafíos:

```json theme={null}
[
  {
    "type": "recovery-code",
    "id": "recovery-code|dev_qpOkGUOxBpw6R16t",
    "authenticator_type": "recovery-code",
    "active": true
  },
  {
    "type": "otp",
    "id": "totp|dev_6NWz8awwC8brh2dN",
    "authenticator_type": "otp",
    "active": true
  }
]
```

Aplica el desafío de MFA llamando al endpoint [`request/mfa/challenge`](/es/docs/api/authentication/muti-factor-authentication/request-mfa-challenge).

Personaliza aún más tu flujo de MFA con Actions de Auth0. Para obtener más información, consulta [Actions Triggers: post-challenge - API Object](/es/docs/customize/actions/explore-triggers/password-reset-triggers/post-challenge-trigger/post-challenge-api-object).

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

* [Administrar factores de autenticación con Authentication API](/es/docs/secure/multi-factor-authentication/manage-mfa-auth0-apis/manage-authenticator-factors-mfa-api)
* [Desafío con códigos de recuperación](/es/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/challenge-with-recovery-codes)
* [Inscripción y desafío de autenticadores OTP](/es/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/enroll-and-challenge-otp-authenticators)
* [Inscripción y desafío de autenticadores push](/es/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/enroll-and-challenge-push-authenticators)
* [Inscripción y desafío de autenticadores SMS y de voz](/es/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa/enroll-challenge-sms-voice-authenticators)
