Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First request to protected endpoint fails, CSRF header is empty #174

Open
1 task done
nate-anderson opened this issue Jan 22, 2024 · 0 comments
Open
1 task done
Labels

Comments

@nate-anderson
Copy link

nate-anderson commented Jan 22, 2024

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

Calling an endpoint protected with csrf.Protect results in a 403 status and empty response when no header is set - I expect this. However, the client needs a CSRF token to retry with, and none is provided.

I attempted to manually set the CSRF token for errored requests by providing an error handler to the middleware factory:

csrf.Protect(
    []byte(cfg.CSRFAuthKey),
    csrf.ErrorHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		reason := csrf.FailureReason(r)
		if errors.Is(reason, csrf.ErrNoToken) {
		        token := csrf.Token(r)
		        w.Header().Add(CSRFTokenHeader, token)
		}

		w.WriteHeader(http.StatusForbidden)
	})),
)

However, the reason error here is not ErrNoToken, but rather an error with the message "securecookie: hash key is not set". This appears to be an error message from a different Gorilla library.

If I omit the reason check and simply include the CSRF token in all error responses, I get a response with the header X-Csrf-Token set to an empty string - it appears the middleware isn't generating a token for any request coming into the server.

It's possible I'm using the library wrong, but I can't understand how a client is meant to get the initial CSRF token. I assume the server will error with 403 and include the token, and the client should retry. The only other options I can think of are to include the token in the login response (which by definition can't be protected by CSRF and is currently excluded from the middleware, so no token is generated), or to set up a separate unauthenticated endpoint where clients can POST just to get their initial CSRF token, but I don't see that approach mentioned anywhere in the docs.

Expected Behavior

I expect the csrf.Protect middleware to generate a CSRF token for errored requests, so that I can retrieve it with csrf.Token(request) and set the appropriate response header, allowing clients to retry with a token.

Steps To Reproduce

No response

Anything else?

No response

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant