I have a Wordpress site with users, and a separate Flask app with logic for responding to Get/Post requests from the WordPress site.
I am able to get the current user into a JavaScript variable on the WP site and send to the Flask app - however how do I ensure that someone cannot pretend to be a different current user, or make this secure to other potential vulnerabilities?
Is there some way of exposing a token or suchlike to JavaScript on the WP side, which then the Flask app can verify, say by using the WordPress API?
We would likely need a little bit more detail to be sure the best way to solve, but it seems there are a few ways of approaching this.
You've said that you can get the user id into JavaScript. I'm presuming this means the browser is needing to make the connection to the Flask app. If you have the option of doing this with the WordPress site calling the Flask app directly (server-to-server) you can avoid a lot of hassle.
If you are able to send the request directly from the WordPress server to the Flask app, and the Flask app can check that the source of the request is the WordPress site (either by a shared secret, by checking the IP address the request came from, or just by filtering the traffic to the Flask app to only permit the WordPress server) then do that and you can be sure of the identity of the user making the request.
But if the request has to be made to the Flask app from the browser, then you could do this in a couple of general ways:
Encrypt the value from WP to Flask -- Create a shared secret on the server(s) which is used to encrypt or sign the user id. The WP site would generate the encrypted/signed version of the user id and send that to the browser. The browser javascript code would send this to the Flask app, which would (knowing the shared secret) decrypt the id or verify the signature. This is the simpliest method.
Use an opaque ID -- Generate a random number in the server-side code of the WP site, and record the user id that it was generated for. Send the random number to the browser, which sends it on to the Flask app. Flask then asks WordPress what the user id associated with that random number is.
You need to send the data directly from backend side, but if it depends on a frontend trigger, you can then send an AJAX request from JavaScript to backend in WP side.
jQuery.post( admin_ajax_url, { action: 'get_current_user' } );
and without the nopriv, This function will be triggered only for logged in users.
add_action( 'wp_ajax_get_current_user', 'ajax_get_current_user' );
inside the function, you can get the current user WP_User object and the user ID.
function ajax_get_current_user() {
$current_user_object = wp_get_current_user();
$current_user_id = get_current_user_id();
// Send the User details to flash App here...
}
This is a quick walkthrough of how it should be done. sure, AJAX request will need a nonce check, and sanitization for any passed data, etc.
More details about AJAX request in WP
https://developer.wordpress.org/plugins/javascript/ajax/
https://developer.wordpress.org/plugins/javascript/enqueuing/
https://jackreichert.com/2013/03/24/using-ajax-in-wordpress-development-the-quickstart-guide/
and the WP HTTP API for sending the data to the flask app
https://developer.wordpress.org/plugins/http-api/
You need WordPress Application Passwords. It's essentially a password for APIs.
In your case, you need to define the application password of the WordPress user in Flask, then Flask can send requests to the WordPress REST API as an authenticated user.
Related
New to web development so sorry for the (probably) dumb question
I am building a web app which will need user accounts and verification. I would like to serve several pages (one of which is calendar.html) only if the user is logged in. I created an express endpoint /calendar which will successfully load the page using either ejs or sendFile, but only when the get request is recieved via a URL redirect:
response.render('calendar.ejs')
response.sendFile(path.join(__dirname, '/public/calendar.html'))
The problem is, with a URL redirect eg window.location.href = calendar (I may be wrong here) I cannot send additional information like the user's email address or authentication key in the request header. I would also like to have clean URLs and not encode this data into the URL.
I know how to send these data in a get request using fetch(), however if I do that, the page does not render using either of the above methods. How can I send the credentials to the server, serve back calendar.html and display it, all with a clean URL?
I am creating a JS API that is made to fetch data from my website. To use the API, user is required to include the script in their website html. The API will then display data from my website into their website accordingly. I am using ajax to call the endpoint url of my website.
However, insecurity concern is that, malicious user can create their own API and call the endpoint url.
I was thinking of checking server HTTP_REFERER, getting script id then checking the src of the script. However, the server HTTP_REFERER can be changed programmatically.
Is there a way to prevent user from changing JS script location or checking if the script src has been changed? Or in general, how can I prevent user from using their own script or cURL to call my endpoint url?
I am using PHP LARAVEL as backend language.
I think there is no certain way to prevent this on the client side. It's always right to secure the backend. To authorize users, try using OAuth 2.0; Laravel passport is a good implementation. This will secure your APIs.
I've always use JS framework coupled with a PHP backend on the same server (website in php who use a JS framework like react/vue/angular).
I know how call an API function with axios (from JS to my PHP backend) for insert/select in database. I've a environement file who contains login and password for the database, I use it in PHP.
But I want to make an vue app without integrated it in a webpage PHP. (for convert it in electron and ionic).
So the files are in user disk.
How can I call my own API (ex: http://my-custom-api.test/api/insert_data) without users see a password or another stuff for login himself to my api) => Only my apps are allowed to use API
EDIT: Ok for this step, I use a token system.
But i've one question, a user can be exposed to CSRF attack ? (Client is a electron desktop app or Ionic mobile app). They call my api for execute action with params (form data and token bearer user). It's safe ?
I've made a simple webapp that is going to show some data in a table, which will be updated weekly.
This update it done in the backend with some python code, that scrapes and alters some data, before putting it in a SQLite database.
After doing some reading I learned that to deliver that data to my webapp I should make a API with Flask, that can take that data and deliver it to the JS in my webapp in form of JSON, which then can use the data to populate the table. However, I should secure my API with username and pw. But as its a JS frontend that will retrieve data from the API, there is really no point, as the username and pw will have to be hardcoded into JS, which then can be read by the users. (I think)
Should I expose my API to everyone, or is this not the way to go to be able to use SQLite data as a backend for my webapp? I am fine keeping the API to a GET only.
You are correct, it is pointless for you to secure your API. Securing an API is only needed in certain circumstances.
If you are accessing data that you don't want anybody to see, perhaps through a backend call, then it would make sense to add in some form of security (normally an API key or Authorisation tokens in your request headers).
However, if you are making calls from your front-end (i.e. client side) to a backend API, then there is no point putting additional security there as the user can already see the request and already has access to the data the API is returning - so by securing it you are achieving nothing.
Normally, if the page the user is visiting contains sensitive data that you don't want everyone to see, you would take steps to secure your website instead (for example protecting it with a login for username and password before you can access that page). If you were to take this approach, where the website is protected by username and password, then you can update the API to make sure it does not respond to requests where the user is not authenticated (e.g. by generating a session token or something unique for each logged in user).
If you have a look around on websites that have lots of free data available, you will find they all have front end API calls that are completely unsecured (because it is pointless if the data is already free to access). Some websites do take steps to try to make sure it is their own website that is calling the API, but even then it is a bit pointless as web scrapers can always extract the data from the HTML.
Take a look at this page which outlines authentication headers. This simpler route is to hard code the header info in Flask to make it a little more secure. You could also try the more involved route of reading header info from your db. What's currently working for me to read from postgres db is below so you may modify it slightly for sqlite.
def valid():
headers = request.headers
auth = headers.get("X-Api-Key")
user = User.query.filter_by(apikey=auth).first_or_404()
print('from search of db ',user,'',auth)
return str(user)
As you mentioned, you plan to show a public data - then it can be used even
without authentication. Otherwise I think it can take too much unnecessary time spent on that.
As you have just a simple and single table from database, I believe that you don't need an API. You can just create HTML template and render it with data. Some examples can be found here and few more here.
I have a django app which need to receive post requests from another site using html+javascript.
For example i have mydjangosite.com and smallhtmlsite.com
What i want is : user visit smallhtmlsite.com and fill a form, then he pushing submit button and mydjangosite.com receive request and create objects(form saving models actually).
So i will have a view which will handle this requests. But how can these been done securely?
I have a django app which need to receive post requests from another
site using html+javascript.
You don't have to ! You can build an API instead ;)
You create an API call - small site calls the API of main site. In that situation, the form is handled by a view in small site and the API is called via the server. Check out Django REST Framework.
Note: That solution wouldn't stop you from using AJAX but it would avoid cross domain issues.