I have an API only rails app, with Devise for user management and doorkeeper for token authorization from the Mobile App. This works fine.
I also installed Rails Admin, to manage all of the back end data in my DB and it works fine, I can work with Rails Admin from my browser and the mobile application access data through the API.
So far the Rails Admin dashboard is unprotected and I need to protect it so that only an administrator can modify the data from the DB.
I created another scope for devise with the tutorial from this link https://github.com/plataformatec/devise/wiki/How-to-Setup-Multiple-Devise-User-Models
but when I type the Rails Admin URL, the page is redirected to /admins/sign_in from devise, which I assume is the right behaviour, but then I get the following error:
Started GET "/" for 186.2.132.186 at 2019-06-11 15:14:40 +0000
(0.9ms) SET NAMES utf8, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
↳ /usr/local/rvm/gems/ruby-2.5.5/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
(0.9ms) SELECT `schema_migrations`.`version` FROM `schema_migrations` ORDER BY `schema_migrations`.`version` ASC
↳ /usr/local/rvm/gems/ruby-2.5.5/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
Processing by RailsAdmin::MainController#dashboard as HTML
Completed 401 Unauthorized in 10ms (ActiveRecord: 0.0ms)
Started GET "/admins/sign_in" for 186.2.132.186 at 2019-06-11 15:14:40 +0000
Processing by Admins::SessionsController#new as HTML
Completed 406 Not Acceptable in 16ms (ActiveRecord: 3.2ms)
ActionController::UnknownFormat (ActionController::UnknownFormat):
responders (2.4.1) lib/action_controller/respond_with.rb:213:in `respond_with'
devise (4.6.2) app/controllers/devise/sessions_controller.rb:14:in `new'
...more stack
On Rails ADmin initializer I added the following code:
## == Devise ==
config.authenticate_with do
warden.authenticate! scope: :admin
end
config.current_user_method(&:current_admin)
This are my routes:
#require 'api_constraints.rb'
Rails.application.routes.draw do
use_doorkeeper do
# No need to register client application
skip_controllers :applications, :authorized_applications, :admins
end
#devise_for :admins, path: 'admins'
devise_for :admins, controllers: {
sessions: "admins/sessions",
#registrations: 'admins/registrations',
}, skip: [:registrations]
mount RailsAdmin::Engine => '/', as: 'rails_admin'
#devise_for :users
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
scope module: :api, defaults: { format: :json }, path: 'api' do
scope module: :v1 do
devise_for :users, controllers: {
registrations: 'api/v1/users/registrations',
}, skip: [:sessions, :password]
end
end
#Rutas para acceder al API
#scope '/api' do
namespace :api do
namespace :v1 do
resources :users
resources :ejercicios
resources :medidas
resources :profiles
resources :categoria_ejercicio
end
end
root to: 'home#index'
end
I also included the Devise views for admin with this command
rails g devise:views admins
Can you please give me a hint or suggestion on how to make it work. Thanks.
As you can see in the logs, the /admin/sign_in
path is rejected with a 406 Not Acceptable
http error, which precisely means the requested format (HTML) is not accepted.
Started GET "/admins/sign_in" for 186.2.132.186 at 2019-06-11 15:14:40 +0000
Processing by Admins::SessionsController#new as HTML
Completed 406 Not Acceptable in 16ms (ActiveRecord: 3.2ms)
This happens because you're using Rails in API mode, and in this mode Rails does not accept HTML requests anymore. Some middlewares & modules are disabled in order to improve performances for APIs.
The problem is that Devise is requiring HTML because users are redirected to forms.
Another approach consists to use Basic authentication (Rails provide helpers for that). We get the credentials with basic auth (browser prompt), then we're using Devise only to authenticate the user. Finally we're configuration Rails Admin to use this strategy.
# rails admin configuration, replacing your existing config
config.authenticate_with do
# this is a rails controller helper
authenticate_or_request_with_http_basic('Login required') do |username, password|
# Here we're checking for username & password provided with basic auth
resource = Admin.find_by(email: username)
# we're using devise helpers to verify password and sign in the user
if resource.valid_password?(password)
sign_in :admin, resource
end
end
end
Note: you may have to adapt the resource =
line with your models. I'm assuming you already have an Admin
model.
The code is not tested, but this is a start.
Resources :