Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Forbidden 403 Error "CSRF token missing or incorrect" when trying to log in when already logged in

So I am using all built in Django, I don't have my own login view.


First I'll describe how the scenario is created that causes this error:

So someone is logged in and has multiple tabs open and then they log out. Eventually the other tabs will be directed to the accounts/login page either by themselves or the page is refreshed or a link is pressed, it doesn't really matter how. The point is this person now has multiple tabs that are all on the accounts/login screen and no one is authenticated/logged in.

So then this person successfully logs in in one of the tabs. They then go and to one of the other tabs, which are still on the accounts/login page (even though a session is already created).

If this person then tries to log in as the person logged in, or really anyone, in fact even if the username and password are empty and they simply click the login button, the 403 Error CSRF token missing or incorrect gets thrown.

(I hope this makes sense)

Anyways, how can I fix this?

And this is my html template if that helps:

{% extends 'base.html' %}
{% load crispy_forms_tags %}

{% block content %}
  <div class='panel panel-primary' style='margin: 0 auto; max-width: 360px;'>
    <div class='panel-heading'>
      <h3 class='panel-title'>Login</h3>
    </div>
    <div class='panel-body'>
      <form action='{% url 'login' %}' novalidate='novalidate' role='form' method='post'>
        {% csrf_token %}
        {{ form|crispy }}
        <input type='hidden' name='next' value='{{ next }}' />
        <div class='form-group' style='margin-bottom: 0;'>
          <p>
            <small>
              By using this site, you agree to our
              <a href='{% url 'privacy-policy' %}'>privacy policy</a>
              and
              <a href="{% url 'terms-of-use' %}">terms of use</a>.
            </small>
          </p>
          <button class='btn btn-primary' type='submit'>Login</button>
        </div>
      </form>
    </div>
  </div>
{% endblock %}

Edit:

I would also like to add that if I create the same scenario and instead of immediately trying to log in, instead I reload the page just once, the 403 error doesn't happen.

I just want to be able to prevent users from ever running into an error while using the site (outside of typing things directly into the search bar of course). One idea could be that right when login is clicked it will refresh the csrf token the same way a page refresh would, is this possible and a good idea?

like image 946
tysonsmiths Avatar asked Nov 22 '25 00:11

tysonsmiths


1 Answers

it will happen because, For security reasons, the value of the secret is changed each time a user logs in.

  • In every Django form, you have a hidden input called "CSRF token" or {% csrf_token %}. This value is randomly and uniquely generated at the time the form rendered and will be compared after the request has been made. So the request can only be sent from the authorized user's browser. There is no way (which I know of) an attacker can get this token and perform the malicious request that can be accepted by Django backend.

For all incoming requests that are not using HTTP GET, HEAD, OPTIONS or TRACE, a CSRF cookie must be present, and the ‘csrfmiddlewaretoken’ field must be present and correct. If it isn’t, the user will get a 403 error. When validating the ‘csrfmiddlewaretoken’ field value, only the secret, not the full token, is compared with the secret in the cookie value. This allows the use of ever-changing tokens. While each request may use its own token, the secret remains common to all. This check is done by CsrfViewMiddleware.

for more details click here

like image 194
Akash D Avatar answered Nov 24 '25 14:11

Akash D



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!