Rails Authorization Without Using 3rd Party Gems
In the Gitter Rails chat room, a user asked the following question:
“hey guys, i’ve got simple blog with posts, comments and users. User can delete and edit only his posts and comments. How I can do that? Is it hard to do auth without gem?”
The Rails community never fails to help me when I need answers, so I’ll use this as chance to reciprocate.
The Devise gem would be one way to manage authentication and authorization in a Rails project, but you may find its too much horsepower and it creates a bunch of extra files and routes that you might not understand how to use.
The use-case here is straightforward. The authenticated user is the only user who is allowed to edit or delete their own blog posts.
I’m assuming there is a User Controller that collects a username and password through a form. The form allows the username and password information to be held in the params hash. The information coming from the params hash is saved in the database as part of a User record via the users#create action. If help is needed for the process of creating a user, logging the user in and logging the user out, I recommend a video called “Authentication With Steps.”
Below are the steps to ensure only the authorized user is editing blog posts owned by the authorized user.
In your routes.rb file, add the routes for logging in and logging out:
Create a sessions controller with new, create and destroy actions. The sessions controller allows you to hang on to the information about the user who is currently logged in.
Add a helper method to your application controller called current_user. The current_user is now a powerful object that allows you to restrict editing and deleting functions to only the authenticated user who is currently logged in and using your app.
Now you are in a position to limit the editing and destroying functionality to only the current_user. Since a blog post belongs to a user, you can now replace any instance of a user_id, with the current_user object. You probably have a line of code in your view or controller action that looks like this:
This line returns an array of blog post objects tied to user id 6. You can now do the same query for the user, like this:
This ensures that only the user attached to the blog post can edit or destroy the blog post.
Notify me of any mistakes, typos, or areas of confusion at email@example.com. I want to be helpful, but if I’m making things muddier, I will happily make corrections.