Proposed feature to proxy requests through another server, to avoid exposing API key on frontend

Objective:

Hello :wave:

I’m attempting to avoid having my custom FE code which embeds the viewer from needing to know the API key.

Instead, I’ve made some updates to needed helpers to allow requests to be proxies through my server, which will add the API key to the request before sending to speckle’s servers. (Apologies for missing the part in the contribution guide about discussing first :man_facepalming:)

The updates were mainly to UrlHelpers.getResourceUrls and SpeckleLoader to allow for an optional serverUrl to be specified:

      /** Create a loader for the speckle stream */
      const authToken = await currentAuthToken(); // For authenticating with my backend
      const urls = await UrlHelper.getResourceUrls(
        `https://app.speckle.systems/projects/${projectId}/models/${modelId}`,
        { authToken, serverUrl: `${getGraphQLBaseUrl()}/speckle` },
      );
      for (const url of urls) {
        const loader = new SpeckleLoader(viewer.getWorldTree(), url, {
          authToken,
          serverUrl: `${getGraphQLBaseUrl()}/speckle/rest`,
        });
        /** Load the speckle data */
        await viewer.loadObject(loader, true);
      }

I’m curious to get thoughts on the proposed changes (need test cases still), and whether they stand any chance or merging. Also, I feel like this must be an issue others have faced? So perhaps I’m not going about it the optimal way.

The fact that the getResourceUrls function still returns urls with a different origin/path, feels like a code smell, but that was necessary for SpeckleLoader to continue to understand/parse the urls correctly. In particular, the current parsing can’t handle the addition of the extra path fragment /speckle/rest being included in the provided url parameter. Though that could be enhanced if desired. But maybe it is expected and more convenient for me to re-implement these helpers in my code base.

Thank you.

Hi Christopher,

Others haven’t typically encountered this issue, as we generally recommend using OAuth for frontend authentication, especially when handling user data. OAuth securely delegates access without exposing API keys on the frontend and is the preferred approach for most use cases.

Your proposal of using a proxy to route requests may be functionally possible. However, I’d defer to Speckle’s server architects to determine if it’s a worthwhile change to consider in the core server. @Alessandro_Magionami @iainsproat

If you choose to implement a proxy, a few things to keep in mind:
• Ensure the proxy is secured to avoid it becoming an attack vector.
• Be aware of potential added complexity and performance overhead in your application architecture.
• Implement access controls to limit proxy misuse.

Let us know how you’d like to proceed, and we can provide further guidance.

1 Like

Thanks for your thoughts @jonathon. I’ve read up a little on the auth section of the docs.

I believe the app I have planned sort of falls into the Apps that can act with their own identity category, as listed here.

Though, I was planning on making a “user” for the app, which maybe makes it more like the supported case of Apps that act on behalf of a user?

In our use case, most (95+%) users of our software would not know that speckle exists as part of the architecture behind the system, as they would only be viewers of the data via our frontend. They also, would not have speckle accounts with which to perform OAuth.

The only users which would have speckle accounts would be users providing Revit models of houses. Since they would need to use the Revit Speckle Connector and login with their credentials.

Anyway, happy to hear your thoughts on the above, and how many terms of service this proposal violates :laughing:

Your approach doesn’t violate the terms of service. If you create a pull request with your token change, someone with Server expertise can take a look and offer suggestions for improvements or security considerations.

This setup seems pretty specific to your use case and, as far as I can tell, wouldn’t force other Speckle users to set up a proxy—it’s more of an optional approach for cases like yours, where hiding API keys or centralising control is a priority.

That said, proxies can add some complexity:

  • You’ll need to host and maintain extra infrastructure.
  • Security is key—tokens and API interactions need to be handled carefully.
  • The proxy should also stick to Speckle’s OAuth rules (like token expiry and scoping).

While this doesn’t breach any TOS, it might not be something we’d choose to support broadly. If it works best for you, it could just stay in your self-hosted deployment. Otherwise, feel free to open a PR if you think it’s useful for others—I’ll leave the final call to the server architects, as this is where my architectural knowledge starts to thin out.