Protecting Users::OmniauthCallbacksController

96 views
Skip to first unread message

Claudio Poli

unread,
Apr 25, 2012, 8:20:27 AM4/25/12
to plataforma...@googlegroups.com
I'm trying to guard Users::OmniauthCallbacksController against anonymous users.

If we take a look at lib/devise/controllers/helpers.rb in define_helpers, authenticate_#{mapping} calls warden only if this is not a devise controller or if force.

Since Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController is a devise controller, I though using this:

before_filter :authenticate_user!, force: true

But it still does not have any effect. Should I start using user_signed_in?

Thanks.

Carlos Antonio da Silva

unread,
Apr 25, 2012, 8:37:03 AM4/25/12
to plataforma...@googlegroups.com
The main question is: why would you want to protect this controller against anonymous users? Technically it's for anonymous users to get access to your application right?

I think the best you can do to "protect" your controller, is to redirect to another place in case the omniauth hash is not present in the env - which probably means it didn't come from Facebook.

-- 
At.
Carlos Antonio

Claudio Poli

unread,
Apr 25, 2012, 8:41:58 AM4/25/12
to plataforma...@googlegroups.com
Hello Carlos,
in my app I let users link with third party services not for the sign in with X goal, but to enable additional features afterwards, and since we are using Devise, we find the OmniAuth integration great.
So yes, a valid user session should be required to access the custom Users::OmniauthCallbacksController controller in my case.

Cheers

Carlos Antonio da Silva

unread,
Apr 25, 2012, 8:55:05 AM4/25/12
to plataforma...@googlegroups.com
Hm ok, got it. So yeah, in theory using the normal before_filter with :force option should be the way to go I believe. What happens, do you get any error, does it redirect to somewhere else?

-- 
At.
Carlos Antonio

Claudio Poli

unread,
Apr 26, 2012, 7:51:20 AM4/26/12
to plataforma...@googlegroups.com
I don't get any particular errors using the :force option on the before_filter, it just gets ignored and the controller code goes on the request like it isn't there at all.

*However* if I call via browser my http://0.0.0.0:5000/users/auth/facebook/callback it appears to redirect correctly, but spec fails so I suspect it's something with my spec.

describe Users::OmniauthCallbacksController do
before(:each) do
request.env["devise.mapping"] = Devise.mappings[:user]
end
context "when not signed in", :focus do
it "should be redirected to user sign in" do
User.omniauth_providers.each do |provider|
get provider
response.should be_redirect
# response.code.should eq("401")
end
end
end

Carlos Antonio da Silva

unread,
Apr 26, 2012, 8:26:28 AM4/26/12
to plataforma...@googlegroups.com
Hm yeah, may be. Is this a controller/functional test? Are you using Devise::TestHelpers, right? I think I've never tested a controller for non signed in process like this, and I can't seem to spot anything wrong with your test at a glance.

What's the error, you get a success response? The action is executed normally?

-- 
At.
Carlos Antonio

Claudio Poli

unread,
Apr 26, 2012, 9:25:03 AM4/26/12
to plataforma...@googlegroups.com
Yes, Devise test helpers and all the other stuff. I have this code in controller:

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
before_filter :authenticate_user!, force: true

User.omniauth_providers.each do |provider|
send :define_method, provider do
process_callback
end
end

private
def process_callback

process_callback should not be reached if the user is not logged in but it appears to be (in specs, I tried to investigate because I was having errors in staging due to not signed in users reaching the action although a before_filter is in place).

I tried to tinker around in helpers.rb in self.define_helpers where the method authenticate_#{mapping}! is created, the spec posted previously passes if I remove the if condition from warden.authenticate!(opts); tried swapping the conditions (ruby 1.9.3-p194) but obviously it sorted no effect.

I then tried to check if for some reason opts.delete(:force) was at fault but from a quick inspection it's okay.

I suspect there is more however, still investigating what's up.

Thanks!

Claudio Poli

unread,
Apr 26, 2012, 10:23:45 AM4/26/12
to plataforma...@googlegroups.com
Heads up, it works by doing this in controller:

prepend_before_filter :authenticate_scope!

protected
def authenticate_scope!
send(:"authenticate_#{resource_name}!", :force => true)
self.resource = send(:"current_#{resource_name}")
end

Cheers
Reply all
Reply to author
Forward
0 new messages