Reputation: 5874
We have an external system that handles user authentication. We are in the process of switching from that system to rails, slowly but surely.
Using a 3rd party gem is not an option for us at this stage. Long story short, we need to create authorization around "appointments".
Essentially, only users who "own" appointments should be able to modify them.
I added this method to the ApplicationController
def require_authorized_user!(params)
if params[:appointment_id]
appointment = Appointment.find(params[:appointment_id])
if appointment.user_id.to_s != user_id.to_s
render :file => "public/401.html", :status => :unauthorized, :layout => "application"
end
end
end
The AppointmentController
has a before_filter { require_authorized_user! params }
I understand that this may not be the best approach and trust me when I say that we will be migrating to something scalable ASAP. But for now, is the above approache proper? Do you have any suggestions?
Upvotes: 0
Views: 421
Reputation: 23357
If you're not using any gems, then where does the require_authorized_user!
method come from? I guess you wrote it yourself?
But yes, a require_authorized_user! kind of method, called in a before filter, is the right way to implement protected actions.
Whether it's right or not depends on the implementation of the method. It looks like you are passing the params
to the method, and it's going to decide based on those?
That will not be right. Because params
come from URL query parameters, or HTTP POST parameters, in either case a browser can set them to whatever they want. If you're just checking for params[:user_id]
, all someone needs to do is add &user_id=1
to their URLs, and they can be whoever they want. So, no, that's probably no good.
A somewhat dated but still pretty good guide to implementing your own authentication can be found in this free RailsCast: http://railscasts.com/episodes/250-authentication-from-scratch?view=asciicast
With some more ideas in this one, also still somewhat dated: http://railscasts.com/episodes/270-authentication-in-rails-3-1?view=asciicast
I'm not sure if anyone has a high-quality "build your own authentication" tutorial that includes some of the new features in Rails 4 that make this even easier. But the basic approach described in those old RailsCasts will still work.
It's hard to build authentication yourself that doesn't have any holes in it at all, there are lots of places to make mistakes. On the other hand, I'm not a big fan of the over-complexity of Devise either. There are some alternatives to Devise that are simpler, but I haven't tried any of them out myself yet. But if you really want to build it entirely yourself, you can -- but you've got to know what you're doing, or it won't be at all secure. Hopefully those RailsCasts can help you get there.
Upvotes: 0
Reputation: 19899
Kind of depends on where user_id
comes from doesn't it? But yeah, if user_id
has been authenticated successfully somewhere else then what you have would work.
You could also tweak it this way assuming that user
is your user object and the association is setup correctly.
if params[:appointment_id]
appointment = user.appointments.find_by(id: params[:appointment_id])
if appointment.nil?
render :file => "public/401.html", :status => :unauthorized, :layout => "application"
end
end
Upvotes: 1