> ## Documentation Index
> Fetch the complete documentation index at: https://docs.abbyy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Flujo de código de autorización

> Use el flujo de código de autorización de OAuth 2.0 con PKCE para autenticar a los usuarios en ABBYY Vantage y obtener tokens de acceso para la Vantage API.

export const VantageRegion = ({children}) => {
  const STORAGE_KEY = "abbyy.vantage.region";
  const REGIONS = [{
    code: "eu",
    label: "Europe"
  }, {
    code: "us",
    label: "North America"
  }, {
    code: "au",
    label: "Australia / Asia-Pacific"
  }];
  const [region, setRegion] = useState("eu");
  const [open, setOpen] = useState(false);
  const containerRef = useRef(null);
  const dropdownRef = useRef(null);
  function safeGetSavedRegion() {
    try {
      const saved = typeof window !== "undefined" ? window.localStorage.getItem(STORAGE_KEY) : null;
      const valid = new Set(REGIONS.map(r => r.code));
      return saved && valid.has(saved) ? saved : "eu";
    } catch {
      return "eu";
    }
  }
  function safeSetSavedRegion(code) {
    try {
      if (typeof window !== "undefined") {
        window.localStorage.setItem(STORAGE_KEY, code);
      }
    } catch {}
  }
  function dispatchRegionChanged(code) {
    try {
      if (typeof window !== "undefined") {
        window.dispatchEvent(new CustomEvent("abbyy:region-changed", {
          detail: {
            code
          }
        }));
      }
    } catch {}
  }
  function replaceRegionInString(text, currentRegion) {
    if (typeof text !== "string") return text;
    const hostRegex = /https:\/\/vantage-(eu|us|au)\.abbyy\.com/gi;
    const tokenRegex = /https:\/\/vantage-\[region\]\.abbyy\.com/gi;
    const bareHostRegex = /vantage-(eu|us|au)\.abbyy\.com/gi;
    const bareTokenRegex = /vantage-\[region\]\.abbyy\.com/gi;
    return text.replace(hostRegex, `https://vantage-${currentRegion}.abbyy.com`).replace(tokenRegex, `https://vantage-${currentRegion}.abbyy.com`).replace(bareHostRegex, `vantage-${currentRegion}.abbyy.com`).replace(bareTokenRegex, `vantage-${currentRegion}.abbyy.com`);
  }
  useEffect(() => {
    setRegion(safeGetSavedRegion());
  }, []);
  useEffect(() => {
    const root = containerRef.current;
    if (!root) return;
    const anchors = root.querySelectorAll("a[href]");
    anchors.forEach(a => {
      const href = a.getAttribute("href");
      if (href) {
        const next = replaceRegionInString(href, region);
        if (next !== href) {
          a.setAttribute("href", next);
        }
      }
    });
    const walker = typeof document !== "undefined" ? document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null) : null;
    if (walker) {
      const toUpdate = [];
      let node = walker.nextNode();
      while (node) {
        const updated = replaceRegionInString(node.nodeValue, region);
        if (updated !== node.nodeValue) {
          toUpdate.push([node, updated]);
        }
        node = walker.nextNode();
      }
      toUpdate.forEach(([textNode, value]) => {
        textNode.nodeValue = value;
      });
    }
  }, [region, children]);
  useEffect(() => {
    const root = containerRef.current;
    if (!root) return;
    const anchors = root.querySelectorAll("a[href]");
    anchors.forEach(a => {
      a.style.fontWeight = "600";
      a.style.textDecoration = "underline";
      a.style.textUnderlineOffset = "2px";
    });
  }, [region, children]);
  useEffect(() => {
    const onRegionChanged = evt => {
      const code = evt && evt.detail && evt.detail.code;
      if (!code || code === region) return;
      setRegion(code);
    };
    if (typeof window !== "undefined") {
      window.addEventListener("abbyy:region-changed", onRegionChanged);
    }
    return () => {
      if (typeof window !== "undefined") {
        window.removeEventListener("abbyy:region-changed", onRegionChanged);
      }
    };
  }, [region]);
  useEffect(() => {
    const onClickAway = e => {
      if (!dropdownRef.current) return;
      if (!dropdownRef.current.contains(e.target)) {
        setOpen(false);
      }
    };
    document.addEventListener("click", onClickAway, true);
    return () => document.removeEventListener("click", onClickAway, true);
  }, []);
  const onSelect = code => {
    setRegion(code);
    safeSetSavedRegion(code);
    dispatchRegionChanged(code);
    setOpen(false);
  };
  const current = REGIONS.find(r => r.code === region) || REGIONS[0];
  return <div className="not-prose">
      <div className="mb-4 inline-flex items-center gap-2" ref={dropdownRef}>
        <span className="text-sm text-zinc-950/80 dark:text-white/80">Tenant Region:</span>
        <div className="relative">
          <button type="button" aria-haspopup="listbox" aria-expanded={open ? "true" : "false"} onClick={() => setOpen(v => !v)} className="h-8 px-3 rounded-md bg-zinc-900/5 dark:bg-white/5 border border-zinc-950/20 dark:border-white/20 text-sm inline-flex items-center gap-2">
            <span className="text-zinc-950 dark:text-white">{current.label}</span>
            <svg width="8" height="24" viewBox="0 -9 3 24" className="transition-transform text-gray-400 overflow-visible dark:text-gray-600 ml-auto" style={{
    transform: open ? "rotate(270deg)" : "rotate(90deg)"
  }}>
              <path d="M0 0L3 3L0 6" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"></path>
            </svg>
          </button>
          {open ? <div role="listbox" className="absolute z-50 left-full top-0 ml-2 w-56 rounded-xl border border-zinc-950/20 dark:border-white/20 bg-white dark:bg-zinc-900 shadow-lg p-2">
              {REGIONS.map(r => {
    const selected = r.code === region;
    return <button key={r.code} type="button" role="option" aria-selected={selected ? "true" : "false"} onClick={() => onSelect(r.code)} className={"w-full flex items-center justify-between px-3 py-2 rounded-lg text-sm hover:bg-zinc-950/5 dark:hover:bg-white/10 text-zinc-950 dark:text-white" + (selected ? " font-medium" : "")}>
                    <span style={selected ? {
      color: "#ff2038"
    } : undefined}>{r.label}</span>
                    <span className={selected ? "ml-3" : "ml-3 invisible"} style={selected ? {
      color: "#ff2038"
    } : undefined}>✓</span>
                  </button>;
  })}
            </div> : null}
        </div>
      </div>
      <div ref={containerRef} className="prose dark:prose-invert max-w-none">{children}</div>
    </div>;
};

Este esquema de autenticación se considera el más seguro, ya que, en lugar de dirigir la solicitud de autenticación al usuario, la aplicación la envía al servidor de autorización de Vantage. El servidor de autorización autentica al usuario y devuelve el código de autorización al cliente.

Para evitar la interceptación del código de autorización, este escenario de autenticación utiliza una extensión de seguridad llamada PKCE (Proof Key for Code Exchange). Esta extensión funciona así: cada solicitud de autorización requiere generar un número aleatorio criptográfico y almacenarlo en **code\_verifier**, que luego se usa para obtener un valor firmado criptográficamente, almacenado en **code\_challenge**. Este nuevo valor se envía al servidor de autorización para obtener un código de autorización.

Para obtener más información sobre PKCE, visite [este enlace](https://datatracker.ietf.org/doc/html/rfc7636).

<div id="getting-the-authorization-code">
  #### Obtención del código de autorización
</div>

Para iniciar el proceso de autenticación, redirija al usuario al endpoint de autorización y pase los siguientes parámetros:

| Parameter                                      | Descripción                                                                                                                                                                      |
| ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| client\_id                                     | Identificador de la aplicación. Para saber cómo crear un cliente de Vantage API (**client\_id** y **client\_secret**), consulte el artículo Managing Tenant Vantage API Clients. |
| redirect\_uri                                  | La URL de su aplicación o sitio web a la que se redirigirá el navegador una vez otorgados los permisos de acceso.                                                                |
| response\_type=code                            | Especifica que se utiliza el tipo de respuesta de código de autorización.                                                                                                        |
| scope=openid permissions global.wildcard       | Especifica el ámbito de permisos.                                                                                                                                                |
| state                                          | Un valor de cadena arbitrario que contendrá el resultado de la autorización en la respuesta.                                                                                     |
| code\_challenge                                | Valor firmado digitalmente del **code\_verifier** (usando **code\_challenge\_method**).                                                                                          |
| code\_challenge\_method                        | El método de firma digital para **code\_verifier** (S256).                                                                                                                       |
| productId=a8548c9b-cb90-4c66-8567-d7372bb9b963 | Identificador de Vantage.                                                                                                                                                        |

<Warning>
  Los valores de response\_type, scope y productId deben ser exactamente los indicados arriba. Estas claves, excepto response\_type, pueden cambiar. Considere mantenerlas en la configuración.
</Warning>

Solicitud de ejemplo

<VantageRegion>
  ```shell wrap theme={null}
  https://vantage-us.abbyy.com/auth2/connect/authorize?client_id=client_id&redirect_uri=https%3A%2F%2Fvantage-us.abbyy.com%2Flogin-callback&response_type=code&scope=openid%20permissions%20global.wildcard&state=ef30939211cc4ecb9a7a349b855c6a10&code_challenge=tA6ayQ5VUjLX2tufAKaHh-9bTAQ4hQQY5VZAoB2kG9o&code_challenge_method=S256&productId=a8548c9b-cb90-4c66-8567-d7372bb9b963
  ```
</VantageRegion>

Un parámetro llamado redirect\_uri que contiene el identificador de su recurso se utiliza en OAuth 2.0 para permitir que Vantage envíe el código de autorización a su recurso y luego intercambie ese código por el token de acceso, necesario para la autenticación en todas las llamadas posteriores a la API. El uso de este método de autenticación requiere proporcionar el valor del parámetro redirect\_uri al soporte técnico de ABBYY para que los administradores lo incluyan en la lista de permitidos.

Una vez verificado que se han concedido los permisos de acceso solicitados mediante el parámetro scope, el navegador se redirige a una página web específica configurada por el servidor de Vantage. Esta página web contiene un cuadro de diálogo que se utiliza para completar la autorización con su cuenta. Esta página debe abrirse en un navegador que tenga visible la barra de direcciones, lo que le permitirá verificar la URL de la página y el estado del certificado SSL de la conexión.

Si su dirección de correo electrónico está vinculada a varias cuentas en distintos tenants, se le pedirá que seleccione un tenant e introduzca su contraseña después de especificar su dirección de correo electrónico. También puede pasar su identificador de tenant (el parámetro tokenId) directamente mediante uno de los siguientes recursos:

<VantageRegion>
  ```shell wrap theme={null}
  https://vantage-us.abbyy.com/auth2/{tenantId}/connect/authorize?client_id=client_id&redirect_uri=external_app_redirect_uri&response_type=code
  &scope=openid%20permissions%20global.wildcard&state=state&code_challenge=code_challenge
  &code_challenge_method=S256&productId=a8548c9b-cb90-4c66-8567-d7372bb9b963
  ```
</VantageRegion>

o

<VantageRegion>
  ```shell wrap theme={null}
  https://vantage-us.abbyy.com/auth2/connect/authorize?client_id=client_id&redirect_uri=external_app_redirect_uri&response_type=code
  &scope=openid%20permissions%20global.wildcard&state=state&code_challenge=code_challenge
  &code_challenge_method=S256&productId=a8548c9b-cb90-4c66-8567-d7372bb9b963&tenantId=tenantId
  ```
</VantageRegion>

Se te pedirá que introduzcas la contraseña de tu cuenta de tenant. Una vez que hayas introducido tus credenciales, la autorización se completa del lado del servidor, la aplicación obtiene acceso a la Vantage API y recibes el código de autorización en la respuesta a tu solicitud.

Tenga en cuenta que, si un sitio o aplicación utiliza este tipo de autenticación, los usuarios de Vantage concederán acceso a la Vantage API en su nombre al sitio o aplicación que está añadiendo a la lista de URL de redirección permitidas. Para proporcionar acceso al sitio o a la aplicación, se pedirá a los usuarios que se autentiquen en Vantage con su nombre de usuario y contraseña. Una vez que el usuario se haya autenticado, al sitio o a la aplicación se le otorgarán los siguientes permisos:

* Administrar catálogos de datos en el tenant de Vantage en nombre del usuario.
* Acceder a skills en el tenant de Vantage en nombre del usuario.
* Crear y acceder a transacciones de Vantage en nombre del usuario.

El sitio o la aplicación no podrá cambiar la contraseña del usuario, modificar la lista de usuarios en un tenant de Vantage ni editar skills. Solo se concederá acceso a la Vantage API. El usuario no podrá revocar este acceso una vez que haya sido concedido.

<div id="getting-the-authorization-token">
  #### Obtención del token de autorización
</div>

Una vez que haya obtenido el código de autorización, dispone de un minuto para intercambiarlo por el token de acceso. Use una solicitud POST al endpoint de token con datos `application/x-www-form-urlencoded`.

Parámetros del cuerpo de la solicitud:

| Parameter                                                | Descripción                                                                                                      |
| -------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| code\_verifier                                           | El código que generó. Necesario para confirmar el inicio de la solicitud de autorización.                        |
| client\_id                                               | El identificador de la aplicación.                                                                               |
| client\_secret                                           | Clave segura de la aplicación.                                                                                   |
| code                                                     | Su código de autorización obtenido del servidor.                                                                 |
| redirect\_uri                                            | La URL de redirección utilizada en el paso de autorización.                                                      |
| grant\_type=authorization\_code                          | Especifica que se utiliza el tipo de concesión “authorization code”.                                             |
| scope=openid permissions global.wildcard offline\_access | Especifica el ámbito de permisos. Para obtener un token de actualización, agregue **offline\_access** al ámbito. |

Ejemplo de solicitud:

Para Windows:

<VantageRegion>
  ```shell theme={null}
  curl --location --request POST "https://vantage-eu.abbyy.com/auth2/connect/token" \
    --data-urlencode "code_verifier=code_verifier" \
    --data-urlencode "client_id=client_id" \
    --data-urlencode "client_secret=client_secret" \
    --data-urlencode "code=authorization code" \
    --data-urlencode "redirect_uri=external app redirect uri" \
    --data-urlencode "grant_type=authorization_code"
  ```
</VantageRegion>

Para Linux:

<VantageRegion>
  ```shell theme={null}
  curl --location --request POST 'https://vantage-eu.abbyy.com/auth2/connect/token' \
    --data-urlencode 'code_verifier=code_verifier' \
    --data-urlencode 'client_id=client_id' \
    --data-urlencode 'client_secret=client_secret' \
    --data-urlencode 'code=authorization code' \
    --data-urlencode 'redirect_uri=external app redirect uri' \
    --data-urlencode 'grant_type=authorization_code'
  ```
</VantageRegion>

La respuesta del servidor a su solicitud contendrá el token de acceso:

```json theme={null}
{
  "id_token": "<redacted>",
  "access_token": "<redacted>",
  "expires_in": 86400,
  "token_type": "Bearer",
  "refresh_token": "<redacted>",
  "scope": "openid permissions global.wildcard offline_access legacy.client"
}
```

Para obtener más información sobre el flujo de código de autorización, visita [este enlace](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1).

Para cada flujo, la clave **access\_token** contiene el token, mientras que la clave **expires\_in** indica en cuánto tiempo caducará el token (en segundos). De forma predeterminada, la vigencia del token de acceso es de 24 horas (para obtener más información, vea [Token lifetimes](#token-lifetimes)). Agregue el siguiente encabezado de autorización a todas sus solicitudes y sustituya `token` por el valor que recibió:

```shell theme={null}
-H "Authorization: Bearer token"
```

Ten en cuenta que puedes obtener varios tokens con la misma cuenta. Para obtener más información sobre el token de autorización, visita [este enlace](https://datatracker.ietf.org/doc/html/rfc6749#section-7.1).

<div id="getting-the-refresh-token">
  #### Obtención del token de actualización
</div>

Si la opción `Allow issuing refresh tokens to refresh access tokens` estaba habilitada al configurar el cliente de Vantage API y la solicitud para obtener el token de acceso contenía el parámetro `scope=openid permissions global.wildcard offline_access`, también recibirá un token de actualización adicional en la respuesta. Una vez que tenga un token de actualización, puede renovar el token de acceso mediante una solicitud POST al endpoint de token con los siguientes parámetros:

| Parámetro                  | Descripción                                                           |
| -------------------------- | --------------------------------------------------------------------- |
| client\_id                 | El identificador de la aplicación.                                    |
| client\_secret             | Una clave segura de la aplicación.                                    |
| refresh\_token             | Su token de actualización obtenido del servidor.                      |
| grant\_type=refresh\_token | Especifica que se usa el tipo de concesión de token de actualización. |

Ejemplo de solicitud:

Para Windows:

<VantageRegion>
  ```shell theme={null}
  curl --location --request POST "https://vantage-eu.abbyy.com/auth2/connect/token" \
    --data-urlencode "client_id=client_id" \
    --data-urlencode "client_secret=client_secret" \
    --data-urlencode "refresh_token=refresh_token" \
    --data-urlencode "grant_type=refresh_token"
  ```
</VantageRegion>

Para Linux:

<VantageRegion>
  ```shell theme={null}
  curl --location --request POST 'https://vantage-eu.abbyy.com/auth2/connect/token' \
    --data-urlencode 'client_id=client_id' \
    --data-urlencode 'client_secret=client_secret' \
    --data-urlencode 'refresh_token=refresh_token' \
    --data-urlencode 'grant_type=refresh_token'
  ```
</VantageRegion>

<div id="token-lifetimes">
  #### Vigencia de los tokens
</div>

Los tokens de acceso y actualización se configuran con las siguientes vigencias:

* **Vigencia del token de acceso:** Define el periodo durante el cual el token de acceso emitido permite el acceso del usuario a Vantage. La vigencia predeterminada de un token de acceso es de 24 horas.
* **Vigencia del token de actualización:** Define el periodo absoluto que comienza con la emisión del primer token de acceso, durante el cual el token de actualización emitido puede utilizarse para renovar el token de acceso. La vigencia predeterminada de un token de actualización es de 30 días.
