Golang CSRF issues with React

Issue

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?

Solution

I figured out the problem.

I started debugging the application by first creating a dummy project with a much simpler setup. There I managed to successully set everything up. While understanding the differences of the two applications I noticed that the cookie was not being sent in the application that was not working.

After some time I understood that the cookies was not being sent from the browser to the API due to cross origin. All of this was running locally, and my painful mistake was:

localhost != 127.0.0.1

All I needed to do was to change all the places where I had used localhost to 127.0.0.1. Since the browser thought the two were of different origins and would not send the cookies…

Answered By – TryingMyBest

Answer Checked By – Marilyn (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.