csrf
csrf copied to clipboard
[BUG] Forbidden - Invalid Origin in localhost
Is there an existing issue for this?
- [x] I have searched the existing issues
Current Behavior
When running in localhost, every csrf check returns "Invalid Origin" error. go-chi router is used.
router.Use(CsrfMiddleware(mustGetCsrfKey()))
func CsrfMiddleware(key []byte) func(http.Handler) http.Handler {
var opts []csrf.Option
env := os.Getenv("APP_ENV")
if env == "local" || env == "dev" {
opts = append(opts, csrf.Secure(false))
}
csrfFn := csrf.Protect(key, opts...)
return csrfFn
}
I made sure that the APP_ENV variable is correctly set and csrf.Protect is called with csrf.Secure(false) option.
After debugging I noticed the error happens do to the check if !sameOrigin(&requestURL, parsedOrigin) ... in gorilla/csrf/csrf.go. The request url gets rewritten in the same csrf.go file in this block:
requestURL := *r.URL // shallow clone
requestURL.Scheme = "https"
if isPlaintext {
requestURL.Scheme = "http"
}
if requestURL.Host == "" {
requestURL.Host = r.Host
}
Expected Behavior
csrf.Secure(false) option should prevent rewriting url scheme from "http" to "https"
Steps To Reproduce
No response
Anything else?
No response
Update: does not reproduce in the version 1.7.2 or lower, only 1.7.3 is affected.
There is a context key PlaintextHTTPContextKey which is AFAIU supposed to be a switch for that url rewrite, but it's not used anywhere apart from tests. According to the commit message that introduced that change, the key is meant to be used by the clients of the library, is it correct?
I was able to reproduce this on localhost using 1.7.3. Workaround is to downgrade to 1.7.2 as mentioned. Minimal example:
router:
...
csrfKey := "abcd1234abcd1234abcd1234abcd1234"
csrfMiddleware := csrf.Protect(
[]byte(csrfKey),
csrf.Secure(false),
)
http.ListenAndServe(":3000", csrfMiddleware(r))
controller:
func (u Users) Signup(w http.ResponseWriter, r *http.Request) {
var data struct {
Email string
CSRFField template.HTML
}
data.Email = r.FormValue("email")
data.CSRFField = csrf.TemplateField(r)
u.Templates.New.Execute(w, data) // template form with CSRF hidden input
}
Verified that the form hidden field and CSRF cookie were all properly set / sent with the POST requests. Received aforementioned Forbidden - Invalid Origin error with 403
My understanding is that PlaintextHTTPRequest() is the library function meant to be used to allow plain text requests (just because it's an exported function - please correct me if I'm wrong).
I rewrote the @shamilovstas's original snippet to use the function:
func CsrfMiddleware(key []byte) func(http.Handler) http.Handler {
var opts []csrf.Option
env := os.Getenv("APP_ENV")
if env == "local" || env == "dev" {
opts = append(opts, csrf.Secure(false))
}
csrfFn := csrf.Protect(key, opts...)
return func(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
// Need this starting from gorilla/csrf 1.7.3.
if env == "local" || env == "dev" {
r = csrf.PlaintextHTTPRequest(r)
}
csrfFn(next).ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
}
Tangentially, the use of PlaintextHTTPRequest() to enable optional behavior seems to me to be counter to the conventions of this package; it seems having another option available for passing to Protect() should be the way to go instead.
Funny, just got this error as well. Forgot I had updated this dependency and here we are.
Hello! I wanted to ask when there will be a fix for this bug? The billing team at GitHub relies on this package for our service but we need to update from 1.7.2 in order to fix a security vulnerability.
I also encountered the same issue with go-chi. Downgrade to 1.7.2 to temporarily fix that.
I also encountered the same issue with go-chi. Downgrade to 1.7.2 to temporarily fix that.
I also encountered it locally & this fixes it
csrf.TrustedOrigins([]string{"localhost:3000"}),
but just a question is this causing issues during deployments as well or not? I don't have a deployment yet.
I also encountered the same issue with go-chi. Downgrade to 1.7.2 to temporarily fix that.
I also encountered it locally & this fixes it
csrf.TrustedOrigins([]string{"localhost:3000"}),
but just a question is this causing issues during deployments as well or not? I don't have a deployment yet.
try that one as suggested somewhere but didn't work for no reason.
I also encountered the same issue with go-chi. Downgrade to 1.7.2 to temporarily fix that.
I also encountered it locally & this fixes it
csrf.TrustedOrigins([]string{"localhost:3000"}),
but just a question is this causing issues during deployments as well or not? I don't have a deployment yet.
This didn't fix it for me. I downgraded temporarily instead.