before_filter strange behaviour on update and create

Hi,

I wrote a authentication script and I'm calling it like this in every
class:

class Blah < ApplicationController

before_filter :auth

def auth
req_perm = Permission.find_by_name("Permission Blah")
access = AccessController.new()
if access.is_logged_in(session.session_id)
  if
!access.get_current_user(session.session_id).role.permissions.include?
req_perm
  redirect_to no_permission_url
  end
else
  redirect_to login_url
end
end

It works for the view pages but if an update or create is made then it
always redirects to the login_url. Acting like the user is not logged
in. But that's wrong.

Did I miss something about the before_filer ? Does it work different on
update/create ?

No.

No.

But why is it acting different ? It always redirects to the login_url
after update/create.

I guess at some point it can't get the session.session_id. Might that be
the problem ?

In my scaffolded update/create methods it redirects to the show page
after update. The update/create work btw. The data get saved. But
afterwards you see the login instead of the show page.

Martin Sz wrote:

No.

But why is it acting different ? It always redirects to the login_url
after update/create.

I guess at some point it can't get the session.session_id. Might that be
the problem ?

In my scaffolded update/create methods it redirects to the show page
after update. The update/create work btw. The data get saved. But
afterwards you see the login instead of the show page.

Ok, I can see the problem now. The session.session_id is different
directly after the update/create when it redirects to the show page.
Question is: why ?

I guess I'm using the wrong session_id. I thought "session.session_id"
is something like the server generates and that's always the same ?

After login I have this session_id:

BAh7BzoMY3NyZl9pZCIlOTBjM2E5NjQxMTZjNTQwMDhkMjhmODhjY2RmYjQw%0AMjQiCmZsYXNoSUM6J0FjdGlvbkNvbnRyb2xsZXI6OkZsYXNoOjpGbGFzaEhh%0Ac2h7AAY6CkB1c2VkewA%3D--da80e3c07efbf5b09fef7418c5d404ca5f053812

After update/create I have this one:

BAh7BzoMY3NyZl9pZCIlZjg1NTBmOThmNmM2NGExNjU2NmQyMGEzMmQ2ZDNi%0AN2QiCmZsYXNoSUM6J0FjdGlvbkNvbnRyb2xsZXI6OkZsYXNoOjpGbGFzaEhh%0Ac2h7AAY6CkB1c2VkewA%3D--e6e7f072c7283b4de8773ed7c8e518b1eb2f5948

The first part is the same, but the end is different:

da80e3c07efbf5b09fef7418c5d404ca5f053812
e6e7f072c7283b4de8773ed7c8e518b1eb2f5948

When you store the session in the server the cookie stores a session_id that is used as a key to retrieve the data on each request.

With cookie-based sessions session_id is not meaningful.

From your code looks like you are storing information in the server based on the session_id. If I am correct that's a bad practice. You'd just store the information in the session itself, that's its purpose:

    session[:user_id] = user.id

and off the top of my head so that you see the idea:

    before_filter :authenticate
    def authenticate
      current_user = nil
      if session[:user_id]
        current_user = User.find(session[:user_id]) rescue nil
      end
      redirect_to login_path unless current_user
    end

It goes without saying that implementing authentication yourself is hard to justify normally, it is normally better to pick some plugin.

-- fxn

Ok, so if I store something in the session like you described it then a
hacker wouldn't be able to change it by simply editing a cookie ?

I mean the cookie wouldn't include plain information like:

"user_id = 123"

I don't really want to use a plugin. I would actually like to understand
as much as possible of what my application does :wink:

Ok, so if I store something in the session like you described it then a
hacker wouldn't be able to change it by simply editing a cookie ?

I mean the cookie wouldn't include plain information like:

"user_id = 123"

That's the purpose of the right hand side of the cookie value, then one you saw changed. That's a digest of the data of the left hand side computed by Rails. If the user tries to edit the data (which goes in clear only encoded in Base64) Rails raises CGI::Session::CookieStore::TamperedWithCookie and the request flow is interrumped right away.

I don't really want to use a plugin. I would actually like to understand
as much as possible of what my application does :wink:

That's good for learning, and normally bad for getting work done. When you get confident with how things works you delegate as much as possible. It is often the case that the author knows the problem to solve better than you ("you" being generic) and has a good design and good handling of corner cases or gotchas.

I changed the Session Store to ActiveRecord and if a user logs in
successfully then I store his or her UserID in session[:user_id]. To
check if he is logged in I just do if session[:user_id] as you said.

That works pretty good now.

Is this halfway secure now ?

Oh by the way I may already say thanks for your help xavier.

It can be so easy to do things with RoR..you just need to know how haha

Not necessarily, cookie-based sessions are a valid storage. It is valid to use the database as well of course.

No it’s not, as long as you only store the user_id and not the user object itself. There is also a plugin out there that can make the cookiebased session more secure by encrypting the data instead just base64’ing it.

Best regards

Peter De Berdt

No it's not, as long as you only store the user_id and not the user
object itself. There is also a plugin out there that can make the
cookiebased session more secure by encrypting the data instead just
base64'ing it.

Hi Peter,

well with my current implementation it all depends on that user_id in
the session. If you manipulate this is then you are another user. For my
understanding: what would a hacker have to do to change the user_id of
the session ? He would need to access my database - right ? Because the
session's are stored there now ..

That would be pretty save .. I mean if someone has access to your
database then you have lost anyways haha ..