0

I'm trying to perform a OTP-based login in my project. So I have a form with email and password field in the login form and when I submit it through AJAX request I check for the email and password in the database, if the values are correct then I will send an OTP through email and display a new OTP field on the same page for Entering the OTP for verifications.

Till now everything is working fine but after entering the OTP when I try to re-submit the form, I got an error csrf_token is not valid. As far as I know csrf_token is only generated on page refresh or page load but in my case the first csrf_token that was generated on page load was used in first post request.

So now how can I send the second post request with same csrf_token or can I generate the new csrf_token.

Code snippets are as follows:

<form id="loginForm" method="post" action="send_otp">
  <div class="col-12">
    <label class="text-16 lh-1 fw-500 text-dark-1 mb-10">Email</label>
    <input id="email" type="text" name="email" placeholder="Name">
  </div>
  <div class="col-12">
    <label class="text-16 lh-1 fw-500 text-dark-1 mb-10">Password</label>
    <input id="password" type="password" name="password" placeholder="Password">
  </div>
  <div id="otp_field" class="col-12">
                        
  </div>
  <div class="col-12">
    <button type="submit" name="submit" id="send_otp" class="button -md -green-1 text-dark-1 fw-500 w-1/1">Login</button>
  </div>
</form>

Sending the request and adding the OTP input field on success through Ajax:

$("#loginForm").submit(function(event) {

  /* stop form from submitting normally */
  event.preventDefault();
  /* get the action attribute from the <form action=""> element */
  var $form = $(this),
    url = $form.attr('action');

  /* Send the data using post with element id name and name2*/
  var posting = $.post(url, {
    "csrfmiddlewaretoken":"{{ csrf_token }}",//$('input[name="csrfmiddlewaretoken"]').val(),
    "email": $('#email').val(),
    "pass": $('#password').val()
  });

  /* Alerts the results */
  posting.done(function(data) {
    $('#email'). attr('disabled','disabled');
    $('#password'). attr('disabled','disabled');
    $('#otp_field').append('<label class="text-16 lh-1 fw-500 text-dark-1 mb-10">Enter OTP</label><input id="otp" type="text" name="otp" placeholder="Enter OTP">')
  });
  posting.fail(function() {
    
  });
});

How can I achieve it?

Sunderam Dubey
  • 1
  • 11
  • 20
  • 40
Yogesh Yadav
  • 133
  • 3
  • 11

1 Answers1

0

Add the javascript from this django-doc to your page.

function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        const cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            const cookie = cookies[i].trim();
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
const csrftoken = getCookie('csrftoken');

Pass csrfmiddlewaretoken:getCookie('csrftoken')

{% csrf_token %} returns an input tag, which you don't want, and have misspelled.

From another question:

Try adding the @csrf_protect decorator just before your login function.

from django.views.decorators.csrf import csrf_protect

@csrf_protect
def login(request):
     csrfContext = RequestContext(request)
     return render_to_response('foo.html', csrfContext)

If the form is not in foo.html then you need to add the @csrf_protect method to the view function that is generating it.

https://stackoverflow.com/a/12731412/18020941

nigel239
  • 1,485
  • 1
  • 3
  • 23
  • I have already tried to implement the same but still getting the same error message ```Failed to load resource: the server responded with a status of 403 (Forbidden) Forbidden (CSRF token from POST incorrect.): /verify_loginotp ``` – Yogesh Yadav Aug 25 '22 at 04:22