es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Keycloak se comporta como si estuviera sin inicializar después de una actualización de página forzada.

En primer lugar, gracias de antemano a todos los que lean mi pregunta y comentarios. Tengo una aplicación CRA que utiliza keycloak-js y ReactKeycloakProvcer de @react-keycloak/web. Cuando cargas por primera vez la página de la aplicación e inicias sesión, keycloak se inicializa correctamente y funciona como debería. El proveedor obtiene una instancia de KC de una manera bastante estándar.

import keycloak from './authentication/keycloak';

const KeycloakProviderBlock = ({children}) => {
    return (
        <reactkeycloakprovider authclient="{keycloak}" initoptions="{{onLoad:" 'login-required'}}="">
            {children}
        </reactkeycloakprovider>
    );
};

Posteriormente, en mi envoltorio de axios, extraigo el token de KC para agregarlo a todas las solicitudes como el token de portador de esta manera:

import keycloak from "./authentication/keycloak";
const {authenticated} = keycloak;
    if (authenticated) {
        client.defaults.headers.common = {
            ...client.defaults.headers.common,
            Authorization: `Bearer ${keycloak.token}`,
        };
    } else {
        logger.error("Request client used before KeyCloak initialized");
    }

Mi archivo keycloak simplemente devuelve una nueva instancia de KC: contenido de /authentication/keycloak.js

import Keycloak from "keycloak-js";

const keycloak = new Keycloak({
    realm: process.env.REACT_APP_KEYCLOAK_REALM,
    url: process.env.REACT_APP_KEYCLOAK_URL,
    clientId: process.env.REACT_APP_KEYCLOAK_CLIENT,
})

export default keycloak

Todo funciona como debería hasta que el usuario actualiza la página. Cuando la página se recarga, keycloak.authenticated no está presente en el objeto KC, por lo que todas las llamadas HTTP fallan porque no hay un token de portador.

Estoy utilizando la versión 15.0.2 de keycloak-js. Cualquier pensamiento o sugerencia será apreciado.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Parece que el problema que estás experimentando está relacionado con la inicialización de Keycloak en tu aplicación CRA. Cuando el usuario actualiza la página, el objeto KC pierde su estado de autenticación, lo que provoca que todas las llamadas HTTP fallen porque no hay un token de acceso.

    Una posible solución es comprobar si el usuario está autenticado antes de establecer el token de acceso en tu interceptor de axios. Puedes lograr esto agregando una verificación en tu bloque if (authenticated) para ver si el valor de keycloak.token es nulo o indefinido. Si lo es, puedes renovar el token antes de establecerlo en los encabezados.

    Así es como puedes modificar tu envoltorio de axios para implementar esta solución:

    import keycloak from "./authentication/keycloak";
    import axios from "axios";
    import logger from "./logger";
    
    const client = axios.create({
      baseURL: process.env.REACT_APP_API_BASE_URL,
    });
    
    client.interceptors.request.use(
      async (config) => {
        const { authenticated, token } = keycloak;
    
        if (authenticated && token) {
          client.defaults.headers.common = {
            ...client.defaults.headers.common,
            Authorization: `Bearer ${token}`,
          };
        } else if (authenticated && !token) {
          try {
            await keycloak.updateToken();
            const { token: updatedToken } = keycloak;
    
            client.defaults.headers.common = {
              ...client.defaults.headers.common,
              Authorization: `Bearer ${updatedToken}`,
            };
          } catch (error) {
            logger.error(error);
          }
        } else {
          logger.error("Se utilizó el cliente de solicitud antes de la inicialización de KeyCloak");
        }
    
        return config;
      },
      (error) => {
        logger.error(error);
        return Promise.reject(error);
      }
    );
    
    export default client;
    

    En el código modificado anteriormente, agregamos otro bloque if dentro del bloque authenticated para verificar si keycloak.token existe. Si no existe, intentamos renovar el token usando el método updateToken() en keycloak.

    Ten en cuenta que el método updateToken() devuelve una promesa, por lo que debemos usar la palabra clave await al llamarlo. Además, capturar el error del método updateToken() puede brindar la oportunidad de informar al usuario sobre el problema.

    ¡Espero que esta solución funcione para ti!

Comments are closed.