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

Do I need CSRF protection for /login endpoint? #247

Open
frederikhors opened this issue Sep 29, 2019 · 2 comments
Open

Do I need CSRF protection for /login endpoint? #247

frederikhors opened this issue Sep 29, 2019 · 2 comments

Comments

@frederikhors
Copy link
Contributor

frederikhors commented Sep 29, 2019

Issue opened for the creation of a wiki page that summarizes the doubts and problems for newbies (#210).


I know

this question has already been asked so many times, but after hours of searching I still don't have a clear answer to my problem.

Even projects like https://github.com/pillarjs/understanding-csrf have been abandoned and have not answered to new questions and doubts over the years like this.

PROBLEM

Let's say I have:

  • a back-end on back.domain.com and
  • a front-end on front.domain.com.

My back-end is a simply app with these rest endpoints:

  1. POST /login:

    1. accepts JSON body like: {"username": "myname", "password": "mypass"}
    2. verify credentials
    3. if OK gives 200 and create a cookie with session
    4. if NOT gives 401
  2. GET /players:

    1. check session in cookie
    2. if OK gives 200 with {"players": "[...]"}
    3. if NOT gives 401
  3. POST /player/1:

    1. check session in cookie
    2. if OK gives 200 and edit player
    3. if NOT gives 401

My front-end app has:

  1. /login page with a form (with username and password fields) for issue a POST request to back.domain.com/login

  2. /players which request a GET request to back.domain.com/players

  3. a button which issues a POST request to back.domain.com/player/1

QUESTIONS

  1. Do I need CSRF protection in this scenario?

    I think YES, I need because an attacker can issue a request to back.domain.com/player/1 from malicious.site.com and use my session cookie to edit player because I'm logged in (and I still have a session cookie) on my domain.com.

  2. Do I need CSRF protection (e.g. an X-CSRF-Token header) when I the first time login on back.domain.com/login?

    1. In this scenario I still don't have any session cookie in my browser.
    2. And also I don't know where to get my CSRF token for X-CSRF-Token authorization header too.

    I read on https://fractalideas.com/blog/making-react-and-django-play-well-together-single-page-app-model they are creating a dedicated endpoint on back-end for this and they explain it's not a security vulnerability.

I saw in authboss-sample you just add the X-CSRF-TOKEN header on OPTIONS calls.

if *flagAPI {
  // In order to have a "proper" API with csrf protection we allow the options request to return the csrf token that's required to complete the request when using post
  optionsHandler := func(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("X-CSRF-TOKEN", nosurf.Token(r))
    w.WriteHeader(http.StatusOK)
  }

  // We have to add each of the authboss get/post routes specifically because chi sees the 'Mount' above as overriding the '/*' pattern.
  routes := []string{"login", "logout", "recover", "recover/end", "register"}
  mux.MethodFunc("OPTIONS", "/*", optionsHandler)
  for _, r := range routes {
    mux.MethodFunc("OPTIONS", "/auth/"+r, optionsHandler)
  }
}

But why are you using that?

Are you using that token in javascript after the OPTIONS call?

But the very first one call is failing, right?

I'm confused.

What do you think about using the dataInjector func to inject csrf token in json response? In fact it is like when we render csrf token in html. Right?

@aarondl
Copy link
Member

aarondl commented Oct 9, 2019

@frederikhors Browsers automatically fire off OPTIONS pre-flight requests when they're needed to determine CORS headers.

Note the section on pre-flighted requests here:
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

The options handler is a single request, and the login post is a follow-up to that that happens after the options is complete. There is no first request failure happening.

It's actually possible there's a bug here because in order for the browser to send back that header it may have to be specified in the CORS headers.

@siredwin
Copy link

For anyone else, Authboss puts CSRF token in the header. If you are importing Authboss into a new server(project), it may be a good idea to put CSRF token in form or somewhere else, or your tokens will fail on both sides.
I use echo framework with Authboss and I put token in the form.

e.Use(middleware.CSRFWithConfig(middleware.CSRFConfig{
		TokenLookup: "form:csrf",                        // Please use token in form // authboss puts token in header causing clashes
	}))

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

No branches or pull requests

3 participants