I'm creating a React application which talks to a backend written in Go. I have setup CSRF using the Gorilla library. The React code will first send a GET request to the csrfToken endpoint where it receives a token. This token is set in the header when sending the POST request.
func main() {
r := mux.NewRouter()
r.HandleFunc("/signup/post", SubmitSignupForm).Methods(http.MethodPost, http.MethodOptions)
r.HandleFunc("/csrfToken", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(csrf.Token(r)))
})
r.Use(csrf.Protect(
[]byte("fff"),
csrf.Path("/"),
csrf.Secure(false),
csrf.TrustedOrigins([]string{"http://localhost:3001/"}),
csrf.RequestHeader("TOKEN"),
))
c := cors.AllowAll()
http.ListenAndServe(":8000", c.Handler(r))
}
The React code looks like this:
import React from 'react';
import './App.css';
import useAxios from "axios-hooks";
function App() {
const [{response: csrfToken}] = useAxios<string>({url: "http://localhost:8000/csrfToken"})
const [{response}, doRequest] = useAxios<string>({
url: "http://localhost:8000/signup/post",
method: "POST"
}, {manual: true})
return (
<div className="App">
<header className="App-header">
<h1>hello</h1>
<h1>csrf: {csrfToken?.data}</h1>
<h1>Response: {response?.data}</h1>
<button onClick={e => {
doRequest({data: {key: "something"}, headers: {"TOKEN": csrfToken!.data}})
}}>click
</button>
</header>
</div>
);
}
export default App;
The thing that makes me the most confused is that I'm able to send a request with Postman to the /csrfTokenendpoint and use that value with the header.
However, when I do the same in the browser I get a 403 and responds Forbidden - CSRF token invalid.
Any ideas what I have done wrong?