Ruby on Rails Developer Series: Ensuring Security is Covered in Your Application
Welcome to the last and fourth blog post in my Ruby on Rails Developer Series. In this part, our goal is to go over some major security themes to ensure best practices. We will piggyback from the project you have been building in the other parts and use project-specific scenarios that will help secure the application. The series theme is to make you feel confident as an engineer in building a structured project with Ruby on Rails.
1. Authentication
Having authentication set up helps verify that the user is sanctioned to have access. Say you wanted to access a specific item in our Todo list todos/{:todo_id}/item/{:item_id}
, however, if we don’t validate, the user has access to view records. They can easily change the numbers of the todo_id
and item_id
and view those.
I recommended you use an existing gem-like devise for authentication. Devise uses Bcrypt which makes it extremely difficult to for hackers to compute a password as it’s computationally expensive with time. Devise has modules to also help with recovering passwords, registering, tracking user sign-ins, locking records, etc.
2. Strong Parameters
Having strong parameters is when you securely permit the data being sent to you from a request. Let us say we created a form that creates a Todo record: If we followed this common pattern Todo.create(params[:todo]
. And say the form was altered with fields that don’t exist in the model then rails will raise an exception. The same scenario works for updating values in a form if there is something we didn’t want to be updated.
What do I do?
By using strong parameters, you whitelist the values that can be used.
params.require(:todo).permit(:name, :priority)
Now if the user submits the form with incorrect data to the parameterized fields the form will throw an error.
How do I use it?
1 2 3 4 5 6 7 | def create Todo.create(todo_params) end def todo_params params. require (:todo).permit(:name, :priority) end |
3. Slug it!
A slug is part of a URL that identifies a particular record in an easy-to-read form. Slugs are good because we don’t have to reveal the id
of the record.
I recommend using FriendlyId as it’s the “Swiss Army bulldozer” of slugging and permalink plugins for ActiveRecord.
After implementing, we can change our show
methods to look like this:
Todo.friendly.find(params[:id])
params[:id]
– will contain the slug as we now use it as the id of the record.
4. Use HTTPS
Protect sensitive data, especially logins or payment pages. These are easily sniffed when traffic is unencrypted since cookies are easily obtainable through cross-site scripting (XSS).
In the application config file you will need to specify config.force_ssl = true
.
Learn how to create an SSL certificate here.
5. Cross-Site Request Forgery (CSRF)
What is this?
The attack method of cross-site request forgery is the idea that someone can insert malicious code into the application and trick the server to think the user is authenticated. This could allow the attacker to execute unauthorized commands.
How do I enable this?
Add protect_from_forgery with: :exception
in the application controller.
You can rescue forgery if the request is invalid as follows:
1 2 3 | rescue_from ActionController::InvalidAuthenticityToken do |exception| sign_out_user # Example method that will destroy the user cookies end |
6. Check for Active Record Exceptions
One good thing we did in the previous part of the series was create an Exception Concern that sat on the top layer of the Application Controller to guard for specific application Active Record exceptions.
The module below rescues these specific Active Record Exceptions:
01 02 03 04 05 06 07 08 09 10 11 12 13 | module ExceptionHandler extend ActiveSupport::Concern included do rescue_from ActiveRecord::RecordNotFound do |e| render json: { message: e.message }, status: 404 end rescue_from ActiveRecord::RecordInvalid do |e| render json: { message: e.message }, status: 422 end end end |
You can find more exceptions to guard for here.
Wrapping up the series
You have done it! Time to pat yourself on the back as we have planned to build our application and have built a structured project using Ruby on Rails.
In this series, the goal was to outline how to bolster your API with strong top layers of infrastructure and Postgres, dockerize your project and add security layers to mitigate attacks to your application.
I wanted to thank everyone for reading this series and I hope you feel more confident as an engineer building a rails application!
I hope outlined the other parts for you to (re)visit.
Additional resources
- Read more about continuous security
- Try CloudBees CodeShip for free
- Download the whitepaper about DevSecOps
Published on Web Code Geeks with permission by Evan Glazer, partner at our WCG program. See the original article here: Ruby on Rails Developer Series: Ensuring Security is Covered in Your Application Opinions expressed by Web Code Geeks contributors are their own. |