Rails 2.0 introduced protection for Cross-site request forgery (CSRF). This is turned on by default in your Rails applications. However, many developers are turning off this valuable protection rather than making the changes necessary to use it. This seems the same to me as leaving your door unlocked while your friend visits because cutting keys is hard. Case in point: text_field_with_auto_complete
You know you have run into the new CSRF protection when you see this error in your Rails application:
This is the point where you Google the error and receive one of the following pieces of advice:
1. Turn off RequestForgeryProtection all together
# add the following line to your application.rb or one of your # environment.rb files. why not production? (sarcasm) config.action_controller.allow_forgery_protection = false
2. Turn off RequestForgeryProtection for just one controller
3. Turn off RequestForgeryProtection for just one action.
protect_from_forgery :except => :attack_me
So let’s see how easy it is to utilize this new feature!
I was working with the text_field_with_auto_complete in a pretty basic form:
For those of you who aren’t familiar with this there is a nice post on the Rails Wiki
When I tried to perform my auto complete I received the ActionController::InvalidAuthenticityToken error.
Why? Because basically my Ajax request did not include a security token that RequestForgeryProtection uses to validate my request is coming from the right place. All you need to do is add this token to the parameters sent with your request. Rails makes this easy with the helper: form_authenticity_token. The token name RequestForgeryProtection will be looking for is: authenticity_token.
So let’s add this to our text_field_with_auto_complete:
Now when I performed my auto complete it worked flawlessly! Now to refactor that string… any suggestions?
Update August 25, 2008
Learned two things working with this…
1. It’s automatically doing a POST, so by changing the method to GET I can avoid having to deal with the authenticity_token.
2. And with that out of the way I don’t need to specify the parameters since by default it will send back the value of the text field.
That’s a lot cleaner!