Protecting Actionable Links from CSRF Attacks Posted on February 9th, 2015
For awhile I wanted to add CSRF tokens to my links. Not all my links, just the links I call actionable. Links that do things e.g.: "delete product", "publish post", "like". Adding a CSRF token to the query string seemed wrong. And after I did some reading, I realized my entire premise was wrong. The links are sending GET requests; the requests are manipulating data and should use a more appropriate method such as POST. This re-framed the entire issue. Rather than figuring out how to attach a CSRF token to a link, I needed to send the request using POST rather than GET.
This is easy enough with jquery and ajax. However after you have updated an object's status the page's UI should reflect this change or maybe even redirect the user to another page. This can be accomplished using javascript redirects, but they always seem hacky to me. I was hoping for cleaner solution and that's when it dawned on me, just send a form. Rather than writing a javascript click handler and then correctly handling the responses, I could write a simple form, include the CSRF token, and style the button to look like a link. The redirection would happen on the server using 302 responses.
I added the following CSS rules to my global style sheet:
.csrfForm { display: inline; }
.csrfForm button {
background: transparent;
border: 0;
padding:0;
color: blue;
text-decoration: underline;
cursor: pointer;
}
Then I updated my link's HTML to a form:
<form method="POST" action="/posts/15/publish" class="csrfForm">
<input type="hidden" value="<CSRF TOKEN>" name="csrf-token" />
<button type="submit">Publish Post</button>
</form>