DEV Community

loading...

Access control gem for your Rails application (the 2nd)

0x7466 profile image Tobias ・4 min read

A lot has happened since my first post about a little project called Action Control back then.

I've learned a lot along the way using my gem and the problems that come with it down the road when scaling a code base with my gem.

This is why we've chosen to change some things from back then. We've introduced policies, moved the auth logic out of the controller, we've made it a lot more stable and secure, have implemented a solid test suite and the most obvious, a new name.

Quick introduction into Active Entry

You'll find Active Entry on GitHub.

  1. Add the gem to your Gemfile and bundle install. 1.1. (Optional but recommended) Add verify_authentication! and verify_authorization! to your ApplicationController to never forget to perform it in your controllers.
  2. Implement policies for the controllers where you want to control access. The methods that carry the logic are called decision makers. Every show action has a complementary show? decision maker in the policy.
  3. Call authenticate!, authorize!, or pass! (for both) in your actions to actually perform the authentication check and authorization.
  4. Rescue from AuthErrors (e.g. redirect to login if user not signed in). If the authentication or authorization check fails, an exception is raised, that can be caught in your controller using rescue_from.

You find a detailed introduction in the README on GitHub.

Why we moved away from putting the auth logic into the controller directly

If you've skimmed over my old post, you've maybe noticed that the old way was to put the authentication and authorization logic directly into the controller. However, there were multiple reasons why we moved the logic into policies.

Small applications back then, big ones now

With growing applications came more complexity and a bigger code base. The old way of doing things was great for quickly bootstrapping an application, but we realized it's not that great when the code base grows.

Testability

It's way easier, more reliable and faster to test "plain Ruby objects" than controllers. Simply create a test file for every policy and test the logic without running through the Rails stack.

Check in views

Whenever we've introduced a link where special privileges were required (e.g. being admin), we had to replicate the logic in our views. And as we all know, duplicated logic is bad and too much logic in views is bad in general. Now you can simply ask the corresponding policy if a user has access and show or hide the link. We've added a few view helpers to make that even easier.

Before:

<%= link_to "Admin Dashboard", admin_dashboard_path if Current.user.admin? %>
Enter fullscreen mode Exit fullscreen mode

After:

<%=
link_to_if_authorized "Admin Dashboard", admin_dashboard_path
%>
or
<%=
link_to "Admin Dashboard", admin_dashboard_path \
  if authorized_for?(:admin_dashboards, :show)
%>
or
<%=
link_to "Admin Dashboard", admin_dashboard_path \
  if AdminDashboardsPolicy.pass?(:show)
%>
Enter fullscreen mode Exit fullscreen mode

This DRYs up the code A LOT.

If we change our logic down the road in the old way, we would have to change it also in every view that replicates the logic. Like in the first example.

It also lowers the risk for bugs. If you change your logic in one place and forget to change in another, you are going to either show something to your users, that they shouldn't see, or they don't see something that they should!

Single-responsibility principle

It's simply none of the controllers business.

Decoupling from Rails

Right now the gem still depends on Rails. However, we've built it in a way in which it can be used in plain Ruby objects. Just create a corresponding Policy for your class and call authenticate!, authorize!, or pass! in the method you want to check.

There is not a lot to do to decouple it from Rails. If you are interested in that, feel free to create a pull request. :)

Differences to other auth gems

You may ask what's makes Active Entry better or different from other gems like Pundit, Action Policy (especially), or CanCanCan.

Shoutout to all these amazing gems! Active Entry is not better or worse than these other gems. It's just another way of doing it. We believe in choice and the awesome thing about open source is that we are all in one boat. Different perspectives and ways of doing things make us only stronger.

In the README, we've written down the key differences to the most similar authorization gem Action Policy.

If you like another gem more, feel free to choose the other without any guilt. Every one of the other gems have been battle tested in big applications, so they can all scale with your code base without messing everything up.

Why not building my own authentication and/or authorization mechanisms?

For the same reason why you wouldn't build your web application with Ruby from the ground up. You don't want to reinvent the wheel. There are cases, where you want to write your own code, but this is not one of them. A proven way of doing it is better most of the time.

The future of Active Entry

We are just starting with this gem. A big code base of ours depends on it, so we will support it in the long term, even if traction is low and no other contributors join.

We are also planning new features down the road. We haven't had much time to write down a lot of our ideas. Hopefully we find that soon. Feel free to propose your own ideas!

Every feedback on Active Entry is really appreciated!

Discussion (0)

pic
Editor guide