Sign in to Devise using omniauth-facebook - devise

Ryan Bates gives great screencast http://railscasts.com/episodes/360-facebook-authentication how to use "omniauth-facebook" gem. But there is some issues with:
#application_controller.rb
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
helper_method :current_user
It sets #current_user too late for standart Devise auth protection for actions in controllers:
before_filter :authenticate_user!, :except => [:index, :show]
So it redirects to sign in page, even #current_user is aviable in views...
Maybe anyone knows how to fix it?
PS I saw few tricks with redirects handler, but I think there should be better decision...

I have found the simple way to sign in using standart Devise method. Based on this tutorial, just set code in sessions_controller:
#sessions_controller.rb
class SessionsController < ApplicationController
def create
user = User.from_omniauth(env["omniauth.auth"])
sign_in user
redirect_to root_url
end
end
And you can delete this from application controller:
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
helper_method :current_user

Related

can't find method in application controller

I've been trying to get authentication working with devise, and then omniauth, but I haven't been able to get the user session.
In my application controller, I have
class ApplicationController < ActionController::Base
protect_from_forgery
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
helper_method :current_user
end
which I got from the updated railscast https://github.com/railscasts/241-simple-omniauth/blob/master/revised/blog-after/app/controllers/application_controller.rb
In my app, I call
<% if current_user %>
but this always errors out as undefined local variable or method 'current_user'
why is this? is it a problem with my application controller, or maybe a session error with rails?

Rails use not condition with before_filter

I'm using before_filter in my application. I have a method logged_in? which returns true if the user is logged in.
def logged_in?
!!current_user
end
def current_user
#current_user = (User.find(session[:user_id]) if session[:user_id]) || false
end
Now in my users controller I want an action to execute only if a user is not logged in. For this I want to use the not condition with logged_in? method in before_filter as:
before_filter :!(logged_in?)
But this gives me an error. I'm resisting creating a new method for not logged in.
Please help me figure out the correct syntax to accomplish this.
While the accepted answer seems to work, I would have done it differently.
before_filter :login_required, unless: :logged_in?
def login_required
redirect_to login_path, notice: 'Please login'
end
This will execute the method login_required unless the user is already logged in. See http://robots.thoughtbot.com/post/159805303/before-filter-wisdom for more info.
You could pass a block to before_filter:
before_filter { |c| !c.logged_in? }
But this wouldn't really do anything, since the return value from the before filter isn't going anywhere. If you want to execute an action if a user is not logged in, then you should be putting that action into the before_filter.
For example, if the action was to redirect to the login page, path, you could do this:
before_filter { |c| redirect_to login_path unless c.logged_in? }
That's actually long enough to justify a method of its own:
before_filter :login_required
def login_required
redirect_to login_path unless logged_in?
end
application_controller.rb
before_filter :authorize
def current_user
#current_user ||= User.find_by(id: session[:user_id])
end
helper_method :current_user
protected
def authorize
unless User.find_by(id: session[:user_id])
redirect_to login_url, :notice => "Not Authorize Member"
end
end

Integrating ActiveAdmin and adauth

I have a running Rails application, using ActiveAdmin and its models to autenticate users. Now I'm interested in moving to an ActiveDirectory authentication, so my users can validate wiht the domain's users.
I've been trying adauth and it looks like a great gem, but I'm a little bit lost when trying to "mix" this gem with my ActiveAdmin authentication. I'm pretty sure I'm not the first one in doing it, so any help would be appreciated.
Thanks!
I finally was able to manage to integrate AD in ActiveAdmin.
Here's what I did, in case someone is interested:
Include gem 'adauth' in your gems
Execute bundle install
Execute rails g adauth:config
Configure the config/initializers/adauth.rb for your AD connection. For example, if your domain is example.com, you must include:
c.domain = "example.com"
c.server = "IP address of your domain controller"
c.base = "dc=example, dc=com"
Execute rails g adauth:sessions
Modify your application_controller.rb. Mine was:
class ApplicationController< ActionController::Base
protect_from_forgery
helper_method :current_user
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
def authenticate_user!
if current_user.nil?
redirect_to '/sessions/new', :error => "Invalid Login"
end
end
end
Execute rails g adauth:user_model user install_adauth.
This creates the migration install_adauth, but for some reason it was empty. I had to fill it myself with:
class InstallAdauth < ActiveRecord::Migration
def up
create_table :users do |u|
u.string 'login'
u.text 'group_strings'
u.string 'name'
u.string 'ou_strings'
end
end
def down
drop_table :users
end
end
Execute rake db:migrate
Modify your sessions_controller.rb. Mine was:
class SessionsController < ApplicationController
def new
redirect_to '/admin' if current_user
end
def create
ldap_user = Adauth.authenticate(params[:username], params[:password])
if ldap_user
user = User.return_and_create_with_adauth(ldap_user)
session[:user_id] = user.id
redirect_to '/admin'
else
redirect_to '/sessions/new', :error => "Invalid Login"
end
end
def destroy
session[:user_id] = nil
redirect_to '/sessions/new'
end
end
So far the validation through ActiveAdmin still works. To switch to ActiveDirectory we must change the file initializers/active_admin.rb
# config.authentication_method = :authenticate_admin_user!
config.authentication_method = :authenticate_user!
#config.current_user_method = :current_admin_user
config.current_user_method = :current_user
In my case, I needed to restart Apache too.
If anytime we want to switch back to ActiveAdmin, we just need to undo the last change

Why doesn't my current_user helper method work during tests?

I have a Rails 3.2.3 application and I am using MiniTest and Capybara to run my integration tests. I rolled my own authentication and created a current_user helper_method in my application_controller.rb.
My application layout file only displays certain links, like logout, etc., when a user is logged in.
But the current_user method does not work during tests. It looks like this:
class ApplicationController < ActionController::Base
protect_from_forgery
private
def authenticate
if current_user.blank?
redirect_to root_url, :alert => "You must first log in."
end
end
def authenticate_admin
unless current_user and current_user.admin?
redirect_to root_url, :alert => "You must be logged in as an administrator to access this feature."
end
end
def current_user
begin
#current_user ||= User.find(session[:user_id]) if session[:user_id]
rescue
nil
end
end
helper_method :current_user
end
So in my application.html.erb file there is:
<% unless current_user.blank? %>
<li><%= link_to logout_path %></li>
So this works when I test it through the browser, but not in my test. "current_user" ends up being nil.
I am new to BDD, but is there something that prevents sessions from being created during tests? What am I missing?
NOTE: helper methods defined in controllers are not included.
from here.
The solution is to organize them in a dedicated helper class.

Couldn't find User with id=1

I've a current_user method to handle authentication.
application_controller.rb
protect_from_forgery
helper_method :current_user
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
but when I try to acces a to a page I get the following error:
Couldn't find User with id=1
app/controllers/application_controller.rb:10:in `current_user'
How can I pass #current_user a sort of default value so if there's no user it will redirect to login page.
Thanks for helping.
It looks like your session contains old data, specifically an id (1) of a user which no longer exists. Try handling the RecordNotFound exception raised by ActiveRecord, and returning nil:
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
rescue ActiveRecord::RecordNotFound
end
To redirect, you should add a second before_filter which checks for a user and handles redirecting to the login path:
before_filter :require_user
def require_user
redirect_to login_path unless current_user
end
Remember to omit require_user for your login action by adding skip_before_filter :require_login to whichever controller manages your authentication.