I am building a web app (with an API too) that is using Devise gem for authentication and I also use Doorkeeper gem for authentication for the API part.
Problem is now that when I go to the URL for receiving the Oauth2 code (and login) I am redirected to the web app and not the client callback URL.
What I need to do is redirect to the web app when signing in normally and to the callback URL when using Oauth.
How can I do this? I am overwriting the Devise sessions controller but I do not know what to put into it.
This is my code:
def new
session[:return_to] = params[:return_to] if params[:return_to]
resource = build_resource
clean_up_passwords(resource)
end
def create
resource = warden.authenticate!(auth_options)
sign_in(resource_name, resource)
if session[:return_to]
redirect_to session[:return_to]
session[:return_to] = nil
else
respond_with resource, :location => after_sign_in_path_for(resource)
end
end
Problem is that Devise seems to ignore my redirect logic.
Please advice further.
Assuming your resource is user add session[:user_return_to] = request.fullpath to resource_owner_authenticator block
Example:
resource_owner_authenticator do
#raise "Please configure doorkeeper resource_owner_authenticator block located in #{__FILE__}"
# Put your resource owner authentication logic here.
# Example implementation:
session[:user_return_to] = request.fullpath
current_user || redirect_to(login_url)
end
This worked for me, in ApplicationController (that Devise's controllers inherit from):
def store_location
# store last url as long as it isn't a /users path
session[:previous_url] = request.fullpath unless request.fullpath =~ /\/users/
end
def after_sign_in_path_for(_resource)
session[:previous_url] || root_path
end
And in the Doorkeeper initializer:
resource_owner_authenticator do
if user_signed_in?
current_user
else
session[:previous_url] = request.fullpath unless request.fullpath =~ /\/users/
redirect_to(new_user_session_path)
end
end
The idea is to remember the path you came from in a session cookie and then let Devise redirect there when it calls its own after_sign_in_path_for callback.
Documentation pointed out the resource_return_to session key, but this worked for me so I didn't examine anymore.
Related
In my application controller I have something like this:
after_filter :store_location
def store_location
# store last url as long as it isn't a /users path
session[:previous_url] = request.fullpath unless request.fullpath =~ /\/users/
end
def after_sign_in_path_for(resource)
session[:previous_url] || root_path
end
This works fine for storing the previous url, however on some pages I automagically redirect to the sign in page like so:
before_filter :require_login
def require_login
unless current_user
redirect_to new_user_session_path
end
end
On pages where the user is redirected (with the require_login filter) it does not store the previous url. It simply defaults them to the root_path.
How can I properly store the previous url for users who are redirected?
devise provides this method called stored_location_for which will do the work for you
def after_sign_in_path_for(resource)
stored_location_for(resource) || root_path
end
Figured it out. The issue was that I using:
after_filter :store_location
but the storing of the url needed to happen right away (before the redirect). So the problem was solved by using:
before_filter :store_location
and making sure it falls before:
before_filter :require_login
I've got the following defined in my application_controller.rb file:
def redirect_back_or(default)
redirect_to(session[:return_to] || default)
session.delete(:return_to)
end
def store_location
session[:return_to] = request.url
end
def after_sign_in_path_for(resource)
r = session[:return_to] || user_root_url
session.delete(:return_to)
r
end
I'm trying to send a user back to the place they came from before the sign_in, or, if no location is saved, send them to their root page.
I call this in one of my controllers:
if current_user.nil?
store_location
redirect_to home_login_url, alert: "You must be logged in to purchase subscriptions"
return
end
I stepped through the debugger and watched the session[:return_to] get set, but after I log on and the after_sign_in_path_for(resource) is called, session[:return_to] is null.
How can I persist the return_to variable across a login?
I'm running Rails 3.2.1 and Devise 2.1.2
Turns out I was overwriting Devise's entry in my hash. I think :return_to is what Devise uses. I ended up implementing this completely differently, but look for name conflicts if you have a problem
For the app that I am writing, I am using simple hand made authentication (as described on Railscast.com). Using some code from Ryan Bates' NiftyGenerators gem, I have an authentication model that has some useful methods for authentication. This module is included into application_controller.rb.
One of the methods that I want to use is called redirect_to_target_or_default. I know this is what I need to redirect a user to the page that they were on once they have authenticated but I don't know where I should call this method? If someone could give me an idea on how to use this method, I would greatly appreciate it.
ControllerAuthenticaion Module Code
module ControllerAuthentication
# Makes these methods helper methods in the controller that includes this module.
def self.included(controller)
controller.send :helper_method,
:current_admin, :logged_in?,
:redirect_to_target_or_default
end
def current_admin
#current_admin ||= Admin.find(session[:admin_id]) if session[:admin_id]
end
def logged_in?
current_admin
end
def login_required
unless logged_in?
store_target_location
redirect_to login_url,
:alert => "You must first log in before accessing this page."
end
end
def redirect_to_target_or_default(default, *args)
redirect_to(session[:return_to] || default, *args)
session[:return_to] = nil
end
def redirect_to_or_default(target, *args)
redirect_to(target || default, *args)
end
def store_target_location
session[:return_to] = request.url
end
end
Did you run the generator(s) within Ryan's gem? It should have generated a SessionController (refer to link) for you with also this method in it:
def create
#session = Session.new(params[:session])
if #session.save
flash[:notice] = "Logged in successfully."
redirect_to_target_or_default(root_url)
else
render :action => 'new'
end
end
I think you can get an idea of how to use it while reading this code. :)
I want to have a sign in page that redirects to user the last page he were before sign in. How could I do it in Rails. Do I need to override after_sign_in_path for each link of how?
Thanks :)
The short answer is yes, you will need to override the after_sign_in_path The simplest method I have found to do so is as follows:
Inside of your application controller you will need to add two methods,
include SessionsHelper
def after_sign_in_path_for(resource_or_scope)
case resource_or_scope
when :user, User
store_location = session[:return_to]
clear_stored_location
(store_location.nil?) ? requests_path : store_location.to_s
else
super
end
end
def check_login
if !anyone_signed_in?
deny_access
end
end
First we override the after_sign_in_path to save our new stored location which we pull from the Rails session into our store_location which we will define in our SessionsHelper. Next we create a method that we can use as a before_filter in any controller we want to use this on.
Next, set up sessions_helper.rb
module SessionsHelper
def deny_access
store_location
redirect_to new_user_session_path
end
def anyone_signed_in?
!current_user.nil?
end
private
def store_location
session[:return_to] = request.fullpath
end
def clear_stored_location
session[:return_to] = nil
end
end
Here we're just defining the methods we used inside of our application controller, which should all be pretty self explanatory. Just remember to use before_filter :check_login before any other before filters in the controllers you are wanting to remember the previous path for.
During a post for a new model, I am checking for authentication via Authlogic. There is a before_filter on the create request. It is calling require_user. After the user session has been successfully created, the redirect_back_or_default(default) method is called. The problem is, The request needs to be posted to the stored uri. I have tried to store the method and input it into the redirect_to however it isn't working. Any ideas?
# called before successful authentication with before_filter
def require_user
unless current_user
store_location
flash[:notice] = "You must be logged in to access this page"
redirect_to new_user_session_url
return false
end
end
def store_location
session[:return_to] = request.request_uri
session[:return_to_method] = request.request_method
end
# called after successful authentication
def redirect_back_or_default(default)
redirect_to((session[:return_to] ? session[:return_to] : default), :method => session[:return_to_method])
session[:return_to] = nil
session[:return_to_method] = nil
end
You can't redirect to a post action, only get actions.
You could store the post object for later processing after authentication, but you really don't want to do that.
Why not simply ask for authentication on the #new method, rather than (or in addition to) the #create? That way the user is authenticated before they fill in the form.