1

We have a simple webapp where a user will have to create an account. To verify their email address (which will be used to send notifications later for business purposes, which is one of the core features of the application), we send an activation link.

Our activation link leads to a different sub-domain. Because of this, and the ability for the user to open this activation link on a different computer/browser (such as on your PC instead of on your phone), the user would need to get a new CSRF token when following the activation link.

When activating your account, you do not need to be logged in. (You could be logged in, but not to the account that you're activating.)

So when activating their account, the following happens:

  1. the user clicks on the link,
  2. the front-end which handles such requests opens,
  3. the front-end makes a pre-flight request to our server to obtain a CSRF token,
  4. the front-end receives the CSRF token,
  5. the front-end uses the parameters passed in the url to send an activation request to our server.
  6. The server sends back the appropriate response after handling the request
  7. The front-end displays the appropriate page based on the response ("It succeeded, click here to login" or "Your account was already activated, click here to login" or "activation link expired", etc.)

Key point here is that the person who activates an account does not gain any special rights. We don't automatically log the person who activates their account in. People still have to do that themselves.

So then I'm left wondering - why do I need this CSRF token? The activation link contains a activation token, so anyone capable of activating an account either got really lucky or has actually received the email. If an attacker activated an account, all that would happen is "the account is activated".

I'd like to take the CSRF token out of this process to speed up the process (particularily for people with high latency internet). Would I be weakening my security if I took the CSRF token out of the process, so that the process resolves to this:

  1. the user clicks on the link,
  2. the front-end which handles such requests opens,
  3. the front-end uses the parameters passed in the url to send an activation request to our server.
  4. The server sends back the appropriate response after handling the request
  5. The front-end displays the appropriate page based on the response ("It succeeded, click here to login" or "Your account was already activated, click here to login" or "activation link expired", etc.)

TL;DR: Does a CSRF token add security for REST end-points where you don't need to be logged in?

1

Ok, as I see it, there are two important HTTP requests here:

  1. The first one is generated when the user clicks the activation link. This one is anyway not protected by a CSRF token, but contains an activation token. That all sounds fine.
  2. The frontend will then generate a CSRF token and will send a request to your server to complete the activation. If that request contains the activation code, and the server verifies it, I do not see a reason to have a CSRF token in this particular case, although it's hard to tell for sure without seeing how the requests/responses look like and what they do on the server side. Could it be that the CSRF token is used later for something else? Are there any security related changes on the server or clinet side after performing these requests?

Because the first request is not protected by a CSRF token, and the token is generated on the fly for the second request, this kind of CSRF token implementation does anyway not really make sense for these particular requests because the attacker still has to know only the activation token, if I understood everything right.

What could still go wrong?

An attacker does not know the activation token of the victim so he can't use that attack vector in any case.

But an attacker could create his own account, and make the victim activate it, but this would be only exploitable if that request would have some additional effect, like logging the user in (what is not the case as you described). You must just be very careful that activating the account is the only effect of that request.

Another far fetched scenario would be if the server is always generating the same CSRF tokens for the same activation codes. The attacker could let the server generate CSRF token, but then interrupt the activation of the account (the second request). After that he would make the victim visit the link with his activation could, and he would know what CSRF token the victim got. But that is also a bit far fetched.

In addition to that, using a CSRF token has often some nice side effects, like limiting XSS to self XSS, but that's a more general thing, not specific to your case.

By the way, if you want to speed up things, why do you use the frontend to generate the second request? Why not make the server process the first request and activate the account?

And please do not take what I said for granted because it is hard to give an accurate answer if I did not see the app.

  • 1
    why do you use the frontend to generate the second request? He is right to do this. Many mail client (eg Outlook) fetch a preview of the page when they see a link. By doing this, those kind of client will confirm the email even if the client didn't click the link, just by doing the appropriate GET request. The right think to do is to activate the account with a request from the front-end. – Xavier59 Aug 3 '17 at 14:46
  • @Xavier59 Thanks for that! That did not come to my mind. Learned something new! :) – stanko Aug 3 '17 at 15:18

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.