I have hosted a django rest api on heroku and used the django-cors-headers in it. I have added a few URLs to the CORS whitelist but find that the app is accepting requests from any origin(Ex:- my local PC). And my query is, Why is heroku not blocking my http request even though it is not whitelisted.
Note:- I dont have any front end application running
Below is a snapshot of my settings.py
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'corsheaders',
'rest_framework',
'rest_framework.authtoken',
)
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.middleware.common.BrokenLinkEmailsMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
)
# REST FRAMEWORK
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
# 'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
],
# Use hyperlinked styles by default.
# Only used if the `serializer_class` attribute is not set on a view.
'DEFAULT_MODEL_SERIALIZER_CLASS':
'rest_framework.serializers.HyperlinkedModelSerializer',
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
],
# Make the default renderer class JSON when in production to prevent users from using the browsable API
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
]
}
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR)],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
DATABASES = {'default': dj_database_url.config(default=os.environ["HEROKU_POSTGRESQL_RED_URL"])}
# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
CORS_ORIGIN_ALLOW_ALL = False
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = (
#'localhost:9000',
#'localhost:5000',
#'127.0.0.1:9000',
#'127.0.0.1:5000',
)
CORS_ALLOW_METHODS = (
'GET',
'POST',
'PUT',
'PATCH',
'DELETE',
'OPTIONS'
)
CORS_ALLOW_HEADERS = (
'Access-Control-Allow-Origin',
'x-requested-with',
'content-type',
'accept',
'origin',
'authorization',
'x-csrftoken'
)
I was expecting it to work in the way it would when I use ALLOWED_HOSTS in the settings.py ALLOWED_HOSTS = ['whitelist url']
Please let me know if I missed some setting here.
I think CORS_ALLOW_HEADERS should be like
CORS_ALLOW_HEADERS = (
'x-requested-with',
'content-type',
'accept',
'origin',
'authorization',
'x-csrftoken'
)
You should also add cache-control if you are using any.
Update
What would happen if you hosted the app on external servers and trying to access it locally?
Answer: When your local machine access the internet, it preserves an assigned available IP from ISP. Which means that the external server when got hit from your machine, It will not see it as 127.0.0.1 but it will see it as what appears here https://www.whatismyip.com/.
Solution: To allow cors origin from your local machine, do one of the following,
Add what appears on https://www.whatismyip.com/ to CORS_ORIGIN_WHITELIST. But this means that you will have to edit CORS_ORIGIN_WHITELIST every time you restart your local router. This is beacuse with restarting the local router, ISP will assign you another IP.
For testing purposes only, add '*' to CORS_ORIGIN_WHITELIST.
Try to have another heroku instance to make the requests.