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

> Aprenda a configurar sus aplicaciones para usar SSO de aplicaciones nativas a web.

# Configurar e implementar SSO de aplicaciones nativas a web

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

<div id="configure-native-to-web-sso">
  ## Configurar el SSO de aplicaciones nativas a web
</div>

Para usar el <Tooltip tip="Inicio de sesión único (SSO): servicio que, una vez que un usuario inicia sesión en una aplicación, inicia automáticamente su sesión en otras aplicaciones." cta="Ver glosario" href="/es/docs/glossary?term=Single+Sign-On">inicio de sesión único</Tooltip> (SSO) de aplicaciones nativas a web, configure su aplicación nativa y su aplicación web (Single Page App o Regular Web App) para crear y administrar sesiones con la <Tooltip tip="Management API: un producto que permite a los clientes realizar tareas administrativas." cta="Ver glosario" href="/es/docs/glossary?term=Management+API">Management API</Tooltip> de Auth0.

Necesita un [token de acceso](/es/docs/secure/tokens/access-tokens/management-api-access-tokens) para usar la Management API o Auth0 CLI.

Para configurar el SSO de aplicaciones nativas a web, debe crear y administrar session\_transfer\_tokens y configurar sus aplicaciones nativa y web.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  El SSO de aplicaciones nativas a web es compatible con los siguientes SDKs: [Auth0 Android SDK](https://github.com/auth0/auth0.android/blob/main/EXAMPLES.md#native-to-web-sso-login-ea), [Auth0 Swift SDK](https://github.com/auth0/Auth0.swift/blob/master/EXAMPLES.md#sso-credentials-ea) y [Auth0 React Native SDK](https://github.com/auth0/react-native-auth0/blob/master/EXAMPLES.md#native-to-web-sso-early-access).

  La compatibilidad con el SSO de aplicaciones nativas a web está disponible en las siguientes herramientas: [Auth0 Deploy CLI](/es/docs/deploy-monitor/deploy-cli-tool). [Auth0 Terraform Provider](/es/docs/deploy-monitor/auth0-terraform-provider) y [Auth0 CLI](https://auth0.github.io/auth0-cli/).

  El SSO de aplicaciones nativas a web es compatible con cualquier flujo de autenticación que devuelva un token de actualización, como [Resource Owner Password Flow](/es/docs/secure/multi-factor-authentication/authenticate-using-ropg-flow-with-mfa) y [Authorization Code Flow with Proof Key for Code Exchange](/es/docs/get-started/authentication-and-authorization-flow/authorization-code-flow-with-pkce).
</Callout>

<div id="create-and-manage-session-transfer-tokens">
  ### Crear y gestionar tokens de transferencia de sesión
</div>

La primera llamada a la Management API permite a sus aplicaciones nativas y web:

* Crear y gestionar `session_transfer_tokens`
* Crear sesiones en un navegador web mediante cookies o un parámetro de URL
* Vincular la sesión al dispositivo de un usuario mediante una dirección IP o un ASN

Para las aplicaciones existentes, haga una llamada `PATCH` al endpoint [Update a Client](https://auth0.com/docs/api/management/v2/clients/patch-clients-by-id). Para crear una nueva aplicación, haga una llamada `POST` al endpoint [Create a Client](https://auth0.com/docs/api/management/v2/clients/post-clients):

```json lines theme={null}
{
  "session_transfer": {
    "can_create_session_transfer_token": false,
    "allowed_authentication_methods": ["cookie", "query"],
    "enforce_device_binding": "ip", // también "none" o "asn",
    "allow_refresh_token": false,
    "enforce_cascade_revocation": true,
    "enforce_online_refresh_tokens": true
  }
}
```

<div id="configure-native-applications">
  ### Configurar aplicaciones nativas
</div>

Una vez autenticado el usuario, Auth0 devuelve un [Token de acceso](/es/docs/secure/tokens/access-tokens), un [token de ID](/es/docs/secure/tokens/id-tokens) y, opcionalmente, un [Token de actualización](/es/docs/secure/tokens/refresh-tokens).

Puede configurar su aplicación nativa para intercambiar un <Tooltip tip="Token de actualización: token que se usa 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> por un Session Transfer Token. Si su aplicación web no admite la inyección de cookies, su aplicación nativa también debe configurar la **Login URI** de su aplicación web para inyectar el Session Transfer Token como parámetro de URI.

* Actualice su aplicación nativa mediante el <Tooltip tip="Auth0 Dashboard: producto principal de Auth0 para configurar sus servicios." cta="Ver glosario" href="/es/docs/glossary?term=Auth0+Dashboard">Auth0 Dashboard</Tooltip>:

  1. Vaya a [Dashboard > Applications](https://manage.auth0.com/dashboard/#/applications):
  2. Seleccione o [cree su aplicación](/es/docs/get-started/auth0-overview/create-applications#create-applications).
  3. Seleccione la pestaña **Settings**.
  4. En **Session Transfer**, habilite **Allow Native to Web SSO**.
  5. Seleccione **Require Cascade Revocation** para revocar automáticamente la sesión de la aplicación web y los tokens asociados.
  6. Seleccione **Save** para actualizar su aplicación.

<Frame>
  <img src="https://mintcdn.com/translations/S4csL9vq6QUX5-Rr/docs/images/sessions/session-transfer-native-app.png?fit=max&auto=format&n=S4csL9vq6QUX5-Rr&q=85&s=8cf5f51b19b9fae575f76b3560338ba8" alt="Aplicación nativa de Session Transfer" width="1404" height="481" data-path="docs/images/sessions/session-transfer-native-app.png" />
</Frame>

* Actualice su aplicación nativa con su <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> de la Management API mediante el endpoint [Update a Client](https://auth0.com/docs/api/management/v2/clients/patch-clients-by-id):

export const codeExample1 = `curl --request PATCH \
  --url 'https://{yourDomain}/api/v2/clients/{yourClientId}' \
  --header 'authorization: Bearer {yourMgmtApiAccessToken}' \
  --header 'content-type: application/json' \
  --data '{
  "session_transfer": {
    "can_create_session_transfer_token": true,
    "enforce_cascade_revocation": true
  }
}'`;

<AuthCodeBlock children={codeExample1} language="bash" filename="cURL" />

* Actualiza tu aplicación nativa mediante [Auth0 CLI](https://auth0.github.io/auth0-cli/auth0_apps_session-transfer_update.html):

export const codeExample2 = `auth0 apps session-transfer update {yourClientId} --can-create-token=true`;

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

<div id="configure-web-applications">
  ### Configurar aplicaciones web
</div>

Antes de habilitar Session Transfer Token, asegúrate de haber configurado el **URI de inicio de sesión de la aplicación** de tu aplicación web para que gestione parámetros adicionales. Para obtener más información sobre los URI, consulta [Configuración de la aplicación](/es/docs/get-started/applications/application-settings#application-uris).

* Actualiza tu aplicación web con Auth0 Dashboard:

  1. Ve a [Dashboard > Applications](https://manage.auth0.com/dashboard/#/applications):
  2. Selecciona o crea tu aplicación web.
  3. Selecciona la pestaña **Settings**.
  4. En **Session Transfer**, habilita **Native to Web SSO Methods**.
  5. Selecciona **Cookie Authentication** y **Query Authentication**.
  6. Habilita **Device Binding Method** y elige **None**, **ASN Binding** o **IP Address Binding**.
  7. Habilita **Allow Refresh Token Requests** para emitir nuevos tokens de actualización después de una transferencia de sesión.
  8. Selecciona **Use online refresh tokens**.
  9. Selecciona **Save** para actualizar tu aplicación web.

<Frame>
  <img src="https://mintcdn.com/translations/S4csL9vq6QUX5-Rr/docs/images/sessions/session-transfer-web-application.png?fit=max&auto=format&n=S4csL9vq6QUX5-Rr&q=85&s=a6457fed99af7a46292cc373dad463a1" alt="Aplicación web de Session Transfer" width="1404" height="944" data-path="docs/images/sessions/session-transfer-web-application.png" />
</Frame>

* Actualiza tu aplicación web con el token de acceso de Management API mediante el endpoint [Update a Client](https://auth0.com/docs/api/management/v2/clients/patch-clients-by-id):

export const codeExample3 = `curl --request PATCH \
  --url '{yourDomain}/api/v2/clients//{yourClientId}' \
  --header 'authorization: Bearer {yourMgmtApiAccessToken}' \
  --header 'content-type: application/json' \
  --data '{
  "session_transfer": {
    "allowed_authentication_methods": ["cookie", "query"],
    "enforce_device_binding": "ip", // también puede ser "none" o "asn",
    "allow_refresh_token": false,
    "enforce_online_refresh_tokens": true
  }
}'`;

<AuthCodeBlock children={codeExample3} language="bash" filename="cURL" />

* Actualiza tu aplicación web con la [Auth0 CLI](https://auth0.github.io/auth0-cli/auth0_apps_session-transfer_update.html):

export const codeExample4 = `auth0 apps session-transfer update {yourClientId}  --allowed-auth-methods=cookie,query --enforce-device-binding=ip`;

<AuthCodeBlock children={codeExample4} language="sh" />

<div id="implement-native-to-web-sso">
  ## Implementar SSO de nativa a web
</div>

El SSO de nativa a web ofrece una experiencia de usuario fluida al pasar usuarios autenticados de su aplicación nativa a su aplicación web.

Para ello, su aplicación nativa debe intercambiar un Token de actualización por un token de transferencia de sesión y enviar el token de transferencia de sesión, mediante una URL o una cookie, a su aplicación web para autorizar la sesión.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  * Si `allow_refresh_token` está deshabilitado en el cliente, pero la aplicación solicita `offline_access`, Auth0 no emitirá un `refresh_token`, aunque la autenticación seguirá funcionando.

  * Si la rotación del Token de actualización está habilitada, Auth0 devuelve un nuevo `refresh_token` en la llamada de intercambio de tokens. El intercambio del Token de actualización debe realizarse justo antes de que su código abra la aplicación web.
</Callout>

<div id="in-your-native-application">
  ### En la aplicación nativa
</div>

<div id="step-1-exchanging-a-refresh-token-for-a-session-transfer-token">
  #### Paso 1: Intercambia un Token de actualización por un token de transferencia de sesión
</div>

Usa el endpoint [/token](https://auth0.com/docs/api/authentication/authorization-code-flow-with-pkce/get-token-pkce) en tu aplicación nativa para intercambiar el token de actualización por un token de transferencia de sesión.

* Intercambia un token de actualización por un token de transferencia de sesión con los SDK de Swift, Android o React Native:

<Tabs>
  <Tab title="SDK de Swift">
    ```swift lines theme={null}
    credentialsManager.ssoCredentials { result in
        switch result {
        case .success(let ssoCredentials):
            print("Obtained SSO credentials: \(ssoCredentials)")
        case .failure(let error):
            print("Failed with: \(error)")
        }
    }

    // O bien, con async/await

    do {
        let ssoCredentials = try await credentialsManager.ssoCredentials()
        print("Obtained SSO credentials: \(ssoCredentials)")
    } catch {
        print("Failed with: \(error)")
    }
    ```
  </Tab>

  <Tab title="SDK de Android">
    ```kotlin lines theme={null}
    secureCredentialsManager.getSsoCredentials(
        mapOf(),  // parámetros opcionales
        object : Callback<SSOCredentials, CredentialsManagerException> {
            override fun onSuccess(result: SSOCredentials) {
                // Usa result.sessionTransferToken para autenticar
                // al usuario en una sesión web de tu aplicación
            }

            override fun onFailure(error: CredentialsManagerException) {
                // Gestiona el error
            }
        }
    )
    ```
  </Tab>

  <Tab title="SDK de React Native">
    ```typescript lines theme={null}
    // Uso de Hooks
    import { useAuth0 } from 'react-native-auth0';

    function MyComponent() {
      const { getSSOCredentials } = useAuth0();

      const openWebApp = async () => {
        try {
          const ssoCredentials = await getSSOCredentials();
          // Usa ssoCredentials.sessionTransferToken para autenticar
          // al usuario en una sesión web de tu aplicación
          console.log('Session Transfer Token:', ssoCredentials.sessionTransferToken);
        } catch (error) {
          console.error('Failed to get SSO credentials:', error);
        }
      };
    }

    // Uso de la clase Auth0
    import Auth0 from 'react-native-auth0';

    const auth0 = new Auth0({
      domain: '{yourDomain}',
      clientId: '{yourClientId}',
    });

    const ssoCredentials = await auth0.credentialsManager.getSSOCredentials();
    console.log('Session Transfer Token:', ssoCredentials.sessionTransferToken);
    ```
  </Tab>
</Tabs>

* Intercambia un token de actualización por un token de transferencia de sesión mediante HTTP:

export const codeExample5 = `curl -X POST https://{yourDomain}/oauth/token \
  -H 'Content-type: application/json' \
  -d '{"grant_type":"refresh_token", 
    "client_id":{yourClientId}",
    "refresh_token":"YOUR_REFRESH_TOKEN",
    "audience":"urn:YOUR_AUTH0_TENANT_DOMAIN:session_transfer"}'`;

<AuthCodeBlock children={codeExample5} language="bash" filename="cURL" />

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Estos ejemplos usan marcadores de posición para las variables dinámicas. Sustituya los marcadores de posición por su dominio de Auth0, client\_id y un refresh\_token existente.
</Callout>

El inquilino de Auth0 devuelve un session\_transfer\_token de un solo uso y de corta duración (con una vigencia de 1 minuto).

```json lines theme={null}
{
    "access_token": "{session_transfer_token}",
    "issued_token_type": "urn:auth0:params:oauth:token-type:session_transfer_token",
    "token_type": "N_A",
    "expires_in": 60
}
```

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Si la rotación de tokens de actualización está habilitada, el intercambio también devolverá un Token de actualización.

  Si solicitaste un ID Token durante la autenticación, esta llamada también devolverá un ID Token.
</Callout>

<div id="step-2-send-the-session-transfer-token-through-a-url-or-cookie">
  #### Paso 2: Envíe el token de transferencia de sesión a través de una URL o una cookie
</div>

Hay dos opciones para enviar el `session_transfer_token` a su aplicación web, según los `allowed_authentication_methods` configurados.

<div id="option-1-send-the-session_transfer_token-as-a-cookie">
  ##### Opción 1: Envíe el session\_transfer\_token como una cookie
</div>

Si su aplicación web, que usa WebView o un navegador, admite la inyección de cookies, puede configurar su aplicación nativa para:

* Agregar el session\_transfer\_token a una cookie.
* Abrir la aplicación web mediante WebView o un navegador.
* Iniciar sesión en la aplicación web en su dominio de Auth0 o <Tooltip tip="Dominio personalizado: dominio de terceros con un nombre específico o personalizado." cta="Ver glosario" href="/es/docs/glossary?term=Custom+Domain">Dominio personalizado</Tooltip>. Como el `session_transfer_token` está incluido en la cookie, no se solicita al usuario la autenticación del primer factor.

export const codeExample6 = `curl --cookie auth0_session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN
      https://{yourDomain}/authorize?{authorize_params}`;

<AuthCodeBlock children={codeExample6} language="bash" filename="cURL" />

<div id="option-2-send-the-session_transfer_token-as-a-url-parameter">
  ##### Opción 2: Enviar session\_transfer\_token como parámetro de URL
</div>

Si su aplicación web no admite la inyección de cookies, puede configurar su aplicación nativa mediante parámetros de URL para:

* Agregar session\_transfer\_token como parámetro de URL.
* Abrir la aplicación web mediante WebView o el navegador.
* Iniciar sesión en la aplicación web agregando `session_transfer_token` como parámetro de URL al endpoint [/authorize](https://auth0.com/docs/api/authentication/authorization-code-flow/authorize-application). El inquilino de Auth0 autentica al usuario sin requerir autenticación del primer factor, ya que session\_transfer\_token es válido y confiable.

<AuthCodeGroup>
  ```bash cURL lines theme={null}
  curl --request GET \
    --url 'https://your_web_app_login_url/?session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN'
  ```

  ```csharp C# lines theme={null}
  var client = new RestClient("https://your_web_app_login_url/?session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN");
  var request = new RestRequest(Method.GET);
  IRestResponse response = client.Execute(request);
  ```

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

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

  func main() {

  	url := "https://your_web_app_login_url/?session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN"

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

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

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

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

  }
  ```

  ```java Java lines theme={null}
  HttpResponse<String> response = Unirest.get("https://your_web_app_login_url/?session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN")
    .asString();
  ```

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

  var options = {
    method: 'GET',
    url: 'https://your_web_app_login_url/',
    params: {session_transfer_token: 'YOUR_SESSION_TRANSFER_TOKEN'}
  };

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

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

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://your_web_app_login_url/?session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET",
  ]);

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

  curl_close($curl);

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

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

  conn = http.client.HTTPSConnection("your_web_app_login_url")

  conn.request("GET", "/?session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN")

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

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

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

  url = URI("https://your_web_app_login_url/?session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN")

  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)

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

<div id="in-your-web-application">
  ### En tu aplicación web
</div>

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Cuando el token de transferencia de sesión se envía como una cookie, no se requiere ninguna configuración adicional, ya que el navegador envía la cookie en la solicitud al endpoint `/authorize`.
</Callout>

Implementa el SSO web único entre nativo y web en tu aplicación web mediante parámetros de URL:

<div id="option-1-add-the-session-transfer-token-in-your-web-application-request">
  #### Opción 1: Agregue el Session Transfer Token a la solicitud de su aplicación web
</div>

Desde la URL de inicio de sesión de la aplicación, redirija al endpoint `/authorize` cuando `session_transfer_token` se envíe como parámetro de URL.

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url 'https://{yourDomain}/authorize?session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN&client_ID={yourClientId}&redirect_uri=YOUR_REDIRECT_URI&response_type=code'
  ```

  ```csharp C# theme={null}
  var client = new RestClient("https://{yourDomain}/authorize?session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN&client_ID={yourClientId}&redirect_uri=YOUR_REDIRECT_URI&response_type=code");
  var request = new RestRequest(Method.GET);
  IRestResponse response = client.Execute(request);
  ```

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

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

  func main() {

  	url := "https://{yourDomain}/authorize?session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN&client_ID={yourClientId}&redirect_uri=YOUR_REDIRECT_URI&response_type=code"

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

  	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}/authorize?session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN&client_ID={yourClientId}&redirect_uri=YOUR_REDIRECT_URI&response_type=code")
    .asString();
  ```

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

  var options = {
    method: 'GET',
    url: 'https://{yourDomain}/authorize',
    params: {
      session_transfer_token: 'YOUR_SESSION_TRANSFER_TOKEN',
      client_ID: '{yourClientId}',
      redirect_uri: 'YOUR_REDIRECT_URI',
      response_type: 'code'
    }
  };

  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}/authorize?session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN&client_ID={yourClientId}&redirect_uri=YOUR_REDIRECT_URI&response_type=code",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET",
  ]);

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

  conn.request("GET", "/{yourDomain}/authorize?session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN&client_ID={yourClientId}&redirect_uri=YOUR_REDIRECT_URI&response_type=code")

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

  print(data.decode("utf-8"))
  ```
</AuthCodeGroup>

<div id="option-2-add-the-session-transfer-token-to-web-applications-using-auth0-sdks">
  #### Opción 2: Añada el Session Transfer Token a aplicaciones web que usan los SDK de Auth0
</div>

Los SDK de Auth0 no admiten automáticamente el SSO único de aplicaciones nativas a web y no incluyen `session_transfer_token` en la solicitud al endpoint `/authorize`.

A continuación, se muestran ejemplos de aplicaciones web que usan los SDK de Auth0 para redirigir `session_transfer_token` en la solicitud al endpoint `/authorize`:

<div id="node-expressjs">
  ##### Node (Express.js)
</div>

Si su aplicación web usa [Express.js](https://expressjs.com/) o el [SDK de Auth0 para Express](https://github.com/auth0/express-openid-connect), puede usar el siguiente código para añadir compatibilidad de middleware para `session_transfer_token`.

```javascript javascript lines theme={null}
const baseConfig = {
  authRequired: false,
  auth0Logout: true
};

// Extender el middleware para detectar automáticamente session_transfer_token
app.use((req, res, next) => {
  const { session_transfer_token } = req.query;

  // Crear una nueva configuración para cada solicitud y evitar la filtración de estado
  const config = { ...baseConfig };

  if (session_transfer_token) {
    config.authorizationParams = {
      session_transfer_token,
    };
  }

  auth(config)(req, res, next);
});
```

<div id="auth0-spa-sdk-auth0auth0-spa-js">
  ##### Auth0 SPA SDK (@auth0/auth0-spa-js)
</div>

Si tu aplicación web utiliza el [Auth0 SPA SDK](https://github.com/auth0/auth0-spa-js), puedes pasar `session_transfer_token` a `loginWithRedirect()` mediante `authorizationParams`.

```typescript typescript lines theme={null}
import { Auth0Client } from '@auth0/auth0-spa-js';

const auth0 = new Auth0Client({
  domain: '{yourDomain}',
  clientId: '{yourClientId}',
});

// Obtener session_transfer_token de los parámetros de consulta de la URL (enviado desde la app nativa)
const urlParams = new URLSearchParams(window.location.search);
const sessionTransferToken = urlParams.get('session_transfer_token');

// Usar loginWithRedirect con el session_transfer_token
if (sessionTransferToken) {
  await auth0.loginWithRedirect({
    authorizationParams: {
      session_transfer_token: sessionTransferToken,
      redirect_uri: window.location.origin,
    },
  });
}
```

<div id="auth0-react-sdk-auth0auth0-react">
  ##### SDK de React de Auth0 (@auth0/auth0-react)
</div>

Si tu aplicación web usa el [SDK de React de Auth0](https://github.com/auth0/auth0-react), puedes usar `loginWithRedirect` del hook `useAuth0` para pasar el `session_transfer_token`.

```typescript typescript lines theme={null}
import { useEffect } from 'react';
import { useAuth0 } from '@auth0/auth0-react';

function App() {
  const { loginWithRedirect, isAuthenticated, isLoading } = useAuth0();

  useEffect(() => {
    if (isLoading || isAuthenticated) return;

    const urlParams = new URLSearchParams(window.location.search);
    const sessionTransferToken = urlParams.get('session_transfer_token');

    if (sessionTransferToken) {
      loginWithRedirect({
        authorizationParams: {
          session_transfer_token: sessionTransferToken,
        },
      });
    }
  }, [loginWithRedirect, isLoading, isAuthenticated]);

  return <div>...</div>;
}
```

<div id="saml-and-ws-federation">
  ##### SAML y WS-Federation
</div>

Si su aplicación web usa <Tooltip tip="Security Assertion Markup Language (SAML): Protocolo estandarizado que permite que dos partes intercambien información de autenticación sin contraseña." cta="Ver glosario" href="/es/docs/glossary?term=SAML">SAML</Tooltip> o <Tooltip tip="Security Assertion Markup Language (SAML): Protocolo estandarizado que permite que dos partes intercambien información de autenticación sin contraseña." cta="Ver glosario" href="/es/docs/glossary?term=WS-Fed">WS-Fed</Tooltip> como proveedor de servicios y Auth0 como <Tooltip tip="Web Service Federation (WS-Fed): Protocolo para administrar identidades de usuario entre dominios." cta="Ver glosario" href="/es/docs/glossary?term=IdP">IdP</Tooltip>, puede enviar `session_transfer_token` como parámetro de URL al endpoint `/authorize` de Auth0, y `redirect_uri` será la URL de inicio de sesión de SAML o WS-Fed.

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url 'https://{yourDomain}/samlp//{yourClientId}?session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN' \
    --header 'cookie: session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN' \
    --cookie session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN
  ```

  ```csharp C# theme={null}
  var client = new RestClient("https://{yourDomain}/samlp//{yourClientId}?session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN");
  var request = new RestRequest(Method.GET);
  request.AddHeader("cookie", "session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN");
  IRestResponse response = client.Execute(request);
  ```

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

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

  func main() {

  	url := "https://{yourDomain}/samlp//{yourClientId}?session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN"

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

  	req.Header.Add("cookie", "session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN")

  	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.get("https://{yourDomain}/samlp//{yourClientId}?session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN")
    .header("cookie", "session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN")
    .asString();
  ```

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

  var options = {
    method: 'GET',
    url: 'https://{yourDomain}/samlp//{yourClientId}',
    params: {session_transfer_token: 'YOUR_SESSION_TRANSFER_TOKEN'},
    headers: {cookie: 'session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN'}
  };

  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}/samlp//{yourClientId}?session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_HTTPHEADER => [
      "cookie: session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN"
    ],
  ]);

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

  curl_close($curl);

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

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

  conn = http.client.HTTPSConnection("")

  headers = { 'cookie': "session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN" }

  conn.request("GET", "/{yourDomain}/samlp//{yourClientId}?session_transfer_token=YOUR_SESSION_TRANSFER_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}/samlp//{yourClientId}?session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN")

  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["cookie"] = 'session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN'

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

<div id="native-to-web-sso-with-organizations">
  ## SSO de nativo a web con Organizaciones
</div>

El SSO de nativo a web admite [Organizaciones](/es/docs/manage-users/organizations). Cuando un usuario se autentica con una organización en su aplicación nativa, el token de transferencia de sesión incluye el contexto de la organización.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Al usar Organizaciones con SSO de nativo a web, el parámetro `organization` en la solicitud `/authorize` de la aplicación web debe coincidir con la organización asociada al token de transferencia de sesión. Si no coincide, la autenticación fallará y se le pedirá al usuario que vuelva a iniciar sesión.
</Callout>

Para usar Organizaciones con SSO de nativo a web:

1. Autentique al usuario en su aplicación nativa con una organización:

```javascript javascript lines theme={null}
// Inicio de sesión en la app nativa con organización
await authorize({
  organization: 'org_abc123',
  scope: 'openid profile email offline_access'
});
```

2. Al redirigir a la aplicación web, incluye la misma organización en la solicitud de `/authorize`:

```bash bash lines theme={null}
https://{yourDomain}/authorize?
  client_id={yourWebClientId}&
  redirect_uri={yourRedirectUri}&
  response_type=code&
  organization=org_abc123&
  session_transfer_token=YOUR_SESSION_TRANSFER_TOKEN
```

Si la organización de la solicitud `/authorize` no coincide con la organización del token de transferencia de sesión, el token de transferencia de sesión se rechaza y el usuario es redirigido a la página de inicio de sesión para volver a autenticarse. Se genera una entrada de advertencia en los registros de su inquilino con la descripción del evento "Single Sign-On failed: Session Transfer Token organization mismatch detected."

<div id="session-transfer-token-with-actions">
  ## Token de transferencia de sesión con Actions
</div>

El uso de `session_transfer_token` con [Actions](/es/docs/customize/actions) le permite configurar capacidades de detección y respuesta ante riesgos posteriores a la autenticación para reforzar la protección del usuario.

Para ello, el objeto post-login de Action **event.session\_transfer\_token** proporciona información relevante, incluido el `client_id` único, `scope` e información de `request`, como `ip`, `asn` y `user_agent`, así como información de `geoip`, como `cityName`, `countryCode`, entre otros. Para obtener más información, consulte [Actions Triggers: post-login - Event Object](/es/docs/customize/actions/explore-triggers/signup-and-login-triggers/login-trigger/post-login-event-object).

El siguiente código de Action le permite rechazar dinámicamente una transacción en función de la información de geolocalización:

```javascript javascript lines theme={null}
/**
* Controlador que se invocará durante la ejecución de un flujo PostLogin.
*
* @param {Event} event - Detalles sobre el usuario y el contexto en el que está iniciando sesión.
* @param {PostLoginAPI} api - Interfaz cuyos métodos pueden usarse para modificar el comportamiento del inicio de sesión.
*/
exports.onExecutePostLogin = async (event, api) => {
   if(
     event.session_transfer_token &&
     event.session_transfer_token.request.geoip.countryCode !== event.request.geoip.countryCode
     ) {
     api.access.deny("Network mismatch detected")
   }
};
```

<div id="access-parent-refresh-token-metadata">
  ### Acceder a los metadatos del token de actualización padre
</div>

El SSO de nativo a web le permite acceder a los metadatos del token de actualización padre que se utilizó para iniciar el flujo de SSO. Esto le permite pasar información contextual recopilada en la aplicación nativa (como la integridad del dispositivo, señales de riesgo o contexto personalizado) a la sesión web creada a partir del `session_transfer_token`.

Auth0 expone esta información en las Actions de Post Login mediante el objeto `event.session.session_transfer.parent_refresh_token.metadata`. Esto permite la propagación segura y estandarizada de metadatos entre plataformas.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  **Caso de uso de ejemplo:** Una aplicación móvil recopila datos de riesgo (puntuación del dispositivo, ubicación, etc.) y los almacena en los metadatos del token de actualización. Cuando la aplicación nativa inicia un flujo de SSO de nativo a web, esos metadatos pasan a estar disponibles automáticamente en la sesión web correspondiente mediante Actions.
</Callout>

El siguiente código de Action le permite aplicar lógica de acceso condicional basada en metadatos de confianza del dispositivo procedentes de la aplicación nativa:

```javascript javascript lines theme={null}
/**
* Controlador que se llamará durante la ejecución de un flujo PostLogin.
*
* @param {Event} event - Detalles sobre el usuario y el contexto en el que está iniciando sesión.
* @param {PostLoginAPI} api - Interfaz cuyos métodos pueden usarse para modificar el comportamiento del inicio de sesión.
*/
exports.onExecutePostLogin = async (event, api) => {
  // Acceder a los metadatos del Token de actualización principal (aplicación nativa)
  const parentMetadata = event.session?.session_transfer?.parent_refresh_token?.metadata;

  if (parentMetadata) {
    const deviceTrustLevel = parentMetadata.device_trust;

    if (deviceTrustLevel !== 'high') {
      api.access.deny("Device trust level insufficient.");
    }

    // También puede agregar claims según el contexto de la aplicación nativa
    if (parentMetadata.subscription_tier) {
      api.idToken.setCustomClaim('subscription_tier', parentMetadata.subscription_tier);
    }
  }
};
```

<div id="monitoring">
  ## Monitoreo
</div>

Puede monitorear la actividad de SSO de Native to Web revisando los [registros](/es/docs/deploy-monitor/logs) del Tenant.

<div id="token-exchange-logs">
  ### Registros de intercambio de tokens
</div>

* `sertft` : Intercambio correcto del Token de actualización. Este registro corresponderá a un intercambio de SSO de una aplicación nativa a una aplicación web cuando el campo `audience` sea `"audience":"urn:$auth0Domain:session_transfer"`
* `fertft`: Intercambio fallido del Token de actualización. Este registro corresponderá a un intercambio de SSO de una aplicación nativa a una aplicación web cuando el campo `audience` sea `"audience": "urn:$auth0Domain:session_transfer"`

<div id="session-transfer-validation-warning-logs">
  ### Registros de advertencia de validación de la transferencia de sesión
</div>

Auth0 emite registros de advertencia (`w`) cuando falla la validación del token de transferencia de sesión durante la solicitud `/authorize`. Estos registros te ayudan a solucionar problemas de SSO de nativo a web:

| Descripción del evento                                                                                                   | Causa                                                                                                                                              |
| ------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Single Sign-On failed: Session Transfer Token not found or expired. This may indicate token reuse or expiration.`       | No se encontró el token de transferencia de sesión, ya se usó o expiró (los tokens son de un solo uso y expiran al cabo de 1 minuto).              |
| `Single Sign-On failed: Session Transfer Token device binding validation failed due to IP/ASN mismatch.`                 | La dirección IP o el ASN de la solicitud web no coinciden con la vinculación del dispositivo configurada para el token de transferencia de sesión. |
| `Single Sign-On failed: Session Transfer Token organization mismatch detected.`                                          | El parámetro `organization` de la solicitud `/authorize` no coincide con la organización del token de transferencia de sesión.                     |
| `Single Sign-On failed: Session Transfer Token user mismatch detected.`                                                  | Una sesión de Auth0 ya existente pertenece a un usuario distinto del token de transferencia de sesión.                                             |
| `Single Sign-On failed: Parent refresh token not found. Session Transfer Token won't be used for session establishment.` | El token de actualización principal usado para crear el token de transferencia de sesión fue revocado o eliminado.                                 |
