Hartl located common authorization functions in the SessionsHelper module. Sessions being an overused term, it took me a while to understand that there is a blend of Authentication and Authorization in that module.
Authentication caching is handled via cookies and is in these methods:
- sign_in
- sign_out
- current_user
- current_user=
Functional authorization support is in:
- signed_in?
- signed_in_user
- store_location
- redirect_back_or
Data authorization support is supplied via:
- current_user? which compares the current user against a different user (often the owner of certain data)
In each controller, one added the before_action :signed_in_user filter.
A Variation
The Ruby-on-Rails/ActionController overview (section 8) discusses moving the check into the ApplicationController. For those controllers that don't need signin, one opts out by using :skip_before_action.
Observations
In both approaches, Authorization Policy is distributed to the controllers. The second design pattern is a little less so but one still needs to check each controller to see if there are any exemptions.
I've also observed both an increase in test complexity and test run-time when authorization is enabled. Creation of a valid user and sign-in before each test take time. One also needs to test each method against non-authorized users.
Formalizing Authorization
Like the variant above, I place a filter in my ApplicationController
include AuthorizationHelper
...
before_filter do |controller|
authorize( controller)
end
The ApplicationHelper module:
module AuthorizationHelper
def authorize( controller)
require_signin = true
if( controller.is_a?( MyExemptController) ) then
require_signin = false
end
if( require_signin && !signed_in?)
logger.info "Signin required for the #{controller.class}::#{controller.action_name} action"
store_location
flash[:notice] = "Please sign in."
redirect_to signin_url
end
end
end
In this approach, all controllers are unaware of the authentication policy. This allows one to look in one place and see what the intended policy is.
Note that the code makes use of the undocumented .action_name attribute. This can allow per-method control over authorization.
No comments:
Post a Comment