I have a Rails site that uses Devise for authentication. I have one page (PhotosController#create) that needs to authenticate users without cookies. I’m doing this with the :token_authenticatable module of Devise, which authenticates a user if the supplied token matches the token stored on the server side. (See this SO question if you’re curious.)
It’s good policy to expire or change the token after the action is complete. This prevents an attacker from sniffing the token and using it to successfully authenticate as the user. However, in my case, I can’t expire or change the token because the client-side photo uploader uploads multiple photos, each resulting in a separate POST to PhotosController#create. So if I expire the token after a successful create, the second, third, etc. uploads will fail.
Devise modules are specified at the model level (e.g. the User model). I need more granularity than this.
My question is, how do I enable the :token_authenticatable module only for a single action of a single controller? Or, equivalently, how do I disable the :token_authenticatable module for all controllers and actions except for one action?
As the developer of one devise plugin (devise_rpx_connectable) I’m happy to answer your question.
TokenAuthenticatable is one Devise strategy, you can read its code here :
https://github.com/plataformatec/devise/blob/master/lib/devise/strategies/token_authenticatable.rb
As you can see, each devise strategy has a valid? and/or valid_request? method that is called to determine if the strategy should be enabled. So you can easily override this strategy for your needs, or you can also only override the valid_request? method. Just load this kind of code in an initializer (AFTER devise is loaded of course) :
I haven’t tested this, I don’t know if that works out of the box but I hope you see the point, if that doesn’t work, use a debugger, or write your own Devise Strategy (see my plugin, it’s easy to understand), etc.
Moreover, when you use this strategy, the user will be stored in session unless you use the stateless_token option, see :
https://github.com/plataformatec/devise/blob/master/lib/devise/models/token_authenticatable.rb#L27