gorilla / csrf

Package gorilla/csrf provides Cross Site Request Forgery (CSRF) prevention middleware for Go web applications & services 🔒

Home Page:https://gorilla.github.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[question] How to use gorilla/csrf for CSRF protection when authenticating with OpenID Connect?

stapelberg opened this issue · comments

Thanks for this useful package!

I’m currently building a web app that uses OpenID Connect so that users can log in via GitLab.

For OpenID Connect, there is a state parameter which is used to protect against CSRF, see e.g. https://auth0.com/docs/protocols/state-parameters

Now, while I can use csrf.Token(r) to put a CSRF token into the request, because OpenID Connect uses GET requests, gorilla/csrf will not actually verify the token, ever!

If there was an API with which I could manually verify a token, I could use gorilla/csrf here. Or maybe I’m missing something?

My code is roughly this:

	// redirects the user to GitLab
	http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
		// To prevent CSRF attacks, state needs to contain a unique and
		// non-guessable value associated with each authentication request.
		state := csrf.Token(r)
		url := oauth2Config.AuthCodeURL(state)
		http.Redirect(w, r, url, http.StatusTemporaryRedirect)
	})

	// user came back from GitLab, verify authentication
	http.HandleFunc("/redirect_uri", func(w http.ResponseWriter, r *http.Request) {
		ctx := r.Context()

		// TODO: how do I verify the CSRF token in state?
		state := r.FormValue("state")
	})
commented

This issue has been automatically marked as stale because it hasn't seen a recent update. It'll be automatically closed in a few days.

This still a relevant question.

Hi @stapelberg ,
I'm not one of the gorilla team, but I would like to share my opinion with you.
I had built one web app with gorilla/csrf and OIDC before.

As far as I understand OAuth2, the state is simply checked by the client and it has nothing to do with gorilla/csrf.
The client needs to make sure the state in OIDC Authentication Request must match the one in server's response which consists of
code and state. And the state in OIDC Authentication Request should be generated by you, which is usually a random string.
In this way, OAuth2's csrf protection using state is completely separated with gorilla/csrf.

Moreover, gorilla/csrf uses "double submit cookie" method to provide csrf protection, which is completely different from OAuth2's method.

You can also take a look on this:

The primary reason for using the state parameter is to mitigate CSRF attacks by using a unique and non-guessable value associated with each authentication request about to be initiated. That value allows you to prevent the attack by confirming that the value coming from the response matches the one you sent.

Thanks for sharing your thoughts!

For some reason, I had thought that state should not only be unique per-request, but also fulfill best practices for a CSRF token. I see now that this isn’t actually stated anywhere AFAICT.

I’ll stick to generating a random state and cryptographically verifying it came from my program.