Do I need a backend API between FaunaDB and my app? What are the use cases of an API?

Hello.

I noticed some front-end apps just query fauna directly without querying an api at all.
How good this is? Can someone bring use cases that I’ll probably need an api in the middle?

Tks.

1 Like

I started with full API then I realised I don’t need it for almost all cases except those which has to be rate-limited because they are not protected by auth, eg. login, sign up, etc.

Using Fauna directly from browser makes your app really fast, 48ms for queries is super awesome. To not bloat client code, I am using UDFs.

I am still using middle API, but only for rare cases, like queues, email sending, etc.

1 Like

Use cases for using an API in between FaunaDB and your app

  • httpOnly cookies which adds security (see later on whether it’s necessary or not)
  • Extra monitoring
  • If you want something like IP-based rate-limiting
  • If you’d like to implement some logic in your backend (although most if not all logic can be implemented in FQL and it’s imho a good idea to have your logic close to the data (some people don’t like that idea).
  • Being in control, some programmers just want more control and see everything passing their servers.

Clarification on the security implications of httpOnly

Since I mentioned httpOnly cookies, it makes sense that we also explain the extra advantage that brings and the different approaches. There are many ways to store keys in memory.

  • local storage
    vulnerable to XSS

  • regular cookies
    vulnerable to CSRF and cookies could be read by the client making them also vulnerable by XSS. It’s much more nuanced than that though, a good explanation on this.

  • in memory (in a JavaScript variable)
    vulnerable to XSS … but this is actually safer than localstorage and regular cookies, and that security is indeed security by obfuscation which is questionable (yet often still a good idea). The idea here is that an automatic attack that briefly gets in and quickly copies over your cookies or localstorage content will not have any success. If it’s a manual attack he’ll have to do a significant effort before he finds an in-memory secret compared to localstorage or cookies which are, of course, easy to find. However, in memory is annoying since it logs you out on each refresh!

  • httpOnly cookies
    Protected from XSS, vulnerable to CSRF (but there are other ways to protect against that)
    Cookies that can’t be read from JavaScript (if your browser supports it and handles it correctly, there are always some subtle security things you have to know). These require a backend for the endpoints where you want to use the data that is stored in the cookie. Which is logical since the whole point is that JS can’t access this data.

Option 1: full backend with edge serverless

HttpOnly cookies are your best bet but it indeed requires a backend and that costs latency and/or you have to set up this backend multi-region since you don’t want to lose the multi-region and low latency aspects of FaunaDB. You can do a full API with Cloudflare Workers, (check the edge ones here) for example which would add only 10-20ms.

*** > Example incoming (still needs a bit of time though)!***

Option 2: backend for only auth

If only auth is behind a non multi-region approach then we actually might not care that much about the latency of the auth. If everything once you logged in runs smoothly. Here the idea is that we store the most sensitive data (the refresh token), in the httpOnly cookie and the token that can cause the least harm (because it’s shorter lived) in memory. You have to realise that if some malicious code is able to access your JavaScript variables, that you have a problem (this should never be the case)! This approach mitigates this problem if it does happen by making sure that the tokens that this code could access are short-lived. Meaning that the harm they can do is limited in time. The most powerful token (refresh token) that could give you more long-term access can’t be accessed from the frontend.

  • short-lived token in memory Make a very short-lived token that you will use to access FaunaDB from JavaScript (stored in memory)

  • refresh token in httpOnly cookie Make a refresh token that is stored in an ecrypted httpOnly cookie which you will use to refresh the access token once it’s too old or when a user refreshes. Make sure to also refresh the refresh token since it adds some security e.g. if you get two times the same security token, you know that someone stole it. It’s good to notice that CSRF is less of an issue since you won’t use the cookie for manipulations of your data.

*** > Example incoming!***

Option 3: all in memory.

You will require your user to log in again on each refresh and should not make the tokens too long-lived. I would personally not advice this approach if you are building a serious production app. It’s also not great from a UX perspective that the user has to log in all the time (which is not an issue in option 2)

*** > Example incoming!***

What code could potentially access my in-memory secret?

Malicious code, injected in your app (XSS)

The real potential harm when storing secrets in JavaScript memory would come from malicious code that was somehow injected in your application (via injection, via a malicious library that was included), basically XSS, if you are interested in the prevention rules, check this.

Browser Extensions? Normally not

I am definitely not a security expert but the answer is more subtle. As far as I know, extensions do not get access to your app code.

A malicious extension could (if it has those permissions) however monitor your dom so it would never be a good idea to store that secret in your dom.

Make sure to verify other sources about such security questions. According to Google Chrome’s information:

Link on extensions and isolation
“Content scripts live in an isolated world, allowing a content script to makes changes to its JavaScript environment without conflicting with the page or additional content scripts.”

IFrames? In theory not a risk

Iframes are protected via the same-origin policy. Iframes can access the parent window via window.parent if they are on the same domain (which hopefully is not the case for an iframe with malicious code, else you have a bigger problem)

Fun fact is that you can even use iFrames like this to your advantage to secure frontend variables: https://pragmaticwebsecurity.com/files/cheatsheets/browsersecrets.pdf
It’s relatively complex to implement and get right though.

Link on iframes and cross-window communication
“otherwise, if it comes from another origin, then we can’t access the content of that window: variables, document, anything. The only exception is location : we can change it (thus redirecting the user). But we cannot read location (so we can’t see where the user is now, no information leak).”

!!! Feel free to correct me or ask further questions, security is important and understanding the implications should be a collaborative effort !!!

4 Likes

Cookies are definitely more secure than localStorage.

I’m not a security expert by any means but my understanding is that with these options the only way to steal a cookie would be with physical access to the machine:

  • httpOnly: JavaScript can’t access the cookie.
  • sameSite: The browser will only send the cookie to the same domain that set the cookie. This prevents CSRF attacks which basically consist in making a request to a third party site and read the cookie on that request.
  • secure: cookies are only sent via HTTPS preventing man-in-the-middle type of attacks.

Unfortunately this means that at least some part of the logic has to live in a server.

Another point to be mentioned is that, depending on your use case, if you query Fauna from your clients you might need some business logic in each of your clients. This logic would have to be maintained across different platforms (web, iOS, Android, C#, etc). I guess this can be alleviated by using custom functions but personally in that situation I’d rather keep my clients as agnostic as possible and just use an API.

1 Like

Great addition @pier, things I should have added.
One addition though. We shouldn’t say that cookies are more secure than localstorage. I’m sure that you are aware but for people not being aware of it reading this. Each have diffferent vulnerabilities. If you take the right measures though you can get achieve a higher level of security with cookies.

  • Cookies open you up to CSRF attacks, but other measures can be taken to protect you against CSRF. These attacks are only relevant if you do updates (e.g.making money transfers). In the case where we use cookies in a partial backend (only auth) the worst that can happen is that someone refreshes the token on your behalf (but he will not get access to it!). If you use cookies and have everything behind a backend and use cookies for every call, be vigilant and protect yourself against CSRF.
  • Both Localstorage as Cookies can be accessed from JavaScript which makes them vulnerable for XSS. Setting httpOnly prevents that.

Exactly, but as I mentioned this is avoided by using the sameSite cookie option.

The link you posted also mentions this:

If the user is logged in to the vulnerable web site, their browser will automatically include their session cookie in the request (assuming SameSite cookies are not being used).

FYI Chromium will only accept cookies without the sameSite attribute over HTTPS in an upcoming version.

In contrast any JavaScript running in your application can access LocalStorage.

This wouldn’t be too bad if one had total control over the JavaScript being executed, but in this day and age it’s very common to use dozens if not hundreds of NPM dependencies client-side. And we’ve seen hacked NPM packages mining bitcoins for example.

I agree this is rare though and it will greatly depend on the use case.

1 Like

Good points, in some special cases of applications it might even happen with sameSite if I’m not mistaking, these kind of apps are rare though. E.g. the type of applications where users can customize pages (with HTML) which is not decently sanitised and share this with other users via a share-link. They could trick someone else in deleting all their data on a different account (abusing their cookie) , I’ve seen that specific vulnerability in a few apps iirc :slight_smile:.

I would definitely avoid local storage as well personally and favor cookies. Just wanted to make sure users also consider the dangerous parts. Interesting discussion in each case :smiley:

1 Like

Good point I totally forgot to mention that!

Non sanitized user input is actually even more dangerous with LocalStorage as cookies can be protected from JavaScript with the httpOnly option.