DEV Community

Mason White
Mason White

Posted on

TIL: Ruby Authenticity Tokens - Reusing the HTML Value

I've been learning about Ruby Form Authenticity Tokens recently, and wanted to dig a bit deeper - specifically looking into why it seems that i can reuse the 'value' that appears in the HTML form.

Background:

When you insert the Form Authenticity Token input type into the relevant form, the token becomes viewable in the Dev Console:

Authenticity Token 1 in HTML form

I'll store the actual token value here for reference:

A5KRrymA_WZ9C7lCkiXrhBMXMAlIilnNgvizf2K85aYdv2HuxrEog73Hgz22HltTv7nihHIZpT-XUB0euL219A
Enter fullscreen mode Exit fullscreen mode

Question:

When I refresh the page, a new token is generated. However, when I manually copy and paste the above token into the form and submit it, the submission still succeeds!

Ruby accepts token 1 again

Is Ruby letting my reuse my token?

Testing:

To investigate further, I manually entered a random value into the token field and submitted the form. This time, I received the expected CSRF error:

Submitting a random value in the HTML form

CSRF Error from random value submission

These tests reveal something interesting: manually setting the token to a random value does trigger the CSRF error, which confirms that Rails is not silently using the token generated at page load. Instead, it validates whatever value is present in the HTML field (even if I manually replace the current token value).

I think this means the backend is accepting the same token repeatedly across submissions. I assumed tokens would be single-use, but that doesn't appear to be the case.

Is this a problem? If someone reads this blog and copies the above token value, could they start making changes to the Movies I created in the mini web-app we are working with?

Conclusion:

I did some more digging, and think I have a better idea of what is happening behind the scenes. It sounds like, when a user session is created, Ruby creates and stores a token in the user session. The value that is presented in the HTML page is actually a mask - some kind of string that, when unencrypted, becomes the single token. While the value of the string changes every time the page refreshes, the underlying token it represents does not change (until the next user session). Further details of the CSRF Protection in rails can be found here:

Rails CSRF Protection - Avo

Build self-hosted Internal Software in days not months

favicon avohq.io

Top comments (0)