You may have cases when you may need to do some authorizations for certain pages, so that they cannot be accessed by unauthorized clients. There are many authorization ways that you can use in a Ruby on Rails application. In this article, I will mention one very simple, yet not that much famous method that comes implemented and ready to be used each time you create a new Rails application.
ActionController::HttpAuthentication::Basic
has a method called http_basic_authenticate_with
that you may usually need to invoke at the top lines of your controller.
Rails is an open source framework so we are thankfully able to see the implementation and the work that is being done by this method:
def <b>http_basic_authenticate_with</b><span style="font-weight: 400;">(options = {})</span>
<span style="font-weight: 400;"> before_action(options.except(</span><span style="font-weight: 400;">:name</span><span style="font-weight: 400;">, </span><span style="font-weight: 400;">:password</span><span style="font-weight: 400;">, </span><span style="font-weight: 400;">:realm</span><span style="font-weight: 400;">)) </span><b>do</b>
<span style="font-weight: 400;"> authenticate_or_request_with_http_basic(options[</span><span style="font-weight: 400;">:realm</span><span style="font-weight: 400;">] </span><b>||</b> <span style="font-weight: 400;">"Application"</span><span style="font-weight: 400;">) </span><b>do</b> <b>|</b><span style="font-weight: 400;">name, password</span><b>|</b>
<span style="font-weight: 400;"> </span><i><span style="font-weight: 400;"># This comparison uses & so that it doesn't short circuit and</span></i>
<span style="font-weight: 400;"> </span><i><span style="font-weight: 400;"># uses `variable_size_secure_compare` so that length information</span></i>
<span style="font-weight: 400;"> </span><i><span style="font-weight: 400;"># isn't leaked.</span></i>
<span style="font-weight: 400;"> </span><span style="font-weight: 400;">ActiveSupport</span><b>::</b><span style="font-weight: 400;">SecurityUtils</span><span style="font-weight: 400;">.variable_size_secure_compare(name, options[</span><span style="font-weight: 400;">:name</span><span style="font-weight: 400;">]) </span><b>&</b>
<span style="font-weight: 400;"> </span><span style="font-weight: 400;">ActiveSupport</span><b>::</b><span style="font-weight: 400;">SecurityUtils</span><span style="font-weight: 400;">.variable_size_secure_compare(password, options[</span><span style="font-weight: 400;">:password</span><span style="font-weight: 400;">])</span>
<span style="font-weight: 400;"> </span><b>end</b>
<span style="font-weight: 400;"> </span><b>end</b>
<b>end</b>
Let’s take an example of a DocumentsController. I have two methods that render views. I want to display a list of documents to anyone regardless of whether they are already authenticated or not. I want to restrict the privileges to modify documents to only the users that are authorized. Namely, they know a name and a password that I have set in the beginning that can be used.
<span style="font-weight: 400;">http_basic_authenticate_with name: "fatos", password: "secure_password", except: :index</span>
I should certainly use parametrized values that are set at config files, but for the purpose of this example, I am using actual values at the time this method is being invoked. Yes, I know that is not the most difficult to be found out and secured password on the planet, but it is only used for this article and maybe a few grandmas out there.
class DocumentsController < ApplicationController
<span style="font-weight: 400;"> http_basic_authenticate_with name</span><span style="font-weight: 400;">:</span> <span style="font-weight: 400;">"fatos"</span><span style="font-weight: 400;">, password</span><span style="font-weight: 400;">:</span> <span style="font-weight: 400;">"secure_password"</span><span style="font-weight: 400;">, except</span><span style="font-weight: 400;">:</span> <span style="font-weight: 400;">:index</span>
<span style="font-weight: 400;"> </span><b>def</b> <b>index</b>
<span style="font-weight: 400;"> render plain</span><span style="font-weight: 400;">:</span> <span style="font-weight: 400;">"Everyone can see me! Yes all of you"</span>
<span style="font-weight: 400;"> </span><b>end</b>
<span style="font-weight: 400;"> </span><b>def</b> <b>edit</b>
<span style="font-weight: 400;"> render plain</span><span style="font-weight: 400;">:</span> <span style="font-weight: 400;">"I'm only accessible if you know the password"</span>
<span style="font-weight: 400;"> </span><b>end</b>
<b>end</b>
That single line of code calls the method that protects your documents from being modified by people you do not want. That’s really awesome and time saving, so you do not have to write everything by yourself.
If you need to do this type of authorization for many controllers, then you can simply declare it at ApplicationController:
class ApplicationController < ActionController::Base
<span style="font-weight: 400;"> http_basic_authenticate_with name: "fatos", password: "secure_password", except: :index</span>
<span style="font-weight: 400;"> protect_from_forgery with: :exception</span>
<span style="font-weight: 400;">end</span>
That’s all you need to do to use this incredibly easy-to-use way of authorization for your application.
Here you can check out the other methods that are included in this Rails module.