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

> Configuración de API y aplicaciones móviles para el escenario de arquitectura Mobile + API

# Configuración de API y aplicaciones móviles (aplicaciones móviles + API)

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

En esta sección veremos cómo implementar una API para nuestro caso.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Para simplificar, mantendremos la implementación centrada exclusivamente en la autenticación y la autorización. Como verá en los ejemplos, el registro de horas de entrada estará definido de forma fija en el código, y la API no persistirá ese registro. En su lugar, simplemente devolverá parte de la información.
</Callout>

<div id="define-the-api-endpoints">
  ## Definir los endpoints de la API
</div>

Primero debemos definir los endpoints de nuestra API.

<Card title="¿Qué es un endpoint de API?">
  Un **endpoint de API** es una URL única que representa un objeto. Para interactuar con este objeto, la aplicación debe apuntar a su URL. Por ejemplo, si tuviera una API que pudiera devolver pedidos o clientes, podría configurar dos endpoints: `/orders` y `/customers`. La aplicación interactuaría con estos endpoints mediante distintos métodos HTTP; por ejemplo, `POST /orders` podría crear un pedido nuevo o `GET /orders` podría recuperar el conjunto de datos de uno o más pedidos.
</Card>

Para esta implementación, solo definiremos dos endpoints: uno para recuperar una lista de todos los registros de horas de un empleado y otro que permitirá a un empleado crear un nuevo registro de horas.

Una solicitud `HTTP GET` al endpoint `/timesheets` permitirá que un usuario recupere sus registros de horas, y una solicitud `HTTP POST` al endpoint `/timesheets` permitirá que un usuario agregue un nuevo registro de horas.

Consulte la implementación en [Node.js](/es/docs/get-started/architecture-scenarios/mobile-api/api-implementation-nodejs#1-define-the-api-endpoints)

<div id="secure-the-endpoints">
  ### Proteger los endpoints
</div>

Cuando una API recibe una solicitud con un bearer <Tooltip tip="Token de acceso: credencial de autorización, en forma de cadena opaca o JWT, que se usa para acceder a una API." cta="Ver glosario" href="/es/docs/glossary?term=Access+Token">Token de acceso</Tooltip> en el encabezado, lo primero que debe hacerse es validar el token. Esto consiste en una serie de pasos y, si alguno de ellos falla, la solicitud debe rechazarse con el mensaje de error `Missing or invalid token` para la aplicación que realiza la llamada.

Las validaciones que debe realizar la API son:

* Verificar que el <Tooltip tip="JSON Web Token (JWT): formato estándar de ID Token (y, con frecuencia, de Token de acceso) que se usa para representar claims de forma segura entre dos partes." cta="Ver glosario" href="/es/docs/glossary?term=JWT">JWT</Tooltip> tenga un formato válido
* Verificar la firma
* Validar los claims estándar

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  [JWT.io](https://jwt.io/) proporciona una lista de bibliotecas que pueden hacer la mayor parte del trabajo por usted: analizar el JWT y verificar la firma y los claims.
</Callout>

Parte del proceso de validación también consiste en comprobar los permisos del cliente (alcances), pero esto se abordará por separado en el siguiente párrafo de este documento.

Para obtener más información sobre cómo validar tokens de acceso, consulte [Validar tokens de acceso](/es/docs/secure/tokens/access-tokens/validate-access-tokens).

Consulte la implementación en [Node.js](/es/docs/get-started/architecture-scenarios/mobile-api/api-implementation-nodejs#2-secure-the-api-endpoints)

<div id="check-the-clients-permissions">
  ### Comprobar los permisos del cliente
</div>

A estas alturas, ya hemos verificado que el JWT es válido. El último paso es comprobar que el cliente tenga los permisos necesarios para acceder a los recursos protegidos.

Para ello, la API debe comprobar los [alcances](/es/docs/get-started/apis/scopes) del JWT decodificado. Esta claim forma parte de la carga útil y es una lista de cadenas separadas por espacios.

Consulta la implementación en [Node.js](/es/docs/get-started/architecture-scenarios/mobile-api/api-implementation-nodejs#3-check-the-client-permissions)

<div id="determine-user-identity">
  ### Determinar la identidad del usuario
</div>

Para ambos endpoints (obtener la lista de registros de horas y agregar un nuevo registro de horas), necesitaremos determinar la identidad del usuario.

Al obtener la lista de registros de horas, esto garantiza que solo devolvamos los registros de horas que pertenecen al usuario que realiza la solicitud; y al agregar un nuevo registro de horas, garantiza que este se asocie con el usuario que realiza la solicitud.

Una de las claims estándar de un JWT es la claim `sub`, que identifica al principal que es el sujeto de la claim. En el caso del flujo Implicit Grant, esta claim contendrá la identidad del usuario, que será el identificador único del usuario de Auth0. Puede usarla para asociar cualquier información en sistemas externos con un usuario concreto.

También puede usar una claim personalizada para agregar otro atributo del usuario, como su correo electrónico, al Token de acceso y usarlo para identificar de forma única al usuario.

Consulte la implementación en [Node.js](/es/docs/get-started/architecture-scenarios/mobile-api/api-implementation-nodejs#4-determine-the-user-identity)

<div id="implement-the-mobile-app">
  ## Implementa la aplicación móvil
</div>

En esta sección veremos cómo implementar una aplicación móvil para este escenario.

[Consulta la implementación en Android.](/es/docs/get-started/architecture-scenarios/mobile-api/mobile-implementation-android#1-set-up-the-application)

<div id="authorize-the-user">
  ### Autorice al usuario
</div>

Para autorizar al usuario, implementaremos el [flujo de código de autorización con Proof Key for Code Exchange (PKCE)](/es/docs/get-started/authentication-and-authorization-flow/authorization-code-flow-with-pkce/call-your-api-using-the-authorization-code-flow-with-pkce). La aplicación móvil primero debe redirigir al usuario a la [URL de autorización](https://auth0.com/docs/api/authentication#authorization-code-grant-pkce-) junto con el `code_challenge` y el método utilizado para generarlo:

export const codeExample1 = `https://{yourDomain}/authorize?
    audience=API_AUDIENCE&
    scope=SCOPE&
    response_type=code&
    client_id={yourClientId}&
    code_challenge=CODE_CHALLENGE&
    code_challenge_method=S256&
    redirect_uri=https://YOUR_APP/callback`;

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

La solicitud `GET` a la URL de autorización debe incluir los siguientes valores:

| Parameter                   | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **client\_id**              | El valor de tu ID de cliente de Auth0. Puedes obtenerlo en la configuración de tu aplicación en el [Auth0 Dashboard](https://manage.auth0.com/#/applications).                                                                                                                                                                                                                                                                                                                                                                                                                      |
| **audience**                | El valor del identificador de tu API. Puedes obtenerlo en la configuración de tu API en el [Auth0 Dashboard](https://manage.auth0.com/#/apis).                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| **scope**                   | Los [alcances](/es/docs/get-started/apis/scopes) que determinan los claims que se devolverán en el ID Token y el token de acceso. Por ejemplo, un scope de `openid` devolverá un ID Token en la respuesta. En nuestra aplicación móvil de ejemplo, usamos los siguientes alcances: `create:timesheets read:timesheets openid profile email offline_access`. Estos alcances permiten que la aplicación móvil llame a la API, obtenga un [Token de actualización](/es/docs/glossary?term=Refresh+Token) y devuelva los claims `name`, `picture` y `email` del usuario en el ID Token. |
| **response\_type**          | Indica el flujo de autenticación que se debe usar. En una aplicación móvil que usa PKCE, debe establecerse en `code`.                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| **code\_challenge**         | El desafío de código generado a partir del verificador de código. Puedes encontrar instrucciones para generar un desafío de código [aquí](/es/docs/get-started/authentication-and-authorization-flow/authorization-code-flow-with-pkce/call-your-api-using-the-authorization-code-flow-with-pkce#authorize-the-user%23create-a-code-verifier).                                                                                                                                                                                                                                      |
| **code\_challenge\_method** | Método utilizado para generar el desafío. Auth0 solo admite `S256`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| **redirect\_uri**           | La URL a la que Auth0 redirigirá el navegador después de que el usuario haya otorgado la autorización. El código de autorización estará disponible en el parámetro de URL `code`. Esta URL debe especificarse como una URL de callback válida en la [configuración de tu aplicación](https://manage.auth0.com/#/applications).                                                                                                                                                                                                                                                      |

[Consulta la implementación en Android.](/es/docs/get-started/architecture-scenarios/mobile-api/mobile-implementation-android#2-authorize-the-user)

<div id="get-the-credentials">
  ### Obtener las credenciales
</div>

Tras realizar correctamente una solicitud a la URL de autorización, deberías recibir la siguiente respuesta:

export const codeExample2 = `HTTP/1.1 302 Found
Location: https://{yourDomain}/callback?code=AUTHORIZATION_CODE`;

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

A continuación, puedes intercambiar el `authorization_code` de la respuesta por un Token de acceso que puedes usar para llamar a tu API. Realiza una solicitud `POST` a la [URL del token](https://auth0.com/docs/api/authentication#authorization-code-pkce-) e incluye los siguientes datos:

<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 code_verified=YOUR_GENERATED_CODE_VERIFIER \
    --data code=YOUR_AUTHORIZATION_CODE \
    --data 'redirect_uri=https://{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}&code_verified=YOUR_GENERATED_CODE_VERIFIER&code=YOUR_AUTHORIZATION_CODE&redirect_uri=https%3A%2F%2F{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}&code_verified=YOUR_GENERATED_CODE_VERIFIER&code=YOUR_AUTHORIZATION_CODE&redirect_uri=https%3A%2F%2F{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 response = Unirest.post("https://{yourDomain}/oauth/token")
    .header("content-type", "application/x-www-form-urlencoded")
    .body("grant_type=authorization_code&client_id={yourClientId}&code_verified=YOUR_GENERATED_CODE_VERIFIER&code=YOUR_AUTHORIZATION_CODE&redirect_uri=https%3A%2F%2F{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}',
      code_verified: 'YOUR_GENERATED_CODE_VERIFIER',
      code: 'YOUR_AUTHORIZATION_CODE',
      redirect_uri: 'https://{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}&code_verified=YOUR_GENERATED_CODE_VERIFIER&code=YOUR_AUTHORIZATION_CODE&redirect_uri=https%3A%2F%2F{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}&code_verified=YOUR_GENERATED_CODE_VERIFIER&code=YOUR_AUTHORIZATION_CODE&redirect_uri=https%3A%2F%2F{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}&code_verified=YOUR_GENERATED_CODE_VERIFIER&code=YOUR_AUTHORIZATION_CODE&redirect_uri=https%3A%2F%2F{https://yourApp/callback}"

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

| Parámetro          | Descripción                                                                                                                                                                                                            |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **grant\_type**    | Debe establecerse como `authorization_code`.                                                                                                                                                                           |
| **client\_id**     | El valor de tu ID de cliente de Auth0. Puedes obtenerlo en la sección Settings de tu aplicación en el [Auth0 Dashboard](https://manage.auth0.com/#/applications).                                                      |
| **code\_verifier** | Clave aleatoria criptográficamente segura que se utilizó para generar el `code_challenge` enviado a la [URL de autorización](https://auth0.com/docs/api/authentication#authorization-code-grant-pkce-) (`/authorize`). |
| **code**           | El `authorization_code` recibido de la llamada anterior a `authorize`.                                                                                                                                                 |
| **redirect\_uri**  | La URL debe coincidir con el `redirect_uri` enviado en la sección anterior a `/authorize`.                                                                                                                             |

La respuesta de la URL de token contendrá:

```json lines theme={null}
{
  "access_token": "eyJz93a...k4laUWw",
  "refresh_token": "GEbRxBN...edjnXbL",
  "id_token": "eyJ0XAi...4faeEoQ",
  "token_type": "Bearer",
  "expires_in":86400
}
```

* **access\_token**: Un Token de acceso para la API, especificado por `audience`.
* **refresh\_token**: Un [Token de actualización](/es/docs/secure/tokens/refresh-tokens) solo estará presente si incluyó el scope `offline_access` y habilitó **Permitir acceso sin conexión** para su API en el Dashboard.
* **id\_token**: Un <Tooltip tip="ID Token: Credencial destinada al propio cliente, en lugar de para acceder a un recurso." cta="Ver glosario" href="/es/docs/glossary?term=ID+Token">ID Token</Tooltip> JWT que contiene información del perfil del usuario.
* **token\_type**: Una cadena que contiene el tipo de token; siempre será un token Bearer.
* **expires\_in**: La cantidad de segundos hasta que expire el Token de acceso.

Deberá almacenar las credenciales anteriores en el almacenamiento local para usarlas al llamar a su API y recuperar el perfil del usuario.

[Consulte la implementación en Android](/es/docs/get-started/architecture-scenarios/mobile-api/mobile-implementation-android#store-credentials).

<div id="get-the-user-profile">
  ### Obtener el perfil del usuario
</div>

Para obtener el [perfil del usuario](https://auth0.com/docs/api/authentication?http#user-profile), tu aplicación móvil puede decodificar el [ID Token](/es/docs/secure/tokens/id-tokens) con una de las [bibliotecas JWT](https://jwt.io/#libraries-io). Para ello, [verifica la firma](/es/docs/secure/tokens/id-tokens/validate-id-tokens#verify-the-signature) y [las claims](/es/docs/secure/tokens/id-tokens/validate-id-tokens#verify-the-claims) del token. Después de validar el ID Token, puedes acceder a su payload, que contiene la información del usuario:

```json lines theme={null}
{
  "email_verified": false,
  "email": "test.account@userinfo.com",
  "clientID": "q2hnj2iu...",
  "updated_at": "2016-12-05T15:15:40.545Z",
  "name": "test.account@userinfo.com",
  "picture": "https://s.gravatar.com/avatar/dummy.png",
  "user_id": "auth0|58454...",
  "nickname": "test.account",
  "created_at": "2016-12-05T11:16:59.640Z",
  "sub": "auth0|58454..."
}
```

[Consulte la implementación para Android.](/es/docs/get-started/architecture-scenarios/mobile-api/mobile-implementation-android#3-get-the-user-profile)

<div id="display-ui-elements-conditionally-based-on-scope">
  ### Mostrar elementos de la IU de forma condicional según el `scope`
</div>

En función del `scope` del usuario, es posible que quiera mostrar u ocultar determinados elementos de la IU. Para determinar el `scope` emitido para un usuario, deberá inspeccionar el `scope` que se concedió cuando el usuario se autenticó. Será una cadena que contiene todos los alcances, por lo que deberá comprobar si esa cadena contiene el `scope` requerido y, en función de ello, decidir si mostrar un elemento concreto de la IU.

[Consulte la implementación en Android](/es/docs/get-started/architecture-scenarios/mobile-api/mobile-implementation-android#4-display-ui-elements-conditionally-based-on-scope)

<div id="call-the-api">
  ### Llamar a la API
</div>

Para acceder a los recursos protegidos de tu API, debes incluir el token de acceso del usuario autenticado en las solicitudes que le envíes. Esto se logra enviando el token de acceso en un encabezado `Authorization` mediante el esquema `Bearer`.

[Consulta la implementación en Android.](/es/docs/get-started/architecture-scenarios/mobile-api/mobile-implementation-android#5-call-the-api)

<div id="renew-the-token">
  ### Renovar el token
</div>

<Warning>
  Los Tokens de actualización deben almacenarse de forma segura en la aplicación, ya que no caducan y permiten que un usuario permanezca autenticado prácticamente de forma indefinida. Si los Tokens de actualización se ven comprometidos o ya no los necesita, puede revocarlos mediante la [Authentication API](https://auth0.com/docs/api/authentication#revoke-refresh-token).
</Warning>

Para renovar su Token de acceso, realice una solicitud `POST` al endpoint `/oauth/token` con el <Tooltip tip="Token de actualización: token utilizado para obtener un Token de acceso renovado 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> de su resultado de autorización.

Un [Token de actualización](/es/docs/secure/tokens/refresh-tokens) solo estará presente si incluyó el scope `offline_access` en la solicitud de autorización anterior y habilitó **Allow Offline Access** para su API en el Dashboard.

Su solicitud debe incluir:

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url 'https://{yourDomain}/oauth/token' \
    --header 'content-type: application/x-www-form-urlencoded'
  ```

  ```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");
  IRestResponse response = client.Execute(request);
  ```

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

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

  func main() {

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

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

  	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 response = Unirest.post("https://{yourDomain}/oauth/token")
    .header("content-type", "application/x-www-form-urlencoded")
    .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'}
  };

  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_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("")

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

  conn.request("POST", "/{yourDomain}/oauth/token", 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}/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'

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

| Parámetro          | Descripción                                                                                                                                                        |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **grant\_type**    | Debe establecerse en `refresh_token`.                                                                                                                              |
| **client\_id**     | El valor de su ID de cliente de Auth0. Puede recuperarlo en la sección Settings de su aplicación en el [Auth0 Dashboard](https://manage.auth0.com/#/applications). |
| **refresh\_token** | el Token de actualización que se usará, obtenido del resultado de autenticación anterior.                                                                          |

La respuesta incluirá el nuevo Token de acceso:

```json lines theme={null}
{
  "access_token": "eyJz93a...k4laUWw",
  "refresh_token": "GEbRxBN...edjnXbL",
  "id_token": "eyJ0XAi...4faeEoQ",
  "token_type": "Bearer",
  "expires_in":86400
}
```

[Consulte la implementación en Android.](/es/docs/get-started/architecture-scenarios/mobile-api/mobile-implementation-android#store-the-credentials)
