1

I am building an application that is integrated with a 3rd party service provider and uses OAuth 2 to obtain permission from other users using the service to access their account information. Based on the documentation, the implementation process is:

  1. A user clicks a frontend element of my application, which makes a call to my backend.

  2. Before my backend sends the link to the user to redirect him to the 3rd party application's authentication page, I need to create a cookie to store a randomly generated md5 string as "state" at my backend, and the "state" variable is included in the URL link.

  3. After the user uses the link to log into his account and grant my application the permission, a response containing authorization code is sent to my backend.

  4. My backend first checks whether the "state" in cookie matches the "state" in the response. If it does, then my backend will use the authorization code to make a call to the 3rd party's backend to obtain a token.

The documentation states that a "state" variable is needed to protect against cross-site request forgery (CSRF). However, I cannot think of a way how CSRF can happen during this process. CSRF means that a malicious hacker tricks an authenticated user to send an unintended request to the application backend, which is often done by injecting html and javascript into the application's web page. However, in the process mentioned above, after the user is authenticated by the 3rd party, he is completely in the realm of the 3rd party application, which can be assumed to be safe from the 3rd party's point of view. Even if a CSRF does occur, I do not understand how the "state" variable can detect and prevent this.

In short, my questions is: How can a CSRF take place in the process mentioned above and why using the "state" variable can prevent it?

0
1

Your question basically boils down to why do you need CSRF tokens on a login flow?

First off, CSRF protection is to prevent (OWASP):

Cross-Site Request Forgery (CSRF) is an attack that forces an end user to execute unwanted actions on a web application

Now consider if your login flow -- whether that is a simple Form POST with username / password, or something as complex as OAuth2 -- is not protected against CSRF attacks. The user (victim) could be logged in to your app. Another tab (the attacker) could do a POST to your login page with the attacker's credentials (or OAuth2 claim). Your app would accept the attacker's credentials (it's a real account after all) and set the right cookies in the victim's browser so that they are now logged in as the attacker. This is called a Login CSRF Attack because the attacker has forced the victim to execute the unwanted action of logging in to the attacker's account.

Maybe the victim does not notice that they are now in a different account; or maybe the UI has not refreshed and still shows them logged in as them self. Imagine if they enter their credit card information into the attacker's account!


I also need to point out a couple of security flaws in your description:

a randomly generated md5 string as "state"

If you're starting with a random value, why hash it with md5? Why not just use the random value directly? Or a type 4 random GUID? If you do need to hash it, why use an old broken hash function rather than SHA-256?

My backend first checks whether the "state" in cookie matches the "state" in the response.

CSRF tokens in cookies are brittle. At minimum, you need to set SameSite=Strict on your cookie (Mozilla docs). It is always better to put CSRF tokens in a non-cookie header, but I guess if you need the CSRF token on the OAuth2 302 redirect, maybe cookie is your only option?


TL;DR login CSRF attacks are where an attacker can force the user (victim) to log into the attacker's account. You need a CSRF token on your login pages (specifically on the login POST) in order to prevent this.

There is a good related answer on this Stack Overflow post:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.