The following Ruby snippet shows a Ruby on Rails controller that pulls the user from the request parameter, looking up the user email passed as a parameter in the URL:
def restricted @user = User.find_by(email: params[:email]) if !(@user) flash[:error] = "Sorry, invalid user" redirect_to public_index_path end end
This could be abused by any user to access the restricted API by invoking it, passing the email address of another legitimate user as a parameter.
User management and authentication are not native features of Rails, but they can easily be added by either writing the code or adding a gem, such as Devise.
A simple manual approach is to add a method that retrieves the current, logged-in user looking up active sessions to the Application Controller. It is frequent to add e.g.
current_user method in the
ApplicationController class to make sure every controller in the application inherits it.
class ApplicationController < ActionController::Base def current_user User.find_by(id: session[:user_id]) end end
Such method takes the user ID value from the user’s session and is resilient against tampering. It can be easily invoked by other controllers such as the one shown in this snippet:
def restricted @user = current_user if !(@user) flash[:error] = "Sorry, invalid user" redirect_to public_index_path end end
It’s common to set access restrictions based on roles in order to check if a user has a specific role (such as administrator) and either allow access or redirect with an “Access Denied” message. Roles are attributes associated with a user account and implemented in a User schema and model.
The simplest scenario is a binary role scenario when a user can be either an administrator or an ordinary user. Add a boolean attribute to the
User schema to indicate whether a user is an administrator or not and check the role checking the
@user.admin attribute value:
def restricted @user = current_user if !(@user) || !(@user.admin) flash[:error] = "Sorry, the user is not an administrator" redirect_to public_index_path end end
Role-base controls can be also enforced using “before” filters in the
Controller classes in order to halt the request cycle if a condition is not met. In the following snippet, the
restricted method can be invoked only by users who satisfy the
class AdminController < ApplicationController before_filter :administrative def restricted @user = current_user if !(@user) || !(@user.admin) flash[:error] = "Sorry, the user is not an administrator" redirect_to public_index_path end end private def administrative if !current_user.admin redirect_to public_index_path end end end
Filters are inherited, so if you set a filter on
ApplicationController, it will be run on every controller in your application.