Get 403 Forbidden Error, when i use a post method

Hey
I get this error, when i use a post method for register page.

The Error:

Forbidden (403)
CSRF verification failed. Request canceled.

Help
Reason given for failure:

    Origin checking failed - https://subdomain.domain.com does not match any trusted origins.
    
In general, this can occur when there is a genuine Cross Site Request Forgery, or when Django's CSRF mechanism has not been used correctly. For POST forms, you need to ensure:

Your browser is accepting cookies.
The view function passes a request to the template’s render method.
In the template, there is a {% csrf_token%} template tag inside each POST form that targets an internal URL.
If you are not using CsrfViewMiddleware, then you must use csrf_protect on any views that use the csrf_token template tag, as well as those that accept the POST data.
The form has a valid CSRF token. After logging in in another browser tab or hitting the back button after a login, you may need to reload the page with the form, because the token is rotated after a login.
You're seeing the help section of this page because you have DEBUG = True in your Django settings file. Change that to False, and only the initial error message will be displayed.

You can customize this page using the CSRF_FAILURE_VIEW setting.

My views.py

def register_view(request):
    if request.user.is_authenticated:
        return redirect('home:index')
    else:
        form = CreateUserForm()

        if request.method == 'POST':
            form = CreateUserForm(request.POST)
            if form.is_valid():
                form.save()

                messages.success(request, 'Account wurde erstellt')

                return redirect('home:login')

        context = {'form': form}
        return render(request, 'home/page1.html', context) 

My page 1.html

<form action="" method="POST" class="mbr-form form-with-styler mx-auto" data-form-title="Form Name"><input type="hidden" name="email" data-form-email="true" value="O91j1FC0MzSz5LgxPVjfuihgNRgPzecEgljPmrHNqd2EOosmu7rXdscbzJKvCwwCSp7ClbRQRz1j00dCh1UlW4Oqpx1rjtbvjjLokK+Bu0lokWBbduhLGtzBfsTcsRzH">
                    {% csrf_token %}
                    <p class="mbr-text mbr-fonts-style align-center mb-4 display-7">Erstelle dir dein Merkl Konto, um Zugriff zum Portal zu erhalten.<a href="#" class="text-primary"><br></a></p>
                    <div class="dragArea row">
                        <div class="col-lg-12 col-md-12 col-sm-12 form-group mb-3" data-for="name">
                            {% render_field form.username class="form-control" type="username" placeholder="Nutzername" id="phone-form7-b" data-form-field="username"%}
                        </div>
                        <div class="col-lg-12 col-md-12 col-sm-12 form-group mb-3" data-for="email">
                            {% render_field form.email class="form-control" type="email" placeholder="Email" id="phone-form7-b" data-form-field="email"%}
                        </div>
                        <div data-for="phone" class="col-lg-12 col-md-12 col-sm-12 form-group mb-3">
                            {% render_field form.password1 class="form-control" type="password" placeholder="Passwort" id="phone-form7-b" data-form-field="password"%}
                        </div>
                        <div data-for="phone" class="col-lg-12 col-md-12 col-sm-12 form-group mb-3">
                            {% render_field form.password2 class="form-control" type="password" placeholder="Passwort wiederholen" id="phone-form7-b" data-form-field="password"%}
                        </div>
                        <div class="col-auto mbr-section-btn align-center"><button type="submit" class="btn btn-success display-4">Registrieren</button></div>
                        <div class="form-errors">{{form.username.errors}}</div>
                        <div class="form-errors">{{form.email.errors}}</div>
                        <div class="form-errors">{{form.password1.errors}}</div>
                        <div class="form-errors">{{form.password2.errors}}</div>
                    </div>
                </form>

Please help me, thanks!

Do you have other forms on your site that are working? (Or not working?)

What does your deployment environment look like?

Do you have the csrf middware installed?

Is there a reason why you have the action attribute on your form tag?

Yes i have other forms, i have 3 forms.
An i can’t test it if there already not working, because i have to sign in to test it, but the register form don’t work.

And yeah we use middware

And i have the attribute in the form tag.

Here is my settings.py:

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ['IP', 'subdomain.domain.com']
CSRF_TRUSTED_ORIGINS = ['subdomain.domain.com']


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'DruckerSite',
    'widget_tweaks',
]

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',
]

ROOT_URLCONF = 'Portal.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',
            ],
        },
    },
]

WSGI_APPLICATION = 'Portal.wsgi.application'


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

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}


# Password validation
# https://docs.djangoproject.com/en/3.2/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',
    },
]

my forms.py:

from django.forms import ModelForm, Textarea
from django.forms.widgets import DateInput, TextInput
from .models import Entry
from django.contrib.auth import forms
from django.forms.widgets import EmailInput, PasswordInput, TextInput
from django.contrib.auth.models import User
from django.forms.fields import CharField, EmailField
from django.contrib.auth.forms import PasswordResetForm, SetPasswordForm, UserCreationForm

class EntryForm(ModelForm):
    class Meta:
        model = Entry
        fields = ['datum', 'kunde', 'marke', 'modell', 'seriennummer', 'garantieerweiterung', 'service_vertrag', 'toner', 'service_ablauf', 'service_historie', 'bild']
        widgets = {
            'datum': DateInput(attrs={"class": "form-control", "placeholder": "Datum", 'style': 'width: 35%; margin-top: 10px'}),
            'kunde': TextInput(attrs={"class": "form-control", "placeholder": "Kunde", 'style': 'width: 35%; margin-top: 10px', 'required': 'required'}),
            'marke': forms.forms.Select(attrs={"class": "form-control", 'style': 'width: 35%; margin-top: 10px'}),
            'modell': TextInput(attrs={"class": "form-control", "placeholder": "Modell", 'style': 'width: 35%; margin-top: 10px'}),
            'seriennummer': TextInput(attrs={"class": "form-control", "placeholder": "Seriennummer", 'style': 'width: 35%; margin-top: 10px'}),
            'garantieerweiterung': TextInput(attrs={"class": "form-control", "placeholder": "Garantieerweiterung", 'style': 'width: 35%; margin-top: 10px'}),
            'service_vertrag': forms.forms.Select(attrs={"class": "form-control", "placeholder": "Service-Vertrag", 'style': 'width: 35%; margin-top: 10px'}),
            'toner': TextInput(attrs={"class": "form-control", "placeholder": "Toner", 'style': 'width: 35%; margin-top: 10px'}),
            'service_ablauf': DateInput(attrs={"class": "form-control", "placeholder": "Service-Ablauf", 'style': 'width: 35%; margin-top: 10px'}),
            'service_historie': Textarea(attrs={"class": "form-control", "placeholder": "Service-Historie", 'style': 'width: 35%; margin-top: 10px' }),
        }
        labels = {
            'service_ablauf': ('Service-Ablauf'),
            'service_historie': ('Service-Historie'),
            'service_vertrag': ('Service-Vertrag')
        }

class CreateUserForm(UserCreationForm):
    class Meta:
        model = User
        fields = ['username', 'email', 'password1', 'password2']

My views.py:

from django.db.models import query
from django.http.response import Http404
from django.shortcuts import render
from .forms import EntryForm
import string
from django.contrib import messages
from django.contrib.auth.models import User
from django.core.mail import send_mail
from django.shortcuts import get_object_or_404, redirect, render
from django.contrib.auth.decorators import login_required
from django.contrib.auth import authenticate, login, logout, update_session_auth_hash
from .forms import CreateUserForm 
from django.views import generic
from .models import Entry 
from datetime import date, datetime, timedelta

@login_required(login_url='home:login')
def index_view(request):
    username = request.user.username

    today = date.today()
    twomonths = timedelta(days=60)
    pre_yesterday = today + twomonths 
    packet  = Entry.objects.filter(service_ablauf = pre_yesterday)
    for entry in packet:
        kunde = entry.kunde
        id2 = entry.id
        if entry.email_active == True:
            Entry.objects.update(email_active=False)
            print(kunde + " Service läuft ab")
            email = request.user.email
            send_mail(
                'Merkl Portal - Service läuft in kürze ab',
                'Der Service des Kunden ' + kunde + ' läuft in 2 Tagen ab. Informationen zu diesem Eintrag findest du unter https://portal.merkl.it/einträge/' + str(id2),
                '',
            [email],
            fail_silently=False,
)   

    context = {'username': username}
    return render(request, 'home/index.html', context)


def view_400(request):

    return render(request, 'home/400.html')


def view_500(request):

    return render(request, 'home/500.html')    

def view_login(request):

    return render(request, 'home/page2.html')

def view_tickets(request):
    username = request.user.username
    context = {'username': username}
    return render(request, 'home/tickets.html' ,context)


@login_required(login_url='home:login')   
def CreateEntry_View(request):
        username = request.user.username
        if request.method == 'POST':
            form = EntryForm(request.POST, request.FILES)
            if form.is_valid():
                form.save()
            else:
                raise Http404
            return redirect('home:entries')
        else:
            form = EntryForm()
                        
        context= {
            'form': form,
            'username': username

            }
        
        return render(request, 'home/new_entry.html', context)

def login_view(request):
    if request.user.is_authenticated:
        return redirect('home:index')
    else:
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')

            user = authenticate(request, username=username, password=password)

            if user is not None:
                login(request, user)
                return redirect('home:index')
                
            else:
                messages.info(request, 'Username or Password is incorrect')

        return render(request, 'home/page2.html')

@login_required(login_url='home:login')
def logout_view(request):
    logout(request)
    return redirect('home:login')

def register_view(request):
    if request.user.is_authenticated:
        return redirect('home:index')
    else:
        form = CreateUserForm()

        if request.method == 'POST':
            form = CreateUserForm(request.POST)
            if form.is_valid():
                form.save()

                messages.success(request, 'Account wurde erstellt')

                return redirect('home:login')

        context = {'form': form}
        return render(request, 'home/page1.html', context)

See the docs for CSRF_TRUSTED_ORIGINS - those entries are supposed to include the protocol.

Also, how are you running this on the server? What does your deployment environment look like? Apache httpd? nginx? uwsgi? gunicorn? (etc)

I’ll check it out.
We have Nginx with Gunicorn, uwsgi on ubuntu 20.04 with SSL Lets Encrypt Certbot.

Hey

I read through the docs and added the all subdomains to the TRUSTED ORIGINS settings and restarted the server, the error still comes.

My settings.py now:

ALLOWED_HOSTS = ['IP', 'subdomain.domain.com']
CSRF_TRUSTED_ORIGINS = ['http://*.domain.com']

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'DruckerSite',
    'widget_tweaks',
]

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',
]

ROOT_URLCONF = 'Portal.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',
            ],
        },
    },
]

WSGI_APPLICATION = 'Portal.wsgi.application'


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

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}


# Password validation
# https://docs.djangoproject.com/en/3.2/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/3.2/topics/i18n/

LANGUAGE_CODE = 'de-de'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

CSRF_TRUSTED_ORIGINS = ['subdomain.domain.com']

USE_TZ = True


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

STATIC_URL = '/static/'

STATIC_ROOT = "/var/www/subdomain.domain.com/static/"

Are you making an http or an https request? Your settings suggest the former but the error message implies the latter.

2 Likes

I’m making an https request

If that’s true, then this:

doesn’t look quite right to me.

Also, take note of the original error message and what it’s telling you

1 Like

Changed it to https, now it works.
Thanks very much!