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

> Describe cómo usar tu servidor de backend para autenticar una aplicación de página única (SPA) con cookies.

# Autenticar aplicaciones de página única con cookies

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

export const codeExample = `ISSUER_BASE_URL="{yourDomain}"
CLIENT_ID="{yourClientId}"
BASE_URL="http://localhost:3000"
APP_SESSION_SECRET="<TU VALOR SECRETO>"`;

Proteger una aplicación de página única (SPA) puede ser un desafío. Sin embargo, si tu SPA cumple los siguientes criterios, puedes simplificar la implementación usando cookies para la autenticación.

* Se sirve al cliente mediante tu propio backend.
* Tiene el mismo dominio que tu backend.
* Hace llamadas a la API de tu backend que requieren autenticación.

Aquí tienes una descripción de este enfoque, así como una implementación de ejemplo con [Node.js](https://nodejs.org/en/).

<div id="how-it-works">
  ## Cómo funciona
</div>

Los pasos a continuación muestran cómo se recuperan y utilizan los tokens. En este enfoque, se usa [Implicit Flow with Form Post](/es/docs/get-started/authentication-and-authorization-flow/implicit-flow-with-form-post) en lugar de un [Authorization Code Flow with Proof Key for Code Exchange](/es/docs/get-started/authentication-and-authorization-flow/authorization-code-flow-with-pkce) tradicional. Esto se debe a que Form Post Response Mode es una forma más sencilla de implementar el inicio de sesión cuando se solicita acceso a un recurso propio.

<Frame>
  <img src="https://mintcdn.com/translations/c0RQ9V0YAcT0-8l5/docs/images/cdy7uua7fh8z/7suPpG6SuHuCOFHeFmE21T/1bf0a56fd21f65460cff7fd01b4c93f4/2023-09-22_13-21-34.png?fit=max&auto=format&n=c0RQ9V0YAcT0-8l5&q=85&s=fbf81643a02408d39a41f7cb09db539c" alt="Autenticar aplicaciones de página única mediante cookies: diagrama de cómo funciona, parte 1" width="430" height="379" data-path="docs/images/cdy7uua7fh8z/7suPpG6SuHuCOFHeFmE21T/1bf0a56fd21f65460cff7fd01b4c93f4/2023-09-22_13-21-34.png" />
</Frame>

1. El usuario accede a una ruta protegida desde el navegador o realiza alguna acción que requiere iniciar un paso de autenticación (como hacer clic en un botón de inicio de sesión)
2. El cliente del navegador redirige a una ruta `/login` en el backend o a la ruta protegida, según lo que haya hecho el usuario
3. El backend construye una solicitud al endpoint `/authorize` del Servidor de autorización y redirige allí al cliente del navegador
4. Se pide al usuario que se autentique con el método que presente el Servidor de autorización
5. El Servidor de autorización envía los tokens mediante POST al URI de redirección como un formulario codificado en URL. El backend puede recuperar esos tokens analizando los datos del cuerpo.

En este punto, el usuario ya está autenticado y el backend tiene los tokens necesarios. Ahora se puede crear una cookie para representar este estado en el cliente. Luego, el navegador del cliente se redirige a una ruta que sirve la SPA y que también recibe la cookie de autenticación.

A partir de este momento, esta cookie se intercambia entre el cliente y el backend cuando se realizan llamadas a la API mediante AJAX. En cada solicitud, el backend verifica si la cookie sigue siendo válida y, de ser así, permite que la solicitud continúe.

<Frame>
  <img src="https://mintcdn.com/translations/6GE5Z24GDCZehiJ9/docs/images/cdy7uua7fh8z/6SCp9KwQkwJV7L26TOuxIO/d625575a43d00a00fcf17c7310ac2bc8/2023-09-22_13-21-50.png?fit=max&auto=format&n=6GE5Z24GDCZehiJ9&q=85&s=b88900ca48b64d047b7d46237dc0cf2d" alt="Autenticar aplicaciones de página única mediante cookies: diagrama de cómo funciona, parte 2" width="747" height="346" data-path="docs/images/cdy7uua7fh8z/6SCp9KwQkwJV7L26TOuxIO/d625575a43d00a00fcf17c7310ac2bc8/2023-09-22_13-21-50.png" />
</Frame>

<div id="invalid-or-missing-cookies">
  ### Cookies inválidas o ausentes
</div>

Al implementar este enfoque, deberá controlar los casos en los que la cookie de autenticación no sea válida o falte. La llamada del cliente a la API del backend se realiza en segundo plano, por lo que el cliente debe gestionar cualquier respuesta del servidor que indique que el usuario debe volver a autenticarse.

En la siguiente aplicación de ejemplo, este caso se gestiona de forma rudimentaria: se solicita al usuario que vuelva a autenticarse si la llamada a la API da como resultado una respuesta 302 Redirect. El 302 se produce porque, si la validación de la cookie no se realiza correctamente, el servidor intenta redirigir al endpoint de autorización del <Tooltip tip="Servidor de autorización: servidor centralizado que ayuda a definir los límites del acceso de un usuario. Por ejemplo, su servidor de autorización puede controlar los datos, las tareas y las funciones disponibles para un usuario." cta="Ver glosario" href="/es/docs/glossary?term=authorization+server">servidor de autorización</Tooltip> y envía esta respuesta al cliente.

<div id="example">
  ## Ejemplo
</div>

La aplicación de ejemplo utiliza Node.js y Express para demostrar los conceptos tratados anteriormente.

<div id="prerequisites">
  ### Requisitos previos
</div>

* Para seguir este tutorial, asegúrate de tener instalada la [última versión de Node](https://nodejs.org/en/download/).
* Una vez instalado Node, [descarga o clona el código fuente](https://github.com/auth0-blog/spa-cookie-demo/) y abre la carpeta del proyecto en una ventana de terminal.

  ```bash lines theme={null}
  # Clona el repositorio del tutorial mediante SSH
  git clone git@github.com:auth0-blog/spa-cookie-demo
  # ... o, si usas HTTPS:
  git clone https://github.com/auth0-blog/spa-cookie-demo.git
  # Ve al directorio del proyecto
  cd spa-cookie-demo
  ```
* La rama `master` representa el estado de la aplicación antes de añadir cualquier método de autenticación. Si quieres consultar la versión final de la aplicación, cambia a la rama `with-oidc`:
  `git checkout with-oidc`

<div id="initialize-the-nodejs-app">
  ### Inicializa la aplicación de Node.js
</div>

Instala las dependencias de la aplicación ejecutando `npm install` desde la terminal. Para ejecutar la aplicación, usa `npm run dev`. Este comando inicia el servidor Express. Ve a [http://localhost:3000](http://localhost:3000/) en tu navegador para ver la aplicación.

El servidor de desarrollo usa `nodemon`, que se reinicia automáticamente cada vez que detecta cambios en algún archivo.

<div id="explore-the-application">
  ### Explora la aplicación
</div>

Con la aplicación abierta en [http://localhost:3000](http://localhost:3000/), haz clic en el botón **Call API**. Deberías ver un mensaje en la pantalla.

<Frame>
  <img src="https://mintcdn.com/translations/c0RQ9V0YAcT0-8l5/docs/images/cdy7uua7fh8z/7JhdgzFLig2xcDle7ziiGp/c1db6272d20d4a291ba90a6968460109/image3.png?fit=max&auto=format&n=c0RQ9V0YAcT0-8l5&q=85&s=162359e67c515f737bfb5bcee4676480" alt="Pantalla Explora la aplicación de SPA Authentication with Cookies" width="937" height="677" data-path="docs/images/cdy7uua7fh8z/7JhdgzFLig2xcDle7ziiGp/c1db6272d20d4a291ba90a6968460109/image3.png" />
</Frame>

Ten en cuenta que pudiste hacer la llamada a la API sin haber iniciado sesión. Vamos a corregirlo agregando middleware que exija que el usuario se autentique antes de poder realizar la llamada a la API.

<div id="set-up-environment">
  ### Configurar el entorno
</div>

Para que la aplicación funcione con autenticación, `express-openid-connect` requiere algunas variables de entorno. En esta aplicación, estas variables pueden especificarse en un archivo `.env`. Cree un archivo `.env` en la raíz del directorio del proyecto y complételo con lo siguiente:

```shell .env lines theme={null}
ISSUER_BASE_URL="<YOUR OIDC URL>"
CLIENT_ID="<YOUR OIDC CLIENT ID>"
BASE_URL="http://localhost:3000"
APP_SESSION_SECRET="<YOUR SECRET VALUE>"
```

<div id="set-up-app-in-auth0">
  ### Configura la aplicación en Auth0
</div>

1. Ve a [Dashboard > Applications > Applications](https://manage.auth0.com/#/applications) y haz clic en **Create Application**.
2. Asigna un nombre a la nueva aplicación, selecciona **Regular Web Applications** y haz clic en **Create**
3. En **Settings** de la nueva aplicación, agrega `http:/localhost:3000/callback` a **Allowed Callback URLs**.
4. Agrega `http:/localhost:3000` a **Allowed Logout URLs**.
5. Haz clic en **Save Changes**.
6. Ve a [Dashboard > Authentication > Social](https://manage.auth0.com/#/connections/social) y configura algunas conexiones sociales. Habilítalas para la aplicación en las opciones de **Application** de la pestaña **Connections**. En el ejemplo se usan una base de datos de username/password, Facebook, Google y X.
7. En la pantalla **Settings**, toma nota del dominio y del ID de cliente que aparecen en la parte superior.
8. Hay dos valores que debes configurar como parte de la aplicación. Vuelve a abrir el archivo `.env` y establece estos valores:

   <AuthCodeBlock children={codeExample} language="shell" filename=".env" />

<div id="run-the-app">
  ### Ejecuta la aplicación
</div>

1. Con la configuración del servidor y del entorno completada, busca la ventana del navegador donde tienes abierta la aplicación. Si has cerrado el navegador y detenido el servidor, ejecuta lo siguiente en la terminal para reiniciar la aplicación:
   `npm run dev`
2. Abre `http://localhost:3000` en el navegador. En términos de interfaz de usuario, la aplicación debería verse igual; sin embargo, esta vez, cuando hagas clic en el botón **Call API**, deberías recibir una advertencia indicando que el usuario no ha iniciado sesión. Fíjate también en que ya no ves el mensaje "Hello, World" como antes, ya que la llamada a la API ha sido rechazada.
3. Haz clic en **Log in now** para iniciar sesión. Una vez que te hayas autenticado, volverás a la aplicación y verás una interfaz actualizada que refleja tu nuevo estado de inicio de sesión. Deberías poder pulsar el botón **Call API** una vez más para hacer una llamada a la API del servidor, y ahora sí funcionará.
4. Haz clic en el enlace **Profile** en la parte superior de la página para mostrar la información del usuario recuperada del ID Token.

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

* [Flujo implícito con envío mediante formulario](/es/docs/get-started/authentication-and-authorization-flow/implicit-flow-with-form-post)
* [Seguridad](/es/docs/secure)
* [Cambios en el atributo SameSite de las cookies](/es/docs/manage-users/cookies/samesite-cookie-attribute-changes)
