> ## 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 obtener un token de actualización al iniciar una solicitud mediante el endpoint Authorize.

# Obtener tokens de actualización

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

Para obtener un <Tooltip tip="Token de actualización: token que se utiliza para obtener un nuevo Token de acceso sin obligar a los usuarios a volver a iniciar sesión." cta="Ver glosario" href="/es/docs/glossary?term=refresh+token">token de actualización</Tooltip>, debe incluir el `offline_access` [scope](/es/docs/get-started/apis/scopes) cuando inicie una solicitud de autenticación a través del endpoint `/authorize`. Asegúrese de habilitar Offline Access en su API. Para obtener más información, consulte [Configuración de la API](/es/docs/get-started/apis/api-settings).

Por ejemplo, si usa el [Flujo de código de autorización](/es/docs/get-started/authentication-and-authorization-flow/authorization-code-flow), la solicitud de autenticación tendría el siguiente aspecto:

export const codeExample1 = `https://{yourDomain}/authorize?
    audience={API_AUDIENCE}&
    scope=offline_access&
    response_type=code&
    client_id={yourClientId}&
    redirect_uri={https://yourApp/callback}&
    state={OPAQUE_VALUE}`;

<AuthCodeBlock children={codeExample1} language="http" />

El token de actualización se almacena en la sesión. Luego, cuando es necesario renovar una sesión (por ejemplo, porque ha transcurrido un período preconfigurado o el usuario intenta realizar una operación sensible), la aplicación usa el token de actualización en el backend para obtener un nuevo <Tooltip tip="ID Token: Credencial destinada al propio cliente, no a acceder a un recurso." cta="Ver glosario" href="/es/docs/glossary?term=ID+token">token de ID</Tooltip> mediante el endpoint `/oauth/token` con `grant_type=refresh_token`.

Una vez que el usuario se autentique correctamente, la aplicación será redirigida a `redirect_uri`, con un `code` como parte de la URL: `{https://yourApp/callback}?code=BPPLN3Z4qCTvSNOy`. Puede intercambiar este código por un <Tooltip tip="Token de acceso: Credencial de autorización, en forma de una cadena opaca o un JWT, utilizada para acceder a una API." cta="Ver glosario" href="/es/docs/glossary?term=access+token">token de acceso</Tooltip> mediante el 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=authorization_code \
    --data 'client_id={yourClientId}' \
    --data 'client_secret={yourClientSecret}' \
    --data 'code={yourAuthorizationCode}' \
    --data 'redirect_uri={https://yourApp/callback}'
  ```

  ```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=authorization_code&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&code=%7ByourAuthorizationCode%7D&redirect_uri={https://yourApp/callback}", 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=authorization_code&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&code=%7ByourAuthorizationCode%7D&redirect_uri={https://yourApp/callback}")

  	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=authorization_code&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&code=%7ByourAuthorizationCode%7D&redirect_uri={https://yourApp/callback}")
    .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: 'authorization_code',
      client_id: '{yourClientId}',
      client_secret: '{yourClientSecret}',
      code: '{yourAuthorizationCode}',
      redirect_uri: '{https://yourApp/callback}'
    })
  };

  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=authorization_code&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&code=%7ByourAuthorizationCode%7D&redirect_uri={https://yourApp/callback}",
    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=authorization_code&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&code=%7ByourAuthorizationCode%7D&redirect_uri={https://yourApp/callback}"

  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=authorization_code&client_id={yourClientId}&client_secret=%7ByourClientSecret%7D&code=%7ByourAuthorizationCode%7D&redirect_uri={https://yourApp/callback}"

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

La respuesta debe incluir un token de acceso y un token de actualización.

```json lines theme={null}
{
      "access_token": "eyJz93a...k4laUWw",
      "refresh_token": "GEbRxBN...edjnXbL",
      "token_type": "Bearer"
    }
```

Si solicita un Token de actualización para una aplicación móvil mediante el Cliente nativo correspondiente (que es público), no necesita enviar el `client_secret` en la solicitud, ya que solo se requiere para las aplicaciones confidenciales.

Los tokens de actualización deben almacenarse de forma segura en una aplicación, ya que permiten que un usuario permanezca autenticado prácticamente para siempre.

Para obtener más información sobre cómo implementar esto mediante el Flujo de código de autorización, consulte nuestro tutorial, [Llamar a una API mediante el Flujo de código de autorización](/es/docs/get-started/authentication-and-authorization-flow/authorization-code-flow/call-your-api-using-the-authorization-code-flow). Para otros tipos de concesión, consulte [Flujos de autenticación y autorización](/es/docs/get-started/authentication-and-authorization-flow).

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

<Warning>
  La MFA personalizable con los flujos de Resource Owner Password Grant, integrado o Token de actualización está en Early Access. Al usar esta función, aceptas 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, consulta [Product Release Stages](/es/docs/troubleshoot/product-lifecycle/product-release-stages). Para participar en el acceso anticipado, ponte en contacto con [Auth0 Support](https://support.auth0.com/).
</Warning>

La MFA personalizable permite a los usuarios inscribirse y verificarse con los factores compatibles con tu aplicación que elijan.

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 desafío
    ]
  }
}
```

Utilice `mfa_token` para llamar al endpoint [`mfa/authenticator`](/es/docs/api/authentication/muti-factor-authentication/list-authenticators) y obtener una lista de todos los factores que el usuario tiene inscritos, y haga coincidir el tipo con el que admite su aplicación. También debe obtener el `authenticator_type` correspondiente para emitir 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
  }
]
```

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

Personalice aún más su flujo de MFA con Auth0 Actions. Para obtener más información, consulte [Activadores de Actions: post-challenge - Objeto de API](/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>

* [Usar tokens de actualización](/es/docs/secure/tokens/refresh-tokens/use-refresh-tokens)
* [Revocar tokens de actualización](/es/docs/secure/tokens/refresh-tokens/revoke-refresh-tokens)
* [Rotación del token de actualización](/es/docs/secure/tokens/refresh-tokens/refresh-token-rotation)
* [Configurar la expiración del token de actualización](/es/docs/secure/tokens/refresh-tokens/configure-refresh-token-expiration)
