title: CSRF protection on AJAX authentication in Flask
body: <p>I'd like to AJAXify both a login and a signup form on a site. Up to now I've been using WTForms mainly for its built-in CSRF protetion, but for this project I didn't feel like it was worth it -- an extra layer of abstraction, and therefore frustration, for something that should be pretty simple.</p>
  
  <p>So I came across <a href="http://flask.pocoo.org/snippets/3/" rel="noreferrer">this snippet</a> on Flask's security section:</p>
  
  <pre><code>@app.before_request
  def csrf_protect():
      if request.method == "POST":
          token = session.pop('_csrf_token', None)
          if not token or token != request.form.get('_csrf_token'):
          abort(403)
  
  def generate_csrf_token():
      if '_csrf_token' not in session:
          session['_csrf_token'] = some_random_string()
      return session['_csrf_token']
  
  app.jinja_env.globals['csrf_token'] = generate_csrf_token
  </code></pre>
  
  <p>I understand the thought process behind this code. In fact, it all makes perfect sense to me (I think). I can't see anything wrong with it.</p>
  
  <p>But it doesn't work. The only thing I've changed about the code is replacing the pseudofunction <code>some_random_string()</code> with a call to <code>os.urandom(24)</code>. Every request has 403'd so far because <code>token</code> and <code>request.form.get('_csrf_token')</code> are never the same. When I print them this becomes obvious -- usually they're different strings, but occasionally, and seemingly with no underlying reason, one or the other will be <code>None</code> or a truncated version of the output of <code>os.urandom(24)</code>. Obviously something out of sync, but I'm not understanding what it is.</p>