0

I'm having 403 Forbidden error after saving or editing elements from Django admin, on Microsoft Edge. I'm logged in as superuser, so I have all the permissions for adding/editing elements through the admin. In fact, the problem is presenting when I successfully add a new element and then I decide to "save and continue editing" or "save and add another". The second modification/creation will always fail with the 403 error. It works well on all the other browsers, just Microsoft Edge fails. Any ideas?

I'm using Django 1.11.7.

Here is an example of my settings.py:

import os
import raven
from core.run_environment import RunEnvironment

gettext = lambda s: s

CURRENT_ENV = RunEnvironment.current_env()

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

SECRET_KEY = ''

DEBUG = CURRENT_ENV == RunEnvironment.LOCAL

ALLOWED_HOSTS = ['127.0.0.1', 'mysite.mydomain.com']

DOMAIN = '.mydomain.com'
CSRF_COOKIE_DOMAIN = DOMAIN
SESSION_COOKIE_DOMAIN = DOMAIN

CSRF_TRUSTED_ORIGINS = ['mysite.mydomain.com', '127.0.0.1']


ADMINS = (
    ('Admin name', 'admin@adminemail.com'),
)
MANAGERS = ADMINS

INSTALLED_APPS = [
    'django.contrib.sites',
    'admintheme',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'accounts',
    'allauth',
    'allauth.account',
    'allauth.socialaccount',
    'raven.contrib.django.raven_compat',
    'ajax_select',
    'mptt',
    'geoposition',
    'adminsortable2',
    'easy_thumbnails',
    'filer',
    'subscriptions',
    'ckeditor',
    'ckeditor_filebrowser_filer',
    'core',
    'hitcount',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'core.middleware.TimezoneMiddleware',
]

ROOT_URLCONF = 'mysite.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        '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',
                'core.context_processors.app_name'
            ],
        },
    },
]

WSGI_APPLICATION = 'mysite.wsgi.application'

SITE_ID = 1

# ======================================================================================================================
# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases
# ======================================================================================================================

CONFIG_DATABASES = {
    RunEnvironment.LIVE: {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': '',
            'USER': '',
            'PASSWORD': '',
            'HOST': '127.0.0.1',
        }
    },
    RunEnvironment.STAGE: {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': '',
            'USER': '',
            'PASSWORD': '',
            'HOST': '127.0.0.1',
        }
    },
    RunEnvironment.LOCAL: {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': '',
            'USER': '',
            'PASSWORD': '',
            'HOST': '127.0.0.1',
        }
    }
}
DATABASES = CONFIG_DATABASES[CURRENT_ENV]


# ======================================================================================================================
# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
# ======================================================================================================================

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# ======================================================================================================================
# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/
# ======================================================================================================================

LANGUAGE_CODE = 'it'
TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

LANGUAGES = (
    ('it', gettext('Italiano')),
    # ('en', gettext('English')),
)

# ======================================================================================================================
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/
# ======================================================================================================================

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, '../static/')

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, '../media/')


# ======================================================================================================================
# Custom Auth
# ======================================================================================================================

AUTH_USER_MODEL = 'accounts.User'


# ======================================================================================================================
# REST Framework
# ======================================================================================================================

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
    ],
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 200,
}


# ======================================================================================================================
# Django Allauth
# ======================================================================================================================

AUTHENTICATION_BACKENDS = (`allauth`
    'django.contrib.auth.backends.ModelBackend',

    'allauth.account.auth_backends.AuthenticationBackend',
)

ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_SIGNUP_PASSWORD_ENTER_TWICE = True

if DEBUG:
    ACCOUNT_EMAIL_SUBJECT_PREFIX = 'DEBUG: MySite.com - '
else:
    ACCOUNT_EMAIL_SUBJECT_PREFIX = 'MySite.com - '

ACCOUNT_LOGOUT_ON_GET = True

ACCOUNT_ADAPTER = 'accounts.adapter.AccountAdapter'

ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION = True
ACCOUNT_CONFIRM_EMAIL_ON_GET = True
ACCOUNT_EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL = '/accounts/email-confirmed/'

ACCOUNT_EMAIL_VERIFICATION = "mandatory"
ACCOUNT_UNIQUE_EMAIL = True

# ======================================================================================================================
# Easy Thumbnails
# ======================================================================================================================

THUMBNAIL_HIGH_RESOLUTION = True

THUMBNAIL_PROCESSORS = (
    'easy_thumbnails.processors.colorspace',
    'easy_thumbnails.processors.autocrop',
    'filer.thumbnail_processors.scale_and_crop_with_subject_location',
    'easy_thumbnails.processors.filters',
)


# ======================================================================================================================
# CKEditor
# ======================================================================================================================

CKEDITOR_CONFIGS = {
    'default': {
        'width': '100%',
        'toolbar': 'Custom',
        'toolbar_Custom': [
            ['Bold', 'Italic', 'Underline'],
            ['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock'],
            ['Link', 'Unlink'],
            # ['FilerImage'],
            ['RemoveFormat', 'Source']
        ],
        'extraPlugins': 'filerimage',
        'removePlugins': 'image'
    },
    'dashboard': {
        'width': '100%',
        'toolbar': 'Custom',
        'toolbar_Custom': [
            ['Bold', 'Italic', 'Underline'],
            ['NumberedList', 'BulletedList'],
            ['RemoveFormat']
        ],
        'removePlugins': 'image'
    },
}


# ======================================================================================================================
# Geoposition
# ======================================================================================================================

GEOPOSITION_GOOGLE_MAPS_API_KEY = ''


# ======================================================================================================================
# Sentry
# ======================================================================================================================

if DEBUG is False:
    RAVEN_CONFIG = {
        'dsn': '',
    }


# ======================================================================================================================
# Django Notifications
# ======================================================================================================================

NOTIFICATIONS_USE_JSONFIELD = True


# ======================================================================================================================
# Celery
# ======================================================================================================================

CELERY_BROKER_URL = ''
CELERY_RESULT_BACKEND = 'rpc://'
CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler'

Django returns the 403 error this way:

Forbidden (403)

You are seeing this message because this HTTPS site requires a 'Referer header' to be sent by your Web browser, but none was sent. This header is required for security reasons, to ensure that your browser is not being hijacked by third parties.

TylerH
  • 20,799
  • 66
  • 75
  • 101
  • It might be a problem related to the CSFR token, can you share the value of `CSRF_COOKIE_DOMAIN` ? – LS_ Sep 10 '18 at 07:50
  • I haven't set any CSRF_COOKIE_DOMAIN in my settings.py. Should I? – Giulia Cecchetti Sep 10 '18 at 08:01
  • Yes try by setting as value the domain hosting the website. Do you receive any other details of the error from the console? – LS_ Sep 10 '18 at 08:17
  • I tried but it doesn't work yet. The console reports the 403 error this way: "HTTP403 Operation not allowed -The server received the request, but denies its execution". I use one subdomain for my website, could this be a problem? In the CSRF_COOKIE_DOMAIN I used the ".toplevel.com" – Giulia Cecchetti Sep 10 '18 at 08:46
  • I think that the configuration for a subdomain is correct, you could try with [this one](https://gist.github.com/makerj/295ea3d2160326694c123bd8db164d9b) which also sets `SESSION_COOKIE_DOMAIN`. Also try to check [this answer](https://stackoverflow.com/a/29574563/3789527) – LS_ Sep 10 '18 at 09:16
  • I've tried everything with no results, it keeps acting the same way. I realized it's not just a problem of the django admin, allover the website two consecutive POST requests (made with form submission) always return 403 error, with Microsoft Edge. I checked the POST request from the console and I'm sure it has both the csrftoken and the sessionid in the header. Also, I discovered I have the same problem with all my django projects, so I suppose I miss something else in the settings.py? I really don't know what to think... – Giulia Cecchetti Sep 10 '18 at 13:13
  • Yes that error sounds like a misconfiguration somewhere. Really weird it happens only using Edge. Can you please add to the question which Django version you're using, an example of settings.py, and an example of the script which sends the POST request? – LS_ Sep 10 '18 at 13:43
  • I updated the post adding my settings.py (I removed all the sensitive information). I also reported the error message Django returns. Is it helpful? – Giulia Cecchetti Sep 11 '18 at 13:10
  • Still on the issue? I found this [answer](https://stackoverflow.com/a/5588435/3789527) which might be helpful. You should try to add that script to your js file and see if it solves the issue. Basically it catches ajax requests and adds a header `X-CSRFToken` with the value of the cookie `csrftoken` before sending them. Not sure if this solves your issue but It might be a cause for the 403 error you're seeing – LS_ Sep 20 '18 at 08:07

0 Answers0