I have a server action that creates records in a Db and sends emails.
If its called directly it create records and send email etc.
Is there a way to stop the Server action file being called directly from the browser?
Is there an “Action” we can add in one of the steps to stop this?
Perhaps the question you want to ask is, how to restrict this Server Action to Admins?
the public page that uses the server action is not a restricted page, hence why I didn’t ask the question in that way. My understanding, unless I am wrong. If I restrict the server action then it can’t be called from a non-restricted page which is used by any users.
I don’t have any user authentication in this projects. It’s a simple form that creates DB records.
If I restricted the Server action, I won’t be able to use it without authentication on the App side
Your understanding is correct.
Well, you could change your Route to only accept POST requests.
This won’t stop malicious users from repeatedly performing the request over and over again, you probably want a captcha or rate limiting (don’t think Wappler supports this officially).
Thanks @Apple how do I change Route to only accept POST requests?
Also, is there maybe a way I can set a condition in the Server Action to continue if a parameter if met, or something along those lines?
You can use a Condition step, and if you want to abort you can use the Response step with an error code like 401 (Unauthorized) or 422 (Unprocessable content)
Or:
Thanks very much @Apple
@cpuser, I think I have managed to achieve what you want in a different way…
I have a public facing page with a group of related server actions. When a member of the public arrives at the page, they arrive with a specific code in the url, and I use this code as a method in one of the server actions to automatically take them through a login process that they don’t know they’ve been through…
After that, all the other server actions that do the kind of db/email actions you describe are protected by the Security Provider mechanism which the first server action created…
I hope that helps!
Antony.
Hi @Antony thank you for the details. Could your please kindly elaborate? It does sound very much like what I am trying to achieve. Can you give an example I can follow?
HI there @cpuser…
Yes, so I have a security provider which has username and password fields taken from the id and a longer random identifier (idr) fields respectively of a database table row.
When the page is accessed, I run a server action page_loaded
which finds that database row from the idr value that was passed in the url, extracts the id value, and passes through a security provider using those two values as username and password.
The security provider passes back a unique identity which is then used in all the other database calls that I make.
I then use the same security provider and security restrict steps at the start of each of the other server actions which access the database and send emails.
The page_loaded server action also needs to check if you are logged in to the security provider at the start and log you out, so you know you are logged in for the correct idr credentials.
I hope that helps!
Antony.
I'm running Node.js, MySQL, Docker:
Is this really an issue? I tried calling my server actions directly from my browser and was unsuccessful in getting any response back. Didn't matter if the server action was for an anonymous user or a logged in user where g_identity is being checked.
Could an example be provided in how someone can successfully call the server action directly and get a response? What misconfigurations in our API's would allows this?
You create a server action with a Set Value step and the Output checkbox checked
The fact you don't see any response from your Server Action might be because you're not supplying the input arguments. It's only possible to apply GET arguments in the browser's URL bar. If you follow good practices then you use POST for server actions that mutate data, and GET for only getting/accessing data.
So, to answer your question, no, it isn't a problem (if you follow good practices)
Thanks Apple. I do have both types of API's of course (GET and POST) and I know a tool like curl can easily make a POST call. My practices are the following:
- Turning off Output as you commented, unless necessary,
- Turning off debug in production to really minimize what's exposed,
- Having g_identity defined in my Globals and referenced with a Security Restrict where necessary
- Obfuscate API names and locations (to a point where the name still makes sense to me)
I'm sure there's plenty more that can be done to improve security. But in my testing after seeing this post, I believe I've at least protected myself from the script kiddies.
Rate limit public requests to your endpoints and increase the rate point limit and count for authenticated Users. Could also consider using Server Connect Routing with token based parameters generated randomly on the fly and stored in the DB, then as you can specify Dynamic content in the routes themselves inject the token in to the endpoint for the API call after using a Condition for confirmation of a match? Use Node JS scheduler to generate them and update every *120 minutes or whatever you set. Hypothetically, if you wanted to... You could also place your API on an alternative host and configure it to only accept from the origin IP of your application (not fail safe but would work)... I'm just chucking out brain-farts though! Silent but violent hahahaha...
Edit:
If the data is that important establish a VPN and assign your Users to it (give them each an account and a key) and only accept connections originating from the VPN to the API. And do the above on-top!
Fortunately the data isn't that sensitive but I love the idea of a true middleware server with whitelisted IP addresses. That would be a goal when the app is ready to move from Wappler to managed hosting PaaS
We do this quite often. It really is one of the benefits of Wappler having Projects able to interact with each-other pretty seamlessly. Very simple two Project set-up. The rest you'll do server side or via something like Cloudflare. Easy enough though!
Ok, now I just realized that the api paths are viewable from within the HTML source in the browser. So no amount of crazy naming convention for API's is going to help at all. I'm still learning all this new stuff (to me) DMX and Bootstrap for examples. There's so much passed to the client from the server, it's very different from the PHP sites I used to build, but I get it.