I’m using Rails 4.2.1 and Devise and rails_admin and I’m quite new to Rails.
I have a user model in the project and a login module for the users. But I need to add Rails Admin authentication. I added a new model Admin for the purpose. I have already set up basic authentication for the Rails Admin login. But now I need to remove basic authentication and add a login page for Rails Admin. What changes do I have to do?
As for my code, I am currently using this for basic authentication:
RailsAdmin.config do |config|
config.authenticate_with do
authenticate_or_request_with_http_basic('Site Message') do |username, password|
authenticate_admin username, password
end
end
end
I have added a method authenticate_admin in application_controller that I want to use for authentication instead.
As you are using devise with rails admin, you can use devise for the authentication.
In your rails_admin.rb add the following code:
config.authenticate_with do
warden.authenticate! scope: :user
end
config.current_user_method(&:current_user)
Related
How do you implement authentication with the rails_admin gem when you are not using devise e.g. you have rolled your own authentication?
In config/initializers/rails_admin.rb include a config.authenticate_with block and place your authentication logic there. It should raise an exception if the user is not authorised to use rails_admin. Here is a simple example:
RailsAdmin.config do |config|
config.authenticate_with do
raise 'You must be admin' unless signed_in? && current_user.admin?
end
end
If you want to follow the rails_admin instructions for the cancancan gem then also add the following config line:
config.current_user_method(&:current_user)
I have two devise models, user and admin, When user and admin login through login form, then will redirect to /admin
I have read the rails_admin wiki, but it seems just about configuration about single devise model, Can I define multi warden scope like following:
RailsAdmin.config do |config|
config.authenticate_with do
warden.authenticate! scope: [:user,:admin]
end
config.current_user_method(&:current_user)
config.current_admin_method(&:current_admin)
end
You can add more than one devise model. Here is an example (with a checksum authentication):
# initilizer/devise.rb
Devise.setup do |config|
config.warden do |manager|
manager.strategies.add :admin, Admin::ChecksumAuthenticatable
end
end
You class Admin::ChecksumAuthenticatable (for example) needs to inherit from ::Devise::Strategies::Base. Then define all methods you want and overwrite authenticate! method:
def authenticate!
admin = Admin.from_checksum_for_auth!(checksum)
# from_checksum_for_auth! is defined on Admin model and check checksum validity
success! admin
end
I'm trying to install the Rails Admin Gem using Sorcery for authentication instead of Devise.
Rails admin does provide a hook that you can use to attach your own authentication method. Here is the example they provide in their docs (using warden):
config.authenticate_with do
warden.authenticate! :scope => :admin
end
config.current_user_method { current_admin }
I'm guessing that inside the block I need to reference the before_filter that Sorcery uses to authenticate users, which would be require_login.
However, when I try that and I try to visit /admin when logged out, I get a routing error:
No route matches {:action=>"new", :controller=>"sessions"}
This probably happens because I am being redirected within the engine rather than in the main app.
How can I set this up correctly?
# config/initializers/rails_admin.rb
RailsAdmin.config do |config|
config.authenticate_with do
# Use sorcery's before filter to auth users
require_login
end
end
# app/controllers/application_controller.rb
class ApplicationController
# Overwrite the method sorcery calls when it
# detects a non-authenticated request.
def not_authenticated
# Make sure that we reference the route from the main app.
redirect_to main_app.login_path
end
end
#config/initializers/rails_admin.rb
RailsAdmin.config do |config|
...
config.parent_controller = 'ApplicationController'
end
If you use Sorcery with Cancancan gem, you should also add config.current_user_method(&:current_user) in your config/initializers/rails_admin.rb file, or you'll get the error: You are not authorized.
I have been using devise for authentication and cancan for authorization in my application. The application worked fine with them. But now i wanted to use active admin to manage all the users that are already in my application that are being used by devise and cancan. Active admin creates its own admin_users table for the users. how can i make active_admin use the users and roles table that was previously in use? thanx for your help.
If you already have the users table created, so you should skip the creation of this table.
Running:
rails generate active_admin:install --skip-users
And don't forget to run:
bundle exec rake db:migrate
Be attempt to change the authentication method on the config/initializers/active_admin.rb file. Also make sure you have the current_admin_user method created, if you don't, you can just modify it to the devise defaults (current_user method).
You will have to modify the http method used in the logout link to :delete.
config.logout_link_method = :delete
And the route path to the logout action.
config.logout_link_path = :destroy_user_session_path
For better understand the authenticate method, I'm pasting my app/controllers/application_controller.rb relevant code:
class ApplicationController < ActionController::Base
protect_from_forgery
#
# redirect registered users to a profile page
# of to the admin dashboard if the user is an administrator
#
def after_sign_in_path_for(resource)
resource.role == 'admin' ? admin_dashboard_path : user_path(resource)
end
def authenticate_admin_user!
raise SecurityError unless current_user.try(:role) == 'admin'
end
rescue_from SecurityError do |exception|
redirect_to root_path
end
end
Hope it helps you and maybe someone else.
By default it will create a new Devise user / model called AdminUser. To change the name of the user class, simply pass the class as the last argument:
rails generate active_admin:install User
http://activeadmin.info/docs/0-installation.html
http://activeadmin.info/docs/1-general-configuration.html#authentication
if you already ran the activeadmin commands.... you can use existing users table by changing
admin_user to user in active_admin.rb in initializer and define an ability for admin in cancan ability model.Also you have to do something like authorize admin to authorize DSL
My setup: Rails 3.0.9, Ruby 1.9.2, Devise 1.3.4, Warden 1.0.4
I'm trying to figure out if it possible to authenticate a custom strategy and not have to create a devise user in the process upon successful authentication. In my config.warden block, the authentication works fine but if I don't create a Devise user, I won't be authenticated. My ideal scenario requires me to either successfully authenticate against a 3rd party provider and sign into my app (using Devise without a corresponding Devise user record) or if I fail to authenticate, then try Devise standard login path.
Here is the devise.rb code snippet I got working but I have to create a devise user for the authentication to work, this is something I wish to avoid
config.warden do |manager|
manager.strategies.add(:custom_strategy) do
def valid?
params[:user] && params[:user][:email] && params[:user][:password]
end
def authenticate!
...perform authentication against 3rd party provider...
if successful_authentication
u = User.find_or_initialize_by_email(params[:user][:email])
if u.new_record?
u.app = 'blah'
u.save
end
success!(u)
end
end
end
manager.default_strategies(:scope => :user).unshift :custom_strategy
end
I realized the question is old but I saw it a couple of time when I was searching for a solution to similar thing so I decided to post the answer in case anyone in the future stumbles upon similar issue. Hope this will help!
I recently had to do similar thing -> had users in my database that were authenticated with some devise/warden strategies but had created another app that has to have access to some of the endpoints to my application. Basically I wanted to do a HMAC authentication.
But I didn't want to involve any user objects in that process and here is what I had to do (provided that you already have you custom strategy that authenticates incoming request without using user object)
create a fake user model that is used so that devise wont blow op. You dont have to create any database table for that
mine looked similar to below:
class Worker # no need to create a table for him
extend ActiveModel::Callbacks
extend Devise::Models
include ActiveModel::Validations
include Concerns::ObjectlessAuthenticatable
define_model_callbacks :validation
attr_accessor :id
def persisted
false
end
def initialize(id)
#id = id
end
def self.serialize_from_session(id)
self.new(id: id)
end
def self.serialize_into_session(record)
[record.id]
end
def self.http_authenticatable
false
end
end
then in devise initializer (/initializers/devise.rb) I've added separate authentication strategy like below:
...
config.warden do |manager|
manager.scope_defaults :user, :strategies => [
...strategies i was using for users
]
manager.scope_defaults :worker, :strategies => [:worker_authentication], store: false, action: 'unautenticated_worker'
manager.failure_app = CustomFailingApp
end
...
then in routes.rb I had to create a mapping for devise to use like so
devise_for :worker # you can pass some custom options here
then wherever I needed to authenticate the worker, not the user I just had to call (in the controller) authenticate_worker!
I would expect that this is against the design of devise where all actions are done using restful routes for a resource. That said, the comments in Warden's success! method say:
# Parameters:
# user - The user object to login. This object can be anything you have setup to serialize in and out of the session
So could you not change the object u to some other object that represents the user, like a plain old Hash?