Where should warden callbacks be placed in a rails app? - ruby-on-rails

I'm relatively new to rails. I have Devise set up, and want to run some callback code after users sign in.
Looking at the Warden wiki page, I can use the "after_set_user" callback to perform this logic, for example:
Warden::Manager.after_set_user do |user, auth, opts|
unless user.active?
auth.logout
throw(:warden, :message => "User not active")
end
end
However, I'm not sure where I should be storing this stuff. My first thought is that I could put it in config/initializers/devise.rb. Is that correct? It doesn't feel right putting what is essentially controller code in the config directory.

Warden hooks need to be required when your application is booting, so inside Devise's initializer at config/initializers/devise.rb is a good candidate.
However, the behavior you want to achieve will be better accomplished by using this Devise feature:
https://github.com/plataformatec/devise/wiki/How-To:-Customize-user-account-status-validation-when-logging-in

Related

Devise ignore my custom strategy

I want to create a custom auth strategy for accessing the API. I followed the example code at Devise ignoring custom strategy.
The problem is that the valid? method in my Api strategy is never run (based on trying to pry in it).
My code:
module Devise
module Strategies
class Api < Devise::Strategies::Base
def valid?
binding.pry
params[:request_source] == 'api'
end
def authenticate!
#do stuff here
if user
success!(user)
else
warden.custom_failure!
render :json=> {:success=>false, :message=>"Error with your login or password"}, :status=>401
end
end
end
Warden::Strategies.add(:api, Devise::Strategies::Api)
end
end
and in the devise initializer:
config.warden do |manager|
manager.default_strategies.unshift :api
end
What ever I do, it seems like Devise always use its default strategy. AFAIK, this should be enough...
-------EDIT--------
I require the strategy like this at the very top of my devise initializer:
require Rails.root.join('app/devise/strategies/api')
I know the strategy is loaded at boot time since if I put a pry call inside the class, it will start a pry session. But the Pry calls inside the methods are never run. :-S
Found the answer!
I had to use this:
config.warden do |manager|
manager.default_strategies(scope: :user).unshift :api
end
to make it work. Weird thing is, a lot of the sample code I saw on the net did not use it :-S
When are you requiring your custom strategy? Comparing to the example, you are adding the strategy there instead of in your initializer. You might try requiring the custom strategy at the top of your initializer to make sure it's loaded before you add it to default_strategies.
If that doesn't do the trick, don't be afraid to add some temporary puts statements right in devise itself where authenticate is called to check default_strategies. That is, if you're not already confortable using the debugger, which is what I would do.

Does devise have 'callback'?

After a user log in, I want to manually log this event and increment a counter column in database.
Is there something like after_login in Devise? Just as ActiveRecord's before_save?
Devise uses Warden behind the scenes and Warden supplies you with a number of callbacks:
https://github.com/hassox/warden/wiki/callbacks
Have a look at the after_authentication callback. That's what you are looking for.
Code:
Warden::Manager.after_authentication do |user, auth, opts|
# your code here..
end
You can simply create a new initializer file and put the code there. (Like /config/initializers/warden_callbacks.rb)

override "/auth/identity"-page of omniauth identity

I'm using omniauth without devise for authentication, as I like it's simplicity. In addition to omniauth-facebook I use omniauth-identity to offer email/pw-authentication.
The railscast on omniauth-identity describes how to setup a customized registration and login page. But the default routes supplied by identity (/auth/identity and /auth/identity/register) are still accessible.
I would like to have these under my control, as I want only want to let invited users register. Is there any way to override those routes supplied by a rack middleware?
Trying to just
match "/auth/identity", to: "somewhere#else"
doesn't do the trick!
Is there maybe a configuration to turn these default routes off? The documentation isn't giving any details on this...
Unfortunately I'm fairly new to Rack, so I don't have enough insight yet, to solve this issue on my own!
I'd be glad, if someone could point me in the right direction!
An OmniAuth strategy object has a method request_phase which generates a html form and shows it to user. For "omniauth-identity" strategy this would be the form you see at /auth/identity url.
You can override the request_phase method and replace the form generator with, for example, a redirect to your custom login page (assuming you have it available at /login url). Place the following along with your omniauth initialization code:
module OmniAuth
module Strategies
class Identity
def request_phase
redirect '/login'
end
end
end
end
# Your OmniAuth::Builder configuration goes here...
In addition to 1gors and iains answer:
"/auth/identity/register" is served with GET as well, to override, I had to:
class OmniAuth::Strategies::Identity
alias :original_other_phase :other_phase
def other_phase
if on_registration_path? && request.get?
redirect '/sign_up'
else
original_other_phase
end
end
end
You can set method in omniauth.rb
:on_login => SessionsController.action(:new)
for example:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :identity,
:fields => [:nickname],
:on_login => SessionsController.action(:new),
:on_registration => UsersController.action(:new),
:on_failed_registration => SessionsController.action(:registration_failure)
end

Removing a Warden strategy - how to ensure original devise_authenticable strategy is gone

I created my own Warden strategy for using with Devise. It's very similar to Devise::Strategies::DatabaseAuthenticatable and actually it inherits from it and re-implements authenticate!
My issue though is that I want to make sure the original devise_authenticable Warden strategy is gone. That is not in the list of strategies Warden will try because it's actually a security problem. Is that possible?
According to my manual inspection and tests, this in the devise.rb initializer achieves the goal:
config.warden do |manager|
strategies = manager.default_strategies(:scope => :user)
strategies[strategies.index(:database_authenticatable)] = :alternative_strategy
end
And the strategy is implemented this way (not part of this question, but I found conflicting information out there and this one is the one that worked for me using Rails 3.1, devise 1.4.7 and warden 1.0.5):
class AlternativeStrategy < Devise::Strategies::Authenticatable
def authenticate!
end
end
Warden::Strategies.add(:alternative_strategy, AlternativeStrategy)
I just implemented this as well. Devise will try each strategy in its list until one succeeds.
For me, rather than replace the :database_authenticatable strategy in place, I just added my strategy to the beginning of the list and popped :database_authenticatable off the end of the existing list.
config.warden do |manager|
# Exiles::Devise::Strategies::BySite implemented in lib/. It matches the stub in Pablo's answer
manager.strategies.add( :by_site_auth, Exiles::Devise::Strategies::BySite )
# add my strategy to the beginning of the list.
manager.default_strategies(:scope => :user).unshift :by_site_auth
# remove the default database_authenticatable strategy from the list
manager.default_strategies(:scope => :user).pop
end

after_filter in devise

I would like to execute an action after the user has logged in. I need something like:
after_filter :log_login
The method should be called as soon as the user has logged in.
You could try inheriting the sessions controller, and add more of your custom login proc. http://github.com/zmbmartin/devise-roles-user-management. I use this as an example, it inherit registration controller, not example the same, but the principle is the same.
As already answered here:
Devise uses Warden behind the scenes and Warden supplies you with a number of callbacks:
https://github.com/hassox/warden/wiki/callbacks
Have a look at the after_authentication callback. That's what you are looking for.
Code:
Warden::Manager.after_authentication do |user, auth, opts|
# your code here..
end
You can simply put that code into an initializer (eg. config/initializers/warden_callback.rb)

Resources