josephspurrier / gowebapp

Basic MVC Web Application in Go
MIT License
1.14k stars 197 forks source link

Sending CSRF token in jQuery POST? #38

Closed k0fi closed 3 years ago

k0fi commented 5 years ago

Hello Joseph, I'd like to let users to like posts through AJAX jQuery POST :

$(function(){
    $('#like').click(function(){
      function getCookie(name) {
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
          var cookies = document.cookie.split(';');
          for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
              if (cookie.substring(0, name.length + 1) == (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
              }
            }
          }
          return cookieValue;
        }
        var token = getCookie('gosess');
        $.ajax({
         url: "/post/like/",  
         type: "POST",         
         beforeSend: function(xhr){xhr.setRequestHeader('token', token  );}, 
         data: { post_id: $(this).attr('name') },
         success: likeSuccess,
         error: likeError,
         dataType: 'html'
       });   
      });
  });

But the snippet above does returns null as cookie, presumably as the cookie is http only. Hence I get 403 error from gowebapp.

What is your suggestion to fix this?

josephspurrier commented 5 years ago

The CSRF doesn't come through the header - it should be submitted as an input in the form:

// Create a new view
v := view.New(r)

// Set the template name
v.Name = "login/login"

// Assign a variable that is accessible in the form
v.Vars["token"] = csrfbanana.Token(w, r, sess)

// Refill any form fields from a POST operation
view.Repopulate([]string{"email"}, r.Form, v.Vars)

// Render the template
v.Render(w)

This is where the token should be:

<input type="hidden" name="token" value="{{.token}}">