Reputation: 59
I have built a get REST API in python with flask. I am calling this API from my own website and I would like to avoid other websites from using it.
To do that, in the header of the api definition I set
'Access-Control-Allow-Origin' = '****'
being **** the domain of the website allowed to make the call.
Is this enough to avoid others from using my api ?
Upvotes: 4
Views: 7683
Reputation: 13074
I have built a get REST API in python with flask. I am calling this API from my own website and I would like to avoid other websites from using it.
The Robert Putt recommendation to use Flask CORS package is the right one to address this concern, but has himself pointed out this will not stop your API from being used by others, that leads us to your next question, that I will try to address in more detail.
Is this enough to avoid others from using my api?
The short answer is NO, because your API can be consumed in many other ways, like by using Postman, automated scripts or scraped by bots, just to mention a few.
The usual steps to protect an API is the use of secrets in form of tokens, like an API key to identify what is performing the requests, aka a web app or mobile app, and a user authentication token to identify the user doing the request, but both are doomed to be easily extracted from their original scope of use and used instead by attackers in automated scripts or manually in tools like Postman. This is easily done in devices that the attacker as control over, but can also be done with free wifi captive portals running in the laptop of the attacker. When attackers use the free wifi captive portal technique in airports, train/bus stations and other public spaces, they will trick the user into install a custom certificate, that will allow them to decrypt all https connections, thus gaining access to their tokens, thus being able to perform calls to the API server in their behalf and without their knowledge and this will be done while allowing the user to normally browse the site.
So anything that runs on the client side and needs some secret to access an API is doomed to be abused in several ways and you can learn more on this series of articles about mobile api security techniques. This articles will teach you how API Keys, User Access Tokens, HMAC, TLS Pinning can be used to protect the API and how they can be bypassed. The articles are more in the context of an API for a mobile app but they are good to illustrate you why you cannot effectively protect your API in a web app context, you can only make it more difficult.
As a final note I would recommend for your web app to also use the CSP header, that will allow you to setup content security policies with reports of violations in real time.
Upvotes: 2
Reputation: 504
A better way to do CORS in Flask
I would probably use Flask-CORS to add adaptable Cross Origin Resource Sharing capability to your Flask project...
First pip install Flask-CORS:
pip install -U flask-cors
and then implement inside your app instantiation:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
cors = CORS(app, resources={r"/api/*": {"origins": "example.com"}})
This will allow access to that specific route from example.com only and deal with all the headers for you, similar to what Avian advised but in a Flasky kind of way. Of course if you want a specific origin (or indeed any origin) to have access to your full API (or part of your API) you can use wild cards.
Is this enough to avoid others from using my api?
No this will only stop people from accessing your API from some other website / origin using JS. It will not stop people simply directly accessing your API using CuRL or equivalent. If you want to prevent access to your API you should implement some form of token / key auth credentials to authenticate only those users you wish to gain access and return a "Unauthorized" 401 to any users without valid credentials.
Upvotes: 10
Reputation: 126
Yes, make sure you put it in the correct format though.
"Access-Control-Allow-Origin": "https://example.com",
This will only allow requests from example.com.
As to your second question, if anyone else is using or can send request from mydomain.com, then of course they'll be able to use your API. I would highly recommend implementing CSRF protection using Flask-WTF if you're really concerned about others using your API - so no one can forge requests.
Upvotes: 0