Home > other >  Golang CSRF issues with React
Golang CSRF issues with React

Time:01-31

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?

CodePudding user response:

I'm not familiar with axios-hooks, but don't you want to execute the csrf function in your react code and fetch the CSRF token like you are doing with doRequest()? There's no second property being destructured in the csrf like in doRequest().

If doing the csrf function without the second property executes the axios function, you may need an await or .then chain since it presumably returns a promise.

I think this question might be more React related than Go which looks fine to me.

CodePudding user response:

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...

  •  Tags:  
  • Related