1

I'm writing a go and react application.

I am trying to use gorilla / csrf as a CSRF countermeasure for SPA.

go and react are developed in completely independent domains.

go port8080 react port3000

I wrote the following code to set the csrf token.

func Route(app *App) *mux.Router {
    r := mux.NewRouter()

    csrfMiddleware := csrf.Protect([]byte("32-byte-long-auth-key"), csrf.Secure(false))
    api := r.PathPrefix("/api").Subrouter()
    api.Use(csrfMiddleware)

    // user
    api.HandleFunc("/users/{id:[0-9]+}", app.tokenVerifyMiddleWare(app.userGetHandler)).Methods("GET", "OPTIONS")
    api.HandleFunc("/users", app.signupHandler).Methods("POST", "OPTIONS")
    api.HandleFunc("/users/{id:[0-9]+}", app.userDeleteHandler).Methods("DELETE", "OPTIONS")
    api.HandleFunc("/users/{id:[0-9]+}", app.userUpdateHandler).Methods("PUT", "OPTIONS")
    // like
    api.HandleFunc("/users/{id:[0-9]+}/likes", app.tokenVerifyMiddleWare(app.likeGetALLHandler)).Methods("GET", "OPTIONS")
    api.HandleFunc("/users/{id:[0-9]+}/likes", app.tokenVerifyMiddleWare(app.likePostHandler)).Methods("POST", "OPTIONS")
    api.HandleFunc("/users/{id:[0-9]+}/likes/{id:[0-9]+}", app.tokenVerifyMiddleWare(app.likeDeleteHandler)).Methods("DELETE", "OPTIONS")
    // auth
    api.HandleFunc("/login", app.loginHandler).Methods("POST", "OPTIONS")
    api.HandleFunc("/logout", app.tokenVerifyMiddleWare(app.logoutHandler)).Methods("POST", "OPTIONS")
    api.HandleFunc("/refresh_token", app.refreshTokenHandler).Methods("POST", "OPTIONS")

}

Route is called below.

func run() error {


    app := controllers.NewApp(models)
    r := controllers.Route(app)
    http.Handle("/", r)
    fmt.Printf("connected port :%d|\n", 8080)
    return http.ListenAndServe(fmt.Sprintf(":%d", 8080), nil)
}

func main() {
    if err := run(); err != nil {
        log.Fatal(err)
    }
}

and set header in middleware

    w.Header().Set("X-CSRF-Token", csrf.Token(r))

What Should I do by React then?

I tried this code from https://github.com/gorilla/csrf#javascript-applications

// You can alternatively parse the response header for the X-CSRF-Token, and
// store that instead, if you followed the steps above to write the token to a
// response header.
let csrfToken = document.getElementsByName("gorilla.csrf.Token")[0].value

// via https://github.com/axios/axios#creating-an-instance
const instance = axios.create({
  baseURL: "https://example.com/api/",
  timeout: 1000,
  headers: { "X-CSRF-Token": csrfToken }
})

// Now, any HTTP request you make will include the csrfToken from the page,
// provided you update the csrfToken variable for each render.
try {
  let resp = await instance.post(endpoint, formData)
  // Do something with resp
} catch (err) {
  // Handle the exception
}

and then

console.log(csrfToken) => undefined
  • What are you trying to accomplish? Why do you need CSRF? – Code-Apprentice Mar 03 '21 at 00:36
  • Thank you for your comment. This is to prevent cross-site request forgery. I want to verify the server and client tokens. – マットmatto Mar 03 '21 at 01:29
  • So do you understand how such a token works, at least at a high level? When your frontend React code makes a request to the server, the server responds with the CSRF token. Then each request from the frontend must include that token. If you add the token to a cookie instead of a header, the browser should just take care of this for you by adding the cookie to every request to that specific domain. – Code-Apprentice Mar 03 '21 at 17:51
  • https://stackoverflow.com/questions/45925344/react-frontend-and-rest-api-csrf Maybe this will help answer your questions? – Code-Apprentice Mar 03 '21 at 17:53
  • I was thinking like this. Issue a token on the server side and save it in a cookie. Grant the token to the header on the client side and verify it on the server side. Therefore, a code to give a token to the header on the client side is required. – マットmatto Mar 03 '21 at 21:32
  • like this https://github.com/gorilla/csrf#javascript-applications . – マットmatto Mar 03 '21 at 21:53
  • Try it and see what happens – Code-Apprentice Mar 04 '21 at 02:31
  • Cloud not get token by this code `let csrfToken = document.getElementsByName("gorilla.csrf.Token")[0].value` `console.log(csrfToken) => undefined` – マットmatto Mar 05 '21 at 00:00
  • Is there an element in your page with `name="gorilla.csrf.Token"`? – Code-Apprentice Mar 05 '21 at 16:31
  • There is none. In other words, I think I need to add it to the meta tag of index.html, but I don't know how to do it. – マットmatto Mar 05 '21 at 22:14
  • You need to add what to the meta tag? The CSRF token? As you said earlier, you save the token in a cookie, that should be good enough. If you save the CSRF token in a cookie instead of a header, the browser will save that cookie and add it to all further requests to the same domain name. – Code-Apprentice Mar 07 '21 at 07:05
  • I see, So how do I validate the csrf token between go react? – マットmatto Mar 08 '21 at 07:03
  • On the server side, you get the CSRF token from the header and check that it is the one that you sent in the first place. – Code-Apprentice Mar 08 '21 at 14:41

0 Answers0