Help Me Understand "use server" Security
I'm new to this topic. So please excuse me if my questions if they're obvious or don't sound well thought out. I'm simply trying to learn.
Let's assume I have an app dashboard. When a user visits that dashboard, I run a createEffect() to check their access status.
Inside that "client-side"
createEffect()
I call a server function getUserRecord()
Here's a simplified example to show logic.
Here's the getUserRecord()
function:
For context, here's the getSupabaseAdminClient()
function:
31 Replies
Here's the question:
Technically, I'm calling the
getUserRecord()
function from the client... which leads me to believe that the getUserRecord()
function is exposed to the client.
Therefore, I'm wondering if it is possible for someone to repeatedly call getUserRecord()
from the client? Can they open Chrome dev tools or hack into something to gain access to getUserRecord()
and run it from the client with different variables?
This might not be a huge concern when I'm reading data, but this could quickly become an issue if exposed a server function that wrote data to my database.
Am I thinking about this correctly?
If so, how do I securely call server function from the client?Therefore, is it possible for someone to repeatedly call getUserRecord() from the clientYes, any
use server
function can be called from the client
Can they open Chrome dev tools or hack into something to gain access to getUserRecord() and run it from the client with different variables?Yes, they'll be able to supply their own
userId
value
If so, how do I securely call server function from the client?Get an auth token into the server function and authenticate the user in there. Whether you do that with cookies or by passing it as an argument is up to you
Ok... if I pass an auth token to my server function, couldn't any hacker just sign up for an account and pass that check?
For the case of
getUserRecord
i assume you'd want it to get the data of the current user, so use the auth token to figure out the user id to use instead of passing it as an argumentOk that makes sense.
What about this:
Take my original logic one step further:
Now I'm exposing
createUserRecord()
to the client.
If this function is exposed to the client, what prevents a hacker from continually writing to my DB?
Would I add a "unique" clause to my user table to prevent multiple rows with the same userId?You'd probably want to make emails unique and personally i'd generate user IDs on the server instead of client
Since signups are a public thing you'll probably want rate limiting at some point
And you'll probably want an email verification step at some point
userId should also be unique though yeah
Boy... apps get complicated the further you go, don't they?
You think you have something all figured out... then you start thinking and realize there's another hole somewhere.
I've got some homework to do.
Last question...
Let's say I'm using a
cache()
and load()
function from the router like this:
Is getOrders()
exposed to the client, even if it's driven by the solid router? I think it is, right?Yes since there's a
use server
there
Solid router has basically no knowledge of server functions, it'll just use what you give itSo a hacker get simply call
getOrders()
can get all of the orders?Yeah
So how do people get order securely?
Auth token
Can you point me in a direction? Where can I read about this?
I assume supabase would have some examples, but the basic premise is that you get the auth token into the function, whether with cookies or as an argument or otherwise, and then make sure the auth token belongs to someone who is an admin
Whether that's by fetching the user info from your database or validatin the auth token itself depends on the implementation
Ok... That's a great start.
Thank you for all of the help with this. I see a full day or two ahead of me.
Have a great night.