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

> SDK de Auth0 para aplicaciones de una sola página que usan el flujo de código de autorización con PKCE.

# SDK de Auth0 para aplicaciones de una sola página: flujo de código de autorización con PKCE.

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

El SDK de Auth0 para aplicaciones de página única es una nueva biblioteca de JavaScript para implementar autenticación y autorización en aplicaciones de página única (SPA) con Auth0. Proporciona una API de alto nivel y se encarga de muchos de los detalles para que puedas proteger las SPA siguiendo prácticas recomendadas y escribiendo menos código.

El SDK de Auth0 para SPA gestiona los detalles de concesión y del protocolo, la caducidad y renovación de los tokens, así como su almacenamiento y almacenamiento en caché. Internamente, implementa [Universal Login](/es/docs/authenticate/login/auth0-universal-login) y el [flujo de código de autorización con PKCE](/es/docs/get-started/authentication-and-authorization-flow/authorization-code-flow-with-pkce).

La [biblioteca](https://github.com/auth0/auth0-spa-js) y la [documentación de la API](https://auth0.github.io/auth0-spa-js/) están alojadas en GitHub.

Si encuentras algún problema o error al usar el nuevo SDK de JavaScript, [consulta las preguntas frecuentes](https://github.com/auth0/auth0-spa-js/blob/master/FAQ.md) para ver si tu problema se trata allí.

<div id="installation">
  ## Instalación
</div>

Tiene varias opciones para usar el SDK de SPA de Auth0 en su proyecto:

* Desde el CDN: `<script src="https://cdn.auth0.com/js/auth0-spa-js/2.0/auth0-spa-js.production.js"></script>`. Para obtener más información, consulte las [preguntas frecuentes](https://github.com/auth0/auth0-spa-js/blob/main/FAQ.md#how-to-use-from-a-cdn).
* Con [npm](https://npmjs.org): `npm install @auth0/auth0-spa-js`
* Con [yarn](https://yarnpkg.com): `yarn add @auth0/auth0-spa-js`

<div id="getting-started">
  ## Primeros pasos
</div>

<div id="create-the-client">
  ### Crear el cliente
</div>

Primero, debes crear una nueva instancia del objeto cliente `Auth0Client`. Crea la instancia de `Auth0Client` antes de renderizar o inicializar la aplicación. Puedes hacerlo con el método async/await o con promesas. Solo debes crear una instancia del cliente.

Al usar `createAuth0Client`, se hacen automáticamente un par de cosas:

* Se crea una instancia de `Auth0Client`.
* Se llama a `getTokenSilently` para actualizar la sesión del usuario.
* Se suprimen todos los errores de `getTokenSilently`, excepto `login_required`.

<div id="use-asyncawait">
  #### Usa async/await
</div>

export const codeExample1 = `import { createAuth0Client } from '@auth0/auth0-spa-js';

const auth0 = await createAuth0Client({
  domain: '{yourDomain}',
  clientId: '{yourClientId}'
});`;

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

#### Usar promesas

export const codeExample2 = `createAuth0Client({
  domain: '{yourDomain}',
  clientId: '{yourClientId}'
}).then(auth0 => {
  //...
});`;

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

También puede crear el cliente directamente con el constructor `Auth0Client`. Esto puede resultar útil si desea:

* Omitir la llamada a `getTokenSilently` durante la inicialización.
* Implementar un manejo de errores personalizado.
* Inicializar el SDK de forma síncrona.

export const codeExample3 = `import { Auth0Client } from '@auth0/auth0-spa-js';

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

<AuthCodeBlock children={codeExample3} language="jsx" />

<div id="login-and-get-user-info">
  ### Inicie sesión y obtenga información del usuario
</div>

A continuación, cree un botón en el que los usuarios puedan hacer clic para iniciar sesión:

`<button id="login">Click to Login</button>`

Escuche los eventos de clic del botón que creó. Cuando se produzca el evento, use el método de inicio de sesión deseado para autenticar al usuario (`loginWithRedirect()` en este ejemplo). Después de que el usuario se haya autenticado, puede recuperar su perfil con el método `getUser()`.

<div id="use-asyncawait">
  #### Usa async/await
</div>

```jsx lines theme={null}
document.getElementById('login').addEventListener('click', async () => {
  await auth0.loginWithRedirect({
    authorizationParams: {
      redirect_uri: 'http://localhost:3000/'
    }
  });
  //sesión iniciada. puedes obtener el perfil del usuario así:
  const user = await auth0.getUser();
  console.log(user);
});
```

#### Usar promesas

```jsx lines theme={null}
document.getElementById('login').addEventListener('click', () => {
  auth0.loginWithRedirect({
    authorizationParams: {
      redirect_uri: 'http://localhost:3000/'
    }
  }).then(token => {
    //sesión iniciada. puedes obtener el perfil del usuario así:
    auth0.getUser().then(user => {
      console.log(user);
    });
  });
});
```

<div id="call-an-api">
  ### Llamar a una API
</div>

Para llamar a tu API, empieza por obtener el <Tooltip tip="Token de acceso: credencial de autorización, en forma de cadena opaca o JWT, que se utiliza para acceder a una API." cta="Ver glosario" href="/es/docs/glossary?term=Access+Token">Token de acceso</Tooltip> del usuario. Luego, usa el Token de acceso en tu solicitud. En este ejemplo, se utiliza el método `getTokenSilently` para recuperar el Token de acceso:

`<button id="callApi">Llamar a una API</button>`

<div id="use-asyncawait">
  #### Usa async/await
</div>

```jsx lines theme={null}
document.getElementById('callApi').addEventListener('click', async () => {
  const accessToken = await auth0.getTokenSilently();
  const result = await fetch('https://exampleco.com/api', {
    method: 'GET',
    headers: {
      Authorization: 'Bearer ' + accessToken
    }
  });
  const data = await result.json();
  console.log(data);
});
```

<div id="use-promises">
  #### Uso de promesas
</div>

```jsx lines theme={null}
document.getElementById('callApi').addEventListener('click', () => {
  auth0
    .getTokenSilently()
    .then(accessToken =>
      fetch('https://exampleco.com/api', {
        method: 'GET',
        headers: {
          Authorization: 'Bearer ' + accessToken
        }
      })
    )
    .then(result => result.json())
    .then(data => {
      console.log(data);
    });
});
```

<div id="logout">
  ### Cerrar sesión
</div>

Agrega un botón para que los usuarios puedan cerrar sesión:

`<button id="logout">Logout</button>`

```jsx lines theme={null}
$('#logout').click(async () => {
  auth0.logout({
    logoutParams: {
      returnTo: 'http://localhost:3000/'
    }
  });
});
```

<div id="change-storage-options">
  ### Cambiar las opciones de almacenamiento
</div>

De forma predeterminada, SDK de SPA de Auth0 almacena los tokens en memoria. Sin embargo, esto no ofrece persistencia entre recargas de página y entre pestañas del navegador. En su lugar, puede optar por almacenar los tokens en el almacenamiento local configurando la propiedad `cacheLocation` como `localstorage` al inicializar el SDK. Esto puede ayudar a mitigar algunos de los efectos de las tecnologías de privacidad del navegador que impiden el acceso a la cookie de sesión de Auth0 <Tooltip tip="Cookie de sesión: entidad que, cuando está presente, permite considerar al usuario autenticado." cta="Ver glosario" href="/es/docs/glossary?term=session+cookie">cookie de sesión</Tooltip> al almacenar Tokens de acceso durante más tiempo.

<Warning>
  Almacenar tokens en el almacenamiento local del navegador ofrece persistencia entre recargas de página y entre pestañas del navegador. Sin embargo, si un atacante logra ejecutar JavaScript en la SPA mediante un ataque de secuencias de comandos entre sitios (XSS), puede recuperar los tokens almacenados en el almacenamiento local. Una vulnerabilidad que permita un ataque XSS exitoso puede estar tanto en el código fuente de la SPA como en cualquier código JavaScript de terceros (como Bootstrap, jQuery o Google Analytics) incluido en la SPA.

  Obtenga más información sobre el [almacenamiento de tokens](/es/docs/secure/tokens/token-best-practices).
</Warning>

export const codeExample4 = `const auth0 = await createAuth0Client({
  domain: '{yourDomain}',
  clientId: '{yourClientId}',
  cacheLocation: 'localstorage'
});`;

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

<div id="use-rotating-refresh-tokens">
  ### Usar Tokens de actualización rotativos
</div>

El SDK de SPA de Auth0 puede configurarse para usar [Tokens de actualización rotativos](/es/docs/secure/tokens/refresh-tokens/refresh-token-rotation) para obtener nuevos tokens de acceso de forma silenciosa. Estos pueden usarse para sortear las tecnologías de privacidad del navegador que impiden acceder a la cookie de sesión de Auth0 al autenticar de forma silenciosa, además de ofrecer detección de reutilización integrada.

Configure el SDK para ello estableciendo `useRefreshTokens` en `true` durante la inicialización:

export const codeExample5 = `const auth0 = await createAuth0Client({
  domain: '{yourDomain}',
  clientId: '{yourClientId}',
  useRefreshTokens: true
});

// Solicita un nuevo token de acceso con un token de actualización
const token = await auth0.getTokenSilently();`;

<AuthCodeBlock children={codeExample5} language="jsx" />

<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+Tokens">Tokens de actualización</Tooltip> también deberán [configurarse para tu inquilino](/es/docs/secure/tokens/refresh-tokens/configure-refresh-token-rotation) antes de poder usarse en tu SPA.

Una vez configurado, el SDK solicitará el scope `offline_access` durante el proceso de autorización. Además, `getTokenSilently` llamará directamente al endpoint `/oauth/token` para intercambiar tokens de actualización por tokens de acceso.
El SDK respetará la configuración de almacenamiento al guardar los tokens de actualización. Si el SDK se configuró con el mecanismo predeterminado de almacenamiento en memoria, los tokens de actualización se perderán al recargar la página.

<div id="usage">
  ## Uso
</div>

A continuación se muestran ejemplos de uso de varios métodos del SDK. Tenga en cuenta que en estos ejemplos se usa jQuery.

<div id="login-with-redirect">
  ### Inicio de sesión con redirección
</div>

Redirige al endpoint `/authorize` de Auth0 para iniciar el flujo de [Universal Login](/es/docs/authenticate/login/auth0-universal-login):

```jsx lines theme={null}
$('#loginRedirect').click(async () => {
  await auth0.loginWithRedirect({
    authorizationParams: {
      redirect_uri: 'http://localhost:3000/'
    }
  });
});
```

<div id="login-with-popup">
  ### Inicio de sesión con ventana emergente
</div>

Usa una ventana emergente para iniciar sesión mediante la página de <Tooltip tip="Universal Login: Tu aplicación redirige a Universal Login, alojado en el Servidor de autorización de Auth0, para verificar la identidad del usuario." cta="Ver glosario" href="/es/docs/glossary?term=Universal+Login">Universal Login</Tooltip>:

```jsx lines theme={null}
$('#loginPopup').click(async () => {
  await auth0.loginWithPopup();
});
```

Si el usuario tarda más del tiempo de espera predeterminado de 60 segundos en completar el flujo de autenticación, la autenticación se interrumpirá y deberá capturar el error en su código para hacer una de estas dos cosas:

Sugerir que el usuario vuelva a intentarlo y cerrar manualmente la ventana emergente con `error.popup.close`:

```jsx lines theme={null}
$('#loginPopup').click(async () => {
  try {
    await auth0.loginWithPopup();
  } catch {error}
  if (error instanceof auth0.PopupTimeoutError) {
    // lógica personalizada para informar al usuario que reintente
    error.popup.close();
  }
});
```

O bien, cree una opción `popup` personalizada en el objeto `options`:

```jsx lines theme={null}
$('#loginPopup').click(async () => {
  const popup = window.open(
    '',
    'auth0:authorize:popup',
    'left=100,top=100,width=400,height=600,resizable'
  );
  try {
    await auth0.loginWithPopup({ popup });
  } catch {error}
  if (error instanceof auth0.PopupTimeoutError) {
    // lógica personalizada para informar al usuario que reintente
    error.popup.close();
  }
});
```

<div id="login-with-redirect-callback">
  ### Callback de redirección de inicio de sesión
</div>

Cuando el navegador sea redirigido desde Auth0 de vuelta a tu SPA, debes llamar a `handleRedirectCallback` para completar el flujo de inicio de sesión:

```jsx lines theme={null}
$('#loginRedirectCallback').click(async () => {
  await auth0.handleRedirectCallback();
});
```

<div id="get-access-token-with-no-interaction">
  ### Obtener un Token de acceso sin interacción
</div>

Obtenga un nuevo Token de acceso de forma silenciosa mediante un iframe oculto y `prompt=none`, o usando un Token de actualización rotativo. Los Tokens de actualización se usan cuando `useRefreshTokens` se establece en `true` al configurar el SDK.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Obtener un Token de acceso de forma silenciosa sin usar Tokens de actualización no funcionará en navegadores que bloquean las cookies de terceros, como Safari y Brave. Para obtener más información sobre la solución alternativa del dominio personalizado, consulte [Solucionar problemas al renovar tokens cuando se usa Safari](https://support.auth0.com/center/s/article/troubleshoot-auth0-token-renewal-issues-in-safari-with-itp-enabled).
</Callout>

Si se usan el almacenamiento en memoria (el valor predeterminado) y los tokens de actualización, los nuevos tokens se obtienen mediante un web worker en los navegadores compatibles:

```jsx lines theme={null}
$('#getToken').click(async () => {
  const token = await auth0.getTokenSilently();
});
```

El método `getTokenSilently()` requiere que tengas habilitada la opción **Allow Skipping User Consent** en la [configuración de la API del Dashboard](https://manage.auth0.com/#/apis). Además, el consentimiento del usuario [no se puede omitir en 'localhost'](/es/docs/get-started/applications/third-party-applications/user-consent-and-third-party-applications).

<div id="get-access-token-with-popup">
  ### Obtener un Token de acceso con una ventana emergente
</div>

Los Tokens de acceso también se pueden obtener mediante una ventana emergente. A diferencia de `getTokenSilently`, este método para obtener un Token de acceso funciona en navegadores en los que las cookies de terceros están bloqueadas de forma predeterminada:

```jsx lines theme={null}
$('#getTokenPopup').click(async () => {
  const token = await auth0.getTokenWithPopup({
    authorizationParams: {
      audience: 'https://mydomain/api/',
      scope: 'read:rules'
    }
  });
});
```

<div id="get-access-token-for-a-different-audience">
  ### Obtener un Token de acceso para una audiencia distinta
</div>

Puedes pasar opciones a `getTokenSilently` para obtener un Token de acceso con una <Tooltip tip="Audiencia: identificador único de la audiencia de un token emitido. En un token, se denomina aud y su valor contiene el ID de una aplicación (ID de cliente) para un ID Token o de una API (Identificador de API) para un Token de acceso." cta="Ver glosario" href="/es/docs/glossary?term=audience">audiencia</Tooltip> y un scope distintos de los solicitados en el momento de la autenticación del usuario.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Esto solo funciona cuando no se usan Tokens de actualización (`useRefreshTokens: false`), ya que un Token de actualización está vinculado a la audiencia y al scope específicos que se solicitaron en el momento de la autenticación del usuario.
</Callout>

```jsx lines theme={null}
$('#getToken_audience').click(async () => {
  const differentAudienceOptions = {
    authorizationParams: {
      audience: 'https://mydomain/another-api/',
      scope: 'read:rules',
      redirect_uri: 'http://localhost:3000/callback.html'
    }
  };
  const token = await auth0.getTokenSilently(differentAudienceOptions);
});
```

<div id="get-user">
  ### Obtener el usuario
</div>

Puede obtener los datos del perfil del usuario autenticado mediante una llamada al método `getUser`:

```jsx lines theme={null}
$('#getUser').click(async () => {
  const user = await auth0.getUser();
});
```

<div id="get-id-token-claims">
  ### Obtener los claims del ID Token
</div>

Puedes obtener los claims del <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> del usuario autenticado mediante el método `getIdTokenClaims`:

```jsx lines theme={null}
$('#getIdTokenClaims').click(async () => {
  const claims = await auth0.getIdTokenClaims();
  // si necesitas el id_token sin procesar, puedes acceder a él
  // usando la propiedad __raw
  const id_token = claims.__raw;
});
```

<div id="logout-default">
  ### Cerrar sesión (predeterminado)
</div>

Puede iniciar el cierre de sesión llamando al método `logout`:

```jsx lines theme={null}
$('#logout').click(async () => {
  auth0.logout({
    logoutParams: {
      returnTo: 'http://localhost:3000/'
    }
  });
});
```

<div id="logout-with-no-client-id">
  ### Cerrar sesión sin ID de cliente
</div>

Puede iniciar el cierre de sesión sin especificar un <Tooltip tip="ID de cliente: valor de identificación asignado a su recurso registrado por Auth0." cta="Ver glosario" href="/es/docs/glossary?term=Client+ID">ID de cliente</Tooltip> llamando al método `logout` e incluyendo `clientId: null`:

```jsx lines theme={null}
$('#logoutNoClientId').click(async () => {
  auth0.logout({
    clientId: null,
    logoutParams: {
      returnTo: 'http://localhost:3000/'
    }
  });
});
```

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

* [Validar tokens de acceso](/es/docs/secure/tokens/access-tokens/validate-access-tokens)
