title: Set Ring-Anti-Forgery CSRF header token
body: <p>I'm attempting to implement the <a href="https://github.com/weavejester/ring-anti-forgery#usage">Ring-Anti-Forgery</a> library via setting the X-CSRF-Token in the header.</p>
  
  <p>Since I am using static html files I found the built-in hiccup helper, which sets the token in the form, to be useless.</p>
  
  <p><em>This is my first stab at using Clojure for web development so I'm guessing that I am completely missing what should be obvious to someone with experience.</em></p>
  
  <p>The instructions from the README state:</p>
  
  <blockquote>
    <p>The middleware also looks for the token in the X-CSRF-Token and
    X-XSRF-Token header fields. This behavior can be customized further
    using the :read-token option:</p>
  </blockquote>
  
  <pre><code>(defn get-custom-token [request]
    (get-in request [:headers "x-forgery-token"]))
  
  (def app
    (-&gt; handler
        (wrap-anti-forgery {:read-token get-custom-token})
        (wrap-session)))
  </code></pre>
  
  <p>I have added the above to <em>handler.clj</em> without any success.</p>
  
  <p><strong>project.clj</strong></p>
  
  <pre><code>(defproject hooktale "0.0.1"
    :description "Hooktale iOS App Website"
    :url "http://www.hooktale.com"
    :repositories {"sonartype releases" "https://oss.sonatype.org/content/repositories/releases/"}
    :source-paths ["src/clj" "src/cljs"]
    :dependencies [[org.clojure/clojure "1.5.1"]
                   [org.clojure/clojurescript "0.0-2080"]
                   [org.clojure/java.jdbc "0.3.0-beta2"]
                   [compojure "1.1.6"]
                   [com.mchange/c3p0 "0.9.5-pre5"]
                   [org.postgresql/postgresql "9.3-1100-jdbc4"]
                   [ring-anti-forgery "0.3.0"]]
    :plugins [[lein-ring "0.8.8"]
              [lein-cljsbuild "1.0.1-SNAPSHOT"]]
    :ring {:handler hooktale.handler/app}
    :profiles {:dev {:plugins [[javax.servlet/servlet-api "2.5"]
                               [ring-mock "0.1.5"]]
                     :cljsbuild {:builds [{:source-paths ["src/cljs"]
                                           :compiler {:optimizations :advanced
                                                      :pretty-print false
                                                      :output-to "resources/public/js/trout.js"}}]}}})
  </code></pre>
  
  <p><strong>handler.clj</strong></p>
  
  <pre><code>(ns hooktale.handler
    (:require [compojure.core :refer [defroutes GET POST]]
              [compojure.handler :refer [site]]
              [compojure.route :refer [resources not-found]]
              [clojure.java.io :refer [resource]]
              [ring.middleware.anti-forgery :refer :all]
              [ring.middleware.session :refer [wrap-session]]
              [hooktale.controllers.prospect :refer [create-prospect]]))
  
  (defn get-custom-token [request]
    (get-in request [:headers "x-forgery-token"]))
  
  (defroutes app-routes
    (GET "/" [] (resource "public/index.html"))
    (POST "/" [email] (create-prospect email))
    (resources "/")
    (not-found "Not Found"))
  
  (def app
    (-&gt;
     (site app-routes)
     (wrap-anti-forgery {:read-token get-custom-token})
     (wrap-session)))
  </code></pre>
  
  <p>Sending a request to the page returns the following info:</p>
  
  <p><code>curl -I localhost:3000</code></p>
  
  <pre><code>HTTP/1.1 200 OK
  Date: Fri, 06 Dec 2013 16:30:45 GMT
  Set-Cookie: ring-session=0b2a477f-9352-4fd8-a3c3-a6b6f8d9e063;Path=/
  Content-Length: 0
  Server: Jetty(7.6.8.v20121106)
  </code></pre>
  
  <p><code>curl -X POST -d '{:email "piglet@aol.com"}' localhost:3000</code></p>
  
  <pre><code>&lt;h1&gt;Invalid anti-forgery token&lt;/h1&gt;
  </code></pre>
  
  <p>The function in ring.middleware.anti-forgery that I thought would allow me to set the token in the header without having to set the hidden token value inside the form field.</p>
  
  <pre><code>(defn- default-request-token [request]
    (or (-&gt; request form-params (get "__anti-forgery-token"))
        (-&gt; request :headers (get "x-csrf-token"))
        (-&gt; request :headers (get "x-xsrf-token"))))
  </code></pre>
  
  <p>If I am reading it correctly, it will check for the token in the form, if not there it will check for the x-csrf-token then the x-xsrf-token in the header.</p>
  
  <p>I seem to be having difficulty in actually setting the value of x-csrf-token or x-xsrf-token in the header.</p>
  
  <p><strong>Curl responses</strong></p>
  
  <p>View the Cookie set by ring-session:</p>
  
  <p><code>curl -I localhost:3000</code></p>
  
  <pre><code>HTTP/1.1 200 OK
  Date: Fri, 06 Dec 2013 19:52:22 GMT
  Set-Cookie: ring-session=b02dd6f8-74b8-4ce0-a1d6-07251dadb9aa;Path=/
  Content-Length: 0
  Server: Jetty(7.6.8.v20121106)
  </code></pre>
  
  <p>Setting the X-CSRF-Token:</p>
  
  <p><code>curl -v --header "X-CSRF-Token: b02dd6f8-74b8-4ce0-a1d6-07251dadb9aa;Path=/" -X POST -d '{:email "starbuck@bsg.com"}' localhost:3000</code></p>
  
  <pre><code>* Adding handle: conn: 0x7fd3ab004000
  * Adding handle: send: 0
  * Adding handle: recv: 0
  * Curl_addHandleToPipeline: length: 1
  * - Conn 0 (0x7fd3ab004000) send_pipe: 1, recv_pipe: 0
  * About to connect() to localhost port 3000 (#0)
  *   Trying ::1...
  * Connected to localhost (::1) port 3000 (#0)
  &gt; POST / HTTP/1.1
  &gt; User-Agent: curl/7.30.0
  &gt; Host: localhost:3000
  &gt; Accept: */*
  &gt; X-CSRF-Token: b02dd6f8-74b8-4ce0-a1d6-07251dadb9aa;Path=/
  &gt; Content-Length: 27
  &gt; Content-Type: application/x-www-form-urlencoded
  &gt;
  * upload completely sent off: 27 out of 27 bytes
  &lt; HTTP/1.1 403 Forbidden
  &lt; Date: Fri, 06 Dec 2013 19:54:52 GMT
  &lt; Content-Type: text/html;charset=ISO-8859-1
  &lt; Content-Length: 35
  * Server Jetty(7.6.8.v20121106) is not blacklisted
  &lt; Server: Jetty(7.6.8.v20121106)
  &lt;
  * Connection #0 to host localhost left intact
  &lt;h1&gt;Invalid anti-forgery token&lt;/h1&gt;
  </code></pre>