Proxying API requests to avoid exposing sensitive data

Retool is an absolute game-changer and I'm completely obsessed with it – I think it's the most flexible of the comparable tools on the market at the moment that doesn't compromise on its UI. That said, I am concerned about the risk of unwittingly exposing the data in my third-party systems when integrating with them, particularly when using the new public Embed functionality.

Although Retool proxies requests server-side to avoid exposing API keys etc., it doesn't seem to allow you to limit what data is returned to the browser in response to a request.

As an example to demonstrate the issue, if I wanted a customer to be able to look up an order via a Retool app, I could do the following:

  1. Include a 'Review order' link in their confirmation email with an autopopulated 'order_no' query parameter in the URL
  2. Use this order number to make a request to my database API and get the details of the order
  3. Display the returned order details to the user

However, with this approach the user could technically amend the order number in the URL and get the details for other customers' orders.

If I was building this outside of Retool I'd include some kind of validation in the server-side service that's proxying the requests to the API, e.g. validating that an email address or customer number passed also match that of the order number requested. However, there doesn't seem to be a mechanism in Retool to validate, server-side, that the user should be able to access that order's details, or indeed to limit the data that's returned from the API to exclude any sensitive data from being passed to the browser.

Does anyone have any workarounds for this? The only one I can think of is to build my own proxy API, but I think that would likely end up taking longer than to use an alternative tool like Bubble (which does support adding request logic and transforming responses server-side).

Hi, welcome,

You need something to limit your query to the database api with some customer identifier.
Maybe a unique (difficult to guess) identifier is already present in your database?
Then pass the identifier also to the app using the url?

like https://url/?orderno=12344&customer=9238383944

then in your query to your database (api) select order from orders where orderno = {{orderno}} and customer = {{customer}}

Or if possible you could add a UUID v4 to your database for each order.
Or you can create as separate database table (in retool database) with some mapping between orderno and UUID v4, eg:

orderno | UUID
12344 | 851efe33-9052-4c84-a338-0c1a01044c13

Then use the uuid in your url query param and lookup the actual orderno to be used in your database query.

Thanks Marc!

The difficulty is that I'm integrating with a third-party API (rather than one I've built myself) – specifically with a product called TicketTailor that we use to manage our event ticketing (Ticket Tailor API v1.0). Somewhat annoyingly in this case it returns quite a bit of sensitive customer data that we don't want to expose to those using our Retool apps.

Do you reckon the only solution is to proxy requests to the TicketTailor API through an API that I build myself? I was hoping there might be a way of customising the server-side logic of the Retool function that actually makes the request to reformat the response and limit what data makes it back to the browser from the third-party API, but looks like that isn't an option at the moment. Hopefully it's on the roadmap? :crossed_fingers:

I don't think that the data is being returned by the API is your concern, but more the way how data is being requested. If you're using a single url param that can easily be guessed or changed, then there is for Retool now way to determine whether the user is allowed to fetch that data. You'll have to include more criteria like customer ID to limit the user requests.
Or use identifiers that are more difficult/less likely to be guessed.

But if I want to make a request to get a user's order, the only parameter that the TicketTailor API accepts is the order_id: Ticket Tailor API v1.0

If I make that request from my Retool apps a user would be able to see the request just by looking at the network logs in their browser dev tools and could in theory then make the request again manually with other order numbers to return other customers' information. Unless I'm missing a step?

No, they won't be able to make a request is made from the retool backend, not from the client (user computer) itself. The user will only see a call to the retool backend, quering a resources. The backend will (should) only accept calls from the retool fronted, not from other sources. I assume that CORS is in place in Retool backend.

Als the API requires an API key which is sent in the header and encrypted using SSL, so even if they would be able to intercept the call from the retool backend to the ticket tailor API server, they wouldn't be able to see what's in the call.

However, being able to change orderID in the url you're sending by e-mail, that's your concern.

It doesn't seem that the Ticket Tailor api is meant to be used this way by other people than the owner of the subscription. So you'll have to apply some kind of authorization.

You could trigger a JS query on succes of the tickettailor call and verify if the e-mail address of the user (add it also in the url as param) equals buyer_details.email in the JSON response. If so, display the data, otherwise drop the result and show an error.

Just tried copying the Retool request from the Network tab in Chrome Dev Tools and was able to change the order_no parameter and get all the data back for other orders, so unfortunately they can.

Essentially any request made via Retool to a third-party API will expose that endpoint to the client, allowing a user to make their own requests for any other data that is accessible via that endpoint – the Retool server essentially acts as a proxy that helpfully (or unhelpfully, in my case) authenticates the requests so that the user doesn't have to :grimacing:

Hi!

You’re right that this is tricky to do securely in Retool today. For now, you can use a workflow to connect to your API directly and then filter/transform the response in the Workflows backend.

We’re working on a feature that will make this much easier and allow you to both securely block unauthorized queries and limit the data that is returned to the frontend on the server-side. Our goal is to make it easier to build use-cases like this securely in Retool.

We reached out over email as well but would love to find some time to chat and get you early access to this when it’s available!

1 Like

Hey Houlton, that's awesome!

For some silly reason I didn't take a proper look at Workflows – I think I'd assumed there wouldn't be the option to return any data to the client when you trigger a Workflow, but that's great to know.

Will follow-up with you on email. Thanks!