By default all rails controllers inherit the application controller.
In my application I want users to be able to authenticate from any page using http-basic auth, and also authenticate by posting, but only to one controller.
Currently things look like this (simplified):
class ApplicationController < ActionController::Base
before_filter :set_current_user
private
def set_current_user
Authorization.current_user = current_user
end
def current_user
if session[:user].blank?
authenticate_or_request_with_http_basic do |user,pass|
session[:user] = authenticated_user_or_nil
end
end
session[:user]
end
end
class UserSessionsController < ApplicationController
prepend_before_filter :set_user_from_params
private
def set_user_from_params
session[:user] = authenticated_user_or_nil
end
end
I set a breakpoint in both set_user_from_params
and set_current_user
and have verified they are indeed being called in the correct order.
set_user_from_params
is in fact setting session[:user]
correctly, but when I continue and hit the breakpoint inside set_current_user
the session hash is empty!?
Is this intended behaviour or have I missed something really obvious?
If the request is a post request then, by default rails will check for the presence of a valid csrf token.
A before_filter
is inserted that does that check, if it fails then rails resets the session, which is consistent with your situation.
You need to either ensure that your post request contains an authenticity token or (if appropriate) disable that check by skipping the verify_authenticity_token
filter.
One way of verifying that is to add
def handle_unverified_request super Rails.logger.info "handling unverified request - csrf issue" end
to your controller. If the issue is a csrf issue then this method will be called and will write to the log file confirming this has happened.