Authorization tokens in Web Viewer

Hi, I have the following problem. Аpparently the web viewer has some underlying network request that it is executing. Right now I have a React application and I have a Hoops viewer component that has a cadData prop. cadData is a url where you can download a scs file. This is my comopnent:

import React, { useState, useEffect } from "react";
import ModelTree from "./ModelTree";

type Props = {
  cadData: string;
}

const HoopsViewer = ({ cadData }: Props) => {
  const [hwv, setHwv] = useState(null);

  useEffect(() => {
    const script = document.createElement("script");
    script.src = "/js/hoops/hoops_web_viewer.js";
    script.onload = () => initViewer();
    document.body.appendChild(script);
    return () => {
      document.body.removeChild(script);
      hwv?.shutdown();
    };
  }, []);

  const initViewer = () => {
    const hwvInstance = new window.Communicator.WebViewer({
      containerId: "viewer",
      endpointUri: cadData,
    });

    console.log("hwvInstance", hwvInstance);

    try {
      hwvInstance.start();
      setHwv(hwvInstance);
      initNavCube(hwvInstance);
    } catch (error) {
      console.error("Failed to start HWV", error);
    }
  };


  return (
    <div className="flex h-full w-full relative h-screen">
      <div id="viewer" className="absolute top-0 left-0 w-full h-full" />
      <div className="absolute bottom-10 left-1/2 transform -translate-x-1/2 flex items-center">
      </div>
      {hwv && <ModelTree hwv={hwv} />}
    </div>
  );
};

export default HoopsViewer;

All my requests to the server have an authorization token, but now I notice that apparently the viewer also executes a request that returns me a 401 and means that it does not apply the headers.

Is there a way to add authorization headers in the hoops web viewer? For example like this?

    const hwvInstance = new window.Communicator.WebViewer({
        containerId: "viewer",
        endpointUri: cadData,
        // Hypothetical configuration to pass headers
        requestHeaders: {
            Authorization: `Bearer ${authToken}`
        }
    });

Hello @dayana,

The WebViewerConfig class has the property sessionToken. This might be what you are looking for.

Thanks,
Tino

Hi, @tino

Thank you for your reply. I have added the sessionToken to the web viewer config. But still I do not see the Authorization: Bearer ${token} in the headers of the request.

import React, { useState, useEffect } from "react";
import ModelTree from "./ModelTree";

type Props = {
  cadData: string;
}

const HoopsViewer = ({ cadData }: Props) => {
  const [hwv, setHwv] = useState(null);

useEffect(() => {
    const script = document.createElement("script");
    script.src = "/js/hoops/hoops_web_viewer.js";
    document.body.appendChild(script);

    const loadViewer = async () => {
      const authToken = await currentSession();
      if (authToken) {
        initViewer(authToken);
      } else {
        console.error("Failed to retrieve auth token");
      }
    };

    script.onload = loadViewer;

    return () => {
      document.body.removeChild(script);
      hwv?.shutdown();
    };
  }, []);

  const initViewer = (authToken) => {
    const hwvInstance = new window.Communicator.WebViewer({
      containerId: "viewer",
      endpointUri: cadData,
      // Token passed here
      sessionToken: `Bearer ${authToken}`
    });

    try {
      hwvInstance.start();
      setHwv(hwvInstance);
      initNavCube(hwvInstance);
    } catch (error) {
      console.error("Failed to start HWV", error);
    }
  };
  return (
    <div className="flex h-full w-full relative h-screen">
      <div id="viewer" className="absolute top-0 left-0 w-full h-full" />
      <div className="absolute bottom-10 left-1/2 transform -translate-x-1/2 flex items-center">
      </div>
      {hwv && <ModelTree hwv={hwv} />}
    </div>
  );
};

export default HoopsViewer;

Just to clarify the catData prop is actually a url for the control to go to and download the file, maybe this is a better example for you:

  const initViewer = (authToken) => {
    const hwvInstance = new window.Communicator.WebViewer({
      containerId: "viewer",
      endpointUri: `http://localhost:8000/source/demo-file.scs`,
      sessionToken: 'Token 12345',
    });

Thanks for providing additional clarification, @dayana

So I don’t think sessionToken is going to help in this scenario. Additionally, the WebViewer class does not have a comparable parameter for requestHeaders: {"Authorization": Bearer ${authToken}.

Indeed a fetch command is used to retrieve the SCS file. The WebViewer class doesn’t have a direct parameter for the authorization token. I’m not 100% on this :crossed_fingers: – but I think you can try implementing a custom HTTP request (perhaps overriding the fetch function) that includes the necessary headers.

Thanks,
Tino

Hi @tino ,
Thanks for the quick reply. Yes, I would definitely like to try an override fetch. Do you have something in mind? Could you send me an example or at least the methods of this class bound to requests?

Best regards,
Dayana

With the help of ChatGPT for prototyping, this is one potential example (but your mileage may vary):

const initViewer = (authToken) => {
    // Intercept the original fetch function
    const originalFetch = window.fetch;

    // Override the fetch function to include authorization header
    window.fetch = (url, options) => {
        // If the URL matches the one you want to modify, add authorization header
        if (url === 'http://localhost:11180/myStreamCacheFile.scs') {
            options = options || {};
            options.headers = options.headers || new Headers();
            options.headers.append('Authorization', `Bearer ${authToken}`);
        }

        // Call the original fetch function with modified options
        return originalFetch(url, options);
    };

    // Initialize the WebViewer
    const hwvInstance = new window.Communicator.WebViewer({
        containerId: "myViewer",
        endpointUri: `http://localhost:11180/myStreamCacheFile.scs`,
    });

    // Optionally, restore the original fetch function when done
    // window.fetch = originalFetch;
};
1 Like

Hi, @tino

Thanks for the example, with a bit of processing on my part I was able to add the headers. However, overriding the fetch in this way should be careful as it may cause problems with other requests.

Best regards,
Dayana

1 Like