The "require_no_authentication" can cause failures

1,311 views
Skip to first unread message

Andrew

unread,
Mar 25, 2010, 2:46:16 PM3/25/10
to Devise
In Devise (1.0.4, I'm on Rails 2.3, but Devise 1.1 looks the same
here), SessionsController tries hard to make login work nicely:

* User logs in successfully ("sessions_controller.rb" line 20)
* Flash is set to a welcome message (line 21)
* User is redirected to a previous stored path or the default path via
"after_sign_in_path_for()" (line 22, then "sign_in_and_redirect()" in
"helpers.rb", line 139)

After upgrading from an earlier (possibly 0.8/0.9-ish) version of
Devise to 1.0.4 [1], I found that login flashes no longer worked and
I'm always dumped at my root path when I log in, with previously
stored paths ignored. This confused me a lot, until I noticed this in
my script/server console output:

Processing SessionsController#create (for 127.0.0.1 at 2010-03-25
17:55:29) [POST]
[...]
Redirected to http://localhost:3000/
Filter chain halted as [:require_no_authentication]
rendered_or_redirected.

The sessions controller uses a before_filter which runs every login
attempt through "require_no_authentication". This is a very simple
method in "internal_helpers.rb" which in Devise 1.x reads:

def require_no_authentication
redirect_to after_sign_in_path_for(resource_name) if
warden.authenticated?(resource_name)
end

Clearly, in SessionsController's "create" action, I should not yet be
logged in. So how come the before_filter-based
"require_no_authentication" is causing a redirection? Clearly, it
thinks I *am* logged in already. This on the face of it is impossible
- except my own application has a raft of before_filter calls in
ApplicationController.

Should any of my ApplicationController filters happen to use
"current_user" in any context, this accidentally forces "lazy logon"
due to the Devise implementation of that method calling
"warden.authenticate(:scope => :#{mapping})". This is the exact same
call (in a different form) which the "create" action will itself make.
Thus we end up logged on *before* the controller's action runs,
because the Devise SessionsController before_filter is run after the
ApplicationController's before_filter.

Apart from putting in ":except" conditions and a great deal of
commenting in my application's before_filter calls to avoid anything
that might possibly go near current_user, is there a better way to
avoid this accidental early logon problem?

If nothing else, this message might (bit of a long shot) serve useful
if anyone else in future encounters the same or a similar problem and
stumbles across the thread while searching for a solution.


[1] Footnote: Noticing the change in login behaviour with a change in
Devise version may just be coincidental. If I'm reading the git
history correctly, 0.8/0.9-era Devise versions worked in the same way.
So, changes which were happening at the same time in my own
application may well be to blame - coming from Restful Authentication
and moving to Devise, I was moving quite a few lazy uses of
"@current_user" to a "current_user" method call and this could well
have triggered the problem.

José Valim

unread,
Mar 25, 2010, 3:03:34 PM3/25/10
to plataforma...@googlegroups.com
Hey mate,

Could you please open your Devise gem and change:

before_filter :require_no_authentication

To:

prepend_before_filter :require_no_authentication

And see if it works without you needing to add an :except in your before_filter?

And *thank you* for such a detailed explanation of the issue!

Regards,

To unsubscribe from this group, send email to plataformatec-devise+unsubscribegooglegroups.com or reply to this email with the words "REMOVE ME" as the subject.



--
José Valim

Director of Engineering - Plataforma Tecnologia
Know more about us: http://plataformatec.com.br/en/

Andrew Hodgkinson

unread,
Mar 25, 2010, 3:15:08 PM3/25/10
to plataforma...@googlegroups.com
On 25/03/2010 19:03, Jos� Valim wrote:

> [change] before_filter :require_no_authentication
> [to] prepend_before_filter :require_no_authentication

That works well. It's a cunning solution, because no matter how I add
filters in my application controller, the session controller subclass
will always get to add its filters last and thus should always force
itself to the head of the filter chain.

I suppose there's still a chance to get a filter installed even earlier
in the chain via some kind of strange gem or plugin arrangement perhaps,
but it seems like a pretty good fix for the majority of cases.

If this is likely to get applied as a fix to the Devise sources, is there
any chance of pushing out a new 1.0.x version as well as updating the
1.1.x branch? I've no immediate plans to upgrade this application to
Rails 3 and I'd like to avoid having to freeze a copy of a specially
modified Devise 1.0.4 gem if possible.

--
TTFN, Andrew Hodgkinson
Find some electronic music at: Photos, wallpaper, software and more:
http://pond.org.uk/music.html http://pond.org.uk/

José Valim

unread,
Mar 25, 2010, 3:18:16 PM3/25/10
to plataforma...@googlegroups.com
Yes, we are applying bug fixes to both branches. :)

I will probably release a new Devise version for 1.0.x tomorrow.
Thanks again for reporting and investigating it!

On Thu, Mar 25, 2010 at 8:15 PM, Andrew Hodgkinson <ahod...@gmail.com> wrote:
To unsubscribe from this group, send email to plataformatec-devise+unsubscribegooglegroups.com or reply to this email with the words "REMOVE ME" as the subject.

Andrew Hodgkinson

unread,
Mar 25, 2010, 3:21:25 PM3/25/10
to plataforma...@googlegroups.com
On 25/03/2010 19:18, Jos� Valim wrote:

> Yes, we are applying bug fixes to both branches. :)

That's good news, thanks.

> I will probably release a new Devise version for 1.0.x tomorrow.
> Thanks again for reporting and investigating it!

No problem - great to have such a swift solution, thanks again.

José Valim

unread,
Mar 26, 2010, 8:11:18 AM3/26/10
to plataforma...@googlegroups.com
Gem released!

On Thu, Mar 25, 2010 at 8:21 PM, Andrew Hodgkinson <ahod...@gmail.com> wrote:
To unsubscribe from this group, send email to plataformatec-devise+unsubscribegooglegroups.com or reply to this email with the words "REMOVE ME" as the subject.
Reply all
Reply to author
Forward
0 new messages