It's a bit tricky to understand. Your example is not unsafe in itself, although it's a very bad practice, unnecessary and can likely lead to security issues.
In your example, you're using YOUR_SERVER_SECRET_KEY_DO_NOT_EXPOSE_THIS_EVER
, which, I assume, is either gonna be a server
or admin
role secret key.

There are a few things to understand:
- Your
FAUNA_SECRET_COOKIE
cookie cannot be accessed from the browser because it uses httpOnly: true
, which makes it readable from the server only. Thus, the secret cannot be accessed by anyone, but only by you.
- Storing server/admin role secret key in a cookie is a very bad practice, even though it uses a httpOnly cookie, if you send this to the browser then this secret can be used to do about anything on your fauna database, it grants too much permissions.
Although, sending a Fauna token in the browser (stored in a httpOnly
cookie) is not necessarily unsafe, but it mostly comes down to what role that token grants (and what permissions comes with it).
What most online examples fail to explain thoroughly is that you should only provide secret tokens to the browser if those tokens have a limited set of permissions. And this usually require creating custom roles, like the Public
role above-mentioned in the screenshot.
Taking a real-world example based on https://github.com/Vadorequest/rwa-faunadb-reaflow-nextjs-magic (I'm the author), you can see a demo of the app at https://rwa-faunadb-reaflow-nextjs-magic.vercel.app/.
On this app, there is a Fauna secret key associated to the Public
role that is available in the browser for everyone who accesses the app. This is not unsafe, because the permissions associated to that role are very limited. You can see them here. (they basically allow to read/write one document of id=1
, nothing else)
This is one example of a secure, yet shared token.
Another example (from the same app) is when a user authenticates, when doing so, he gains a new token that is then stored in a httpOnly cookie (same as your example). This token is not related to a role, but to a document instead.
The document is the "User" that's been authenticated, and this is handled through another custom Role "Editor". The role is configured with a restrictive set of permissions, basically allowing the token to only read the User itself, and documents that have ownerId
set to the user id.
To sum it up:
- If someone were to "steal" the
Public
token (it's hardcoded in the browser and very easy to retrieve), they could only perform a very limited set of operations, it is safe.
- If someone were to steal a user's token (which is not straightforward, because it's not stored on the browser, although possible because it's sent to the browser), they could only impersonate that particular user. Also, the token as a 7h TTL, so it'll be automatically invalidated 7h after being generated.