Devise: Custom fallback function for authenticate_user - ruby-on-rails

I want to write a function which sets cookie when user is not authenticated. So after authenticate_user! if user is not authenticated the cookie is set. Can this be done in devise.
I tried doing it by customizing authenticate_user! function, but can't find anything.
Thanks

Are you using before_filter to call authenticate_user!? Can't you just do:
before_filter do
authenticate_user!
your_cookie_method if current_user.nil?
end

Related

How to logout user logged in with custom devise strategy

I need to logout a user that has been logged in my Rails app using custom Devise authentication strategy. This strategy is used in addition to database_authenticable strategy. Is there a logic I need to add to my custom implementation of authenticate_user! method in custom strategy? Also do I need to implement destroy method in a custom sessions controller?
Currently my custom strategy logs in the user fine (hard coded for now) but I cannot logout the user as logout action calls my custom implementation of authenticate_user! again and they are logged in again.
You can use skip_before_action callback in this case like in your controller put below code before all actions
skip_before_action :authenticate_user, only: [:your_logout_action]
This will skip authentication for your method and user won't log in again.
So far as I understood correctly, is that, let any action to logout the current_user in devise. If it's so then it can be implemented like this
Let's say ,
class SomeController < ApplicationController
before_action :authenticate_user!
def some_action
if some_logic == true #implement some_logic to return boolean(true/false)
sign_out resource
flash[:notice] = ''
flash[:error] = 'You are logged out!'
root_path
end
end
end
I was able to fix my issue. The issue was that I had hard coded valid? method to return true all the time. When I added the logic to return true only if email and password params are present then the custom auth works as expected.
Make user log out by manually.
sign_out(current_user) if current_user.present?

Sign out a devise user from a model

In my application, I need to sign out specific users from time to time. And I need to do it from the interface or from a sidekiq worker. So I would like to create a sign_out method in my user model.
I saw in the documentation that devise provides a sign_out method but only in the controller. Is there a way to access to this method from a model or something similar.
Thanks
You need to read this answer https://stackoverflow.com/a/24388643/4269732 first.
If I was to implement this behavior then I would have added a column in User Model like expire_at_next_request?
Then just check this value in before_filter and logout the user if this is true.
class ApplicationController < ActionController::Base
before_filter :logout_if_requested
def logout_if_requested
if current_user && current_user.expire_at_next_request?
current_user.update_attributes(:expire_at_next_request=>false)
sign_out current_user
redirect_to :new_session_path
end
end

Set a session variable in devise on sign in

I'd like to set a session variable once a user signs in based on a certain field in the User table. I don't want to have to create a custom Devise controller if I don't have to. Is there a way? Or will I have to go the custom controller route?
There is a callback after_sign_in_path_for, you can add it in your ApplicationController
protected
def after_sign_in_path_for(resource)
session[:domain_prefix] = current_user.domain_prefix
user_path(resource)
end
Dont forget return the path in the last line of method, otherwise the callback will redirect the request to content of session[:domain_prefix]
How about this one:
The first resource I'd look at is http://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-a-specific-page-on-successful-sign-in. Also, check out How to redirect to a specific page on successful sign up using rails devise gem? for some ideas.
You can do something like:
def after_sign_in_path_for(resource_or_scope)
session[:account_type] = current_user.account_type
end
You can implement this method in your ApplicationController or in a custom RegistrationsController.

before_filter with devise

I'm using Devise's built in before_filter :authenticate_user!. I want to call my own custom method in my application helper if a user fails the before filter (tries to do an action when logged out). How and where can I do this?
I would write a custom before filter that uses user_signed_in?. This will just return a boolean, and not do any of the redirect-type actions that authenticate_user! does.
So, you could write a before filter like this:
before_filter :custom_user_auth
...
def custom_user_auth
unless user_signed_in?
# Do custom stuff, ultimately restricting access to the
# ...protected resource if it needs to be
end
end
Do note that this before filter won't protect your resource from unauthorized users unless the inside area of that unless statement redirects or renders.
Instead of calling before_filter :authenticate_user! write your own function in your controller that calls authenticate_user!. Something like:
before_filter :logged_in
...
private
def logged_in
your_function
authenticate_user!
end

Rails: Devise redirect to a stored location after sign in or sign up?

I'm using Devise in a Rails application I'm writing, and I want to let users go back to where they were after signing in or signing up.
For example, if I have a "comments" Controller that is protected by:
before_filter :authenticate_user!
Then I want users who click a "Comment Now!" button (and are therefore redirected to the new action in CommentsController) to log in and then have Devise redirect them to the new action (or wherever they were) in CommentsController, not to the generic root of the application, or to a generic after_sign_in_path.
Looking through the RDOC for Devise, I found this method that makes it look as if Devise has at least the capability to do something like this on its own, but I can't figure out a way.
OK, so I've done some more experimentation, and working with Kormie's info, I've got a working solution.
From what I can determine, before_filter authenticate_user! does not save the route for returning the user. What I did was this:
First, I added an extra before_filter at the top of my controller
before_filter :store_location
before_filter :authenticate_user!
Then, I wrote the store_location method at the bottom of the controller
private
def store_location
session[:user_return_to] = any_old_route_path
end
I don't claim this is perfect, but it works for me. (The downside for anyone else wanting to use it, is that it only supports one return path per controller. This is all I need for myself, but it is only a slight improvement over the one return path per app that I was using previously.) I would really appreciate anyone else's insights and suggestions.
Devise should do this by itself. The authenticate_user! filter also did not want to work for me when the route to the action was set via PUT method. When I have changed this to GET in routes.rb devise started to work as expected.
The simple way to do this:
# Modified from https://github.com/plataformatec/devise/wiki/How-To:-redirect-to-a-specific-page-on-successful-sign-in
class ApplicationController < ActionController::Base
def after_sign_in_path_for(resource)
stored_location_for(resource) || your_defaut_path
end
end
I think by default Devise saves the route but you may be usinging
sign_in #user
this should redirect you
sign_in_and_redirect(#user) #assuming you are sigining in that resource
Have you tried after_sign_in_path_for? If you define that method in your ApplicationController it should override the default implementation on a per controller basis.
Adapted from Devise Wiki how to:
Redirect back to current page after sign in, sign out, sign up, update
Redirecting back to the "current page" involves saving the current url in the session and then retrieving the url from the session after the user is authenticated / signed out. This should only really be done for GET requests as the other http methods (POST, PUT, PATCH, DELETE) are not idempotent and should not be repeated automatically.
To store the location for your whole application use before_action to set a callback (Use before_filter in Rails versions before 4.0).
This example assumes that you have setup devise to authenticate a class named User.
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :store_user_location!, if: :storable_location?
# The callback which stores the current location must be added
# before you authenticate the user as `authenticate_user!` (or
# whatever your resource is) will halt the filter chain
# and redirect before the location can be stored.
before_action :authenticate_user!
# To redirect to the stored location after the user signs
# signs in you would override the after_sign_in_path_for method:
def after_sign_in_path_for(resource_or_scope)
# *My note, not wiki*: you may need a fall back as
# stored_location_for can return nil. I've added root_path
stored_location_for(resource_or_scope) || root_path
end
private
# Its important that the location is NOT stored if:
# - The request method is not GET (non idempotent)
# - The request is handled by a Devise controller
# such as Devise::SessionsController as that could
# cause an infinite redirect loop.
# - The request is an Ajax request as this can lead
# to very unexpected behaviour.
def storable_location?
request.get? && is_navigational_format? &&
!devise_controller? && !request.xhr?
end
def store_user_location!
# :user is the scope we are authenticating
store_location_for(:user, request.fullpath)
end
end
Reference
Devise How To: Redirect back to current page after sign in, sign out, sign up, update

Resources