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

# Consentimiento del usuario y aplicaciones de terceros

> Aprenda cómo Auth0 gestiona el consentimiento del usuario cuando las aplicaciones solicitan acceso a las API en nombre del usuario.

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

OAuth permite que las aplicaciones accedan a las API en nombre del usuario. Antes de que una aplicación pueda actuar en nombre de un usuario, este debe aprobar explícitamente los permisos solicitados. Este paso de aprobación se conoce como consentimiento del usuario.

Para las [aplicaciones de terceros](/es/docs/get-started/applications/third-party-applications), el consentimiento del usuario siempre es obligatorio. El usuario debe aprobar cada solicitud de autorización. En las [aplicaciones de primera parte](/es/docs/get-started/applications/first-party-and-third-party-applications), el consentimiento se puede omitir si así se configura, porque controla la aplicación y confía en que actuará de forma adecuada.

<div id="consent-dialog">
  ## Diálogo de consentimiento
</div>

Cuando una aplicación de terceros redirige a un usuario al endpoint `/authorize` y solicita acceso a una API, Auth0 muestra un cuadro de diálogo de consentimiento en el que se enumeran los permisos que solicita la aplicación.

La siguiente solicitud de autorización muestra un cuadro de diálogo de consentimiento en el que se pide al usuario que apruebe los permisos `read:posts` y `write:posts` para la API:

```http wrap lines theme={null}
GET /authorize?
  client_id=tpc_THIRD_PARTY_CLIENT_ID
  &redirect_uri=https://partner.example.com/callback
  &response_type=code
  &scope=read:posts write:posts
  &audience=https://social.example.com
  &code_challenge=CODE_CHALLENGE
  &code_challenge_method=S256
  &state=STATE_VALUE
```

<Frame>
  <img src="https://mintcdn.com/translations/MV7tE-x71x8RWRES/docs/images/cdy7uua7fh8z/5Cz3aZKw8RRVlMkc5Zl6x7/62ac54cbc470286d5c2139d47c604ebc/2025-02-28_14-57-52.png?fit=max&auto=format&n=MV7tE-x71x8RWRES&q=85&s=c1b1fcb30cec8913b375571e6d396a00" alt="Autorización: consentimiento del usuario y aplicaciones: diálogo de consentimiento" width="391" height="698" data-path="docs/images/cdy7uua7fh8z/5Cz3aZKw8RRVlMkc5Zl6x7/62ac54cbc470286d5c2139d47c604ebc/2025-02-28_14-57-52.png" />
</Frame>

Si el usuario lo aprueba, Auth0 crea una concesión de usuario que representa su consentimiento para esta combinación de aplicación, API y alcances solicitados. La aplicación recibe un código de autorización como es habitual.

Una vez otorgado el consentimiento, el usuario no vuelve a ver el cuadro de diálogo de consentimiento en los inicios de sesión posteriores hasta que se revoque explícitamente.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Las aplicaciones de terceros con controles de seguridad mejorados no admiten alcances de OIDC (`openid`, `profile`, `email`) en esta versión. El cuadro de diálogo de consentimiento muestra solo los alcances de la API. La compatibilidad con OIDC para aplicaciones de terceros está prevista para una versión futura.
</Callout>

<div id="scope-descriptions">
  ## Descripciones de alcances
</div>

De forma predeterminada, la página de consentimiento usa nombres de alcances para solicitar el consentimiento del usuario. Como se muestra a continuación, defina los alcances con el formato `action:resource_name` para que se muestren claramente:

<Frame>
  <img src="https://mintcdn.com/translations/3nS3prIggmJG9TUI/docs/images/cdy7uua7fh8z/3Z4Ofbj5yF7eg5cLfcauh9/556bab9e627b0ff68b20664d149f1483/Blog_API_Permissions_-_English.png?fit=max&auto=format&n=3nS3prIggmJG9TUI&q=85&s=a716a58beca5daa6c9c12b4384e0a4a3" alt="Autorización - Consentimiento del usuario y aplicaciones - Alcances de consentimiento" width="1002" height="687" data-path="docs/images/cdy7uua7fh8z/3Z4Ofbj5yF7eg5cLfcauh9/556bab9e627b0ff68b20664d149f1483/Blog_API_Permissions_-_English.png" />
</Frame>

La página de consentimiento agrupa los alcances de la misma API y muestra todas las acciones en una sola línea. Por ejemplo, la configuración anterior da como resultado **Posts: read and write your posts**.

Para mostrar el campo **Description** en lugar del nombre del scope, establezca en `true` la marca `use_scope_descriptions_for_consent` del inquilino:

<AuthCodeGroup>
  ```bash cURL wrap lines theme={null}
  curl --request PATCH \
    --url 'https://YOUR_DOMAIN/api/v2/tenants/settings' \
    --header 'Authorization: Bearer YOUR_MANAGEMENT_API_TOKEN' \
    --header 'Content-Type: application/json' \
    --data '{ "flags": { "use_scope_descriptions_for_consent": true } }'
  ```
</AuthCodeGroup>

Esta configuración afecta a las pantallas de consentimiento de todas las API del inquilino.

<div id="handle-rejected-permissions">
  ## Gestionar los permisos rechazados
</div>

Cuando un usuario rechaza el consentimiento, el comportamiento depende de la [política de redirección](/es/docs/get-started/applications/third-party-applications/security-controls#redirect-protection) de la aplicación:

* **`open_redirect_protection`** (valor predeterminado para aplicaciones de terceros): Auth0 muestra una página de error en lugar de redirigir. Esto evita los ataques de redirección abierta.
* **`allow_always`**: Auth0 redirige a la `redirect_uri` con un error `access_denied`:

```http wrap lines theme={null}
HTTP/1.1 302 Found
Location: https://partner.example.com/callback?
    error=access_denied
    &state=STATE_VALUE
```

<div id="skip-consent-for-first-party-applications">
  ## Omitir el consentimiento para aplicaciones de primera parte
</div>

Las aplicaciones de primera parte pueden omitir el cuadro de diálogo de consentimiento cuando la API tiene habilitada la opción **Allow Skipping User Consent**.

Para acceder al interruptor **Allow Skipping User Consent**, seleccione **Applications > APIs > (select the API) > Settings > Access Settings**.

Las aplicaciones de terceros siempre requieren consentimiento y no pueden omitir el cuadro de diálogo de consentimiento.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Incluso cuando se omite el consentimiento para las aplicaciones de primera parte, es posible que siga apareciendo una pantalla de confirmación de inicio de sesión cuando la aplicación usa un URI de devolución de llamada no verificable (como `localhost` o un esquema de URI personalizado). Esto protege a los usuarios contra la suplantación de aplicaciones en el mismo dispositivo. Para obtener más información, consulte [Medidas contra la suplantación de identidad de aplicaciones](/es/docs/secure/security-guidance/measures-against-app-impersonation).
</Callout>

<div id="revoke-consent">
  ## Revocar el consentimiento
</div>

Para revocar el consentimiento de un usuario para una aplicación específica:

1. Vaya a **Auth0 Dashboard > User Management > Users**.
2. Seleccione al usuario.
3. Seleccione la pestaña **Authorized Applications**.
4. Seleccione **Revoke** junto a la aplicación.

<div id="password-based-flows">
  ## Flujos basados en contraseña
</div>

Al usar el [flujo de contraseña del propietario del recurso](/es/docs/get-started/authentication-and-authorization-flow/resource-owner-password-flow), no se muestra ningún cuadro de diálogo de consentimiento, ya que el usuario proporciona directamente su contraseña a la aplicación, lo que equivale a concederle acceso completo a su cuenta.

<div id="force-consent">
  ## Forzar el consentimiento
</div>

Para obligar a los usuarios a dar su consentimiento en cada inicio de sesión (incluso si ya tienen una concesión existente), incluye `prompt=consent` en la solicitud a `/authorize`:

```http wrap lines theme={null}
GET /authorize?
  client_id=tpc_THIRD_PARTY_CLIENT_ID
  &redirect_uri=https://partner.example.com/callback
  &response_type=code
  &scope=read:posts write:posts
  &audience=https://social.example.com
  &prompt=consent
  &code_challenge=CODE_CHALLENGE
  &code_challenge_method=S256
  &state=STATE_VALUE
```

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

* [Aplicaciones de terceros](/es/docs/get-started/applications/third-party-applications)
* [Aplicaciones de primera parte y de terceros](/es/docs/get-started/applications/first-party-and-third-party-applications)
* [Controles de seguridad para aplicaciones de terceros](/es/docs/get-started/applications/third-party-applications/security-controls)
* [Tipos de concesión para aplicaciones](/es/docs/get-started/applications/application-grant-types)
* [Medidas contra la suplantación de identidad de aplicaciones](/es/docs/secure/security-guidance/measures-against-app-impersonation)
