Reputation: 49
I am working on a web site created in Go.
It is possible to access it both via web (server side pages generated via golang templates) and a REST API (for external users who whant to integrate their own software). The Go server handles both types of requests, with a subrouter that handles the API when calls are sent to the subpath "my-url-root/api".
I successfully applied gorilla/csrf to protect the web pages from csrf attacks, but that modification (essential before I go live) is now creating an issue with the API.
My question When the CSRF is implemented, all GET requests sent to the api URLs work as expected, but any other request sent (e.g. a POST to a method to add something via my REST api) generates an html response that typically states "forbidden - invalid csrf token".
Is there a straightforward way that I am missing? I searched for answers but none applicable to the case where the api is served by the same server and most of all it is stateless. Should I see if I can "disable" the gorilla csrf protection for the subrouter (though I do not even know if that is possible and if that is even safe...)?
Thanks for your help.
Upvotes: 3
Views: 1481
Reputation: 49
Ok, so I tried to apply the suggestions above and I came up with a solution to my problem.
I tested that it works by checking web and api calls against my urls and sub-urls with and without the csrf protection.
Just a clarification to my previous comment. To be more precise the order I created the Submuxes did not matter but of course I had then followed a proper order when I wrote down the lines to Handle each path.
So, the order IS important.
This is what I did (just bits of code).
I used goji as a router and gorilla/csrf for the csrf protection.
NOTE: I did not include all my code but just the most important parts to describe what I did.
1) I created a mux using
mux := goji.NewMux()
2) since my APIs are served under the url "/api" and related sub urls, I created a Submux for the api
apiMux := goji.SubMux()
3) I assigned the pages that match the path "/api" and "/api*" to this subMux
Note that I did NOT include any csrf protection
mux.Handle(pat.New("/api/*"), apiMux)
mux.Handle(pat.New("/api"), apiMux)
4) I created a Submux for web pages of my site
webMux := goji.SubMux()
5) I assigned the pages that match the path "/" and "/*" to this subMux
Note that here in my code I linked the middleware for the csrf protection
mux.Handle(pat.New("/"), csrf.Protect(csrfKey, csrf.Secure(true))(webMux))
mux.Handle(pat.New("/*"), csrf.Protect(csrfKey, csrf.Secure(true))(webMux))
6) For my benefit, I created other SubMuxes to handle other paths, like "/users", "/users/1", "/users/addform". This step is important: I assigned this "userMux" to the webMux, and not to the main mux created at step 1.
In this way, the csrf protection is inherited. Example:
usersMux := goji.SubMux()
webMux.Handle(pat.New("/users/*"), usersMux)
webMux.Handle(pat.New("/users"), usersMux)
IN few words, this was the solution to my problem:
I) I assigned this "apiMux" to the main mux created at step 1.
I did not assigned it to any other mux. I did NOT assigned it to the webMux that handles the root url "/" and "/*"
II) The order is important, so I implemented the code for the API urls and then the code for the web urls
I hope it helps. And most of all I hope the explanation was clear... (if not just let me know). Thanks for pointing me in the right direction
Upvotes: 2