2
votes

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.

1
Can post your entire routes.rb file please, I want to know if you are using a different namespace for the API or how you are handling the API routing.danielavila
Hi @danielavila, I updated the question and included the full routes.rb file.Hector Toro
@danielavila hi Daniel, i posted the entire routes.rb file, do you have any clue on what could fix the problem? Thanks for your time.Hector Toro

1 Answers

4
votes

The problem

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.

Solution

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 :