jaredonline / google-authenticator

Ruby gem to implement Google's MFA authenticator

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

NoMethodError: undefined method `cookies' for nil:NilClass

marknguyen85 opened this issue · comments

when i call http://xxx/api/v1/user_mfa_session/new then throw exception

{
"status": 500,
"error": "Internal Server Error",
"exception": "#<NoMethodError: undefined method cookies' for nil:NilClass>", "traces": { "Application Trace": [ { "id": 1, "trace": "app/controllers/api/v1/user_mfa_sessions_controller.rb:26:in check_mfa'"
}
],
"Framework Trace": [
{
"id": 0,
"trace": "google-authenticator-rails (1.6.1) lib/google-authenticator-rails/session/persistence.rb:16:in find'" }, { "id": 2, "trace": "activesupport (5.1.5) lib/active_support/callbacks.rb:413:in block in make_lambda'"
},
{
"id": 3,
"trace": "activesupport (5.1.5) lib/active_support/callbacks.rb:197:in block (2 levels) in halting'" }, { "id": 4, "trace": "actionpack (5.1.5) lib/abstract_controller/callbacks.rb:12:in block (2 levels) in module:Callbacks'"
},
{
"id": 5,
"trace": "activesupport (5.1.5) lib/active_support/callbacks.rb:198:in block in halting'" }, { "id": 6, "trace": "activesupport (5.1.5) lib/active_support/callbacks.rb:507:in block in invoke_before'"
},
{
"id": 7,
"trace": "activesupport (5.1.5) lib/active_support/callbacks.rb:507:in each'" }, { "id": 8, "trace": "activesupport (5.1.5) lib/active_support/callbacks.rb:507:in invoke_before'"
},
{
"id": 9,
"trace": "activesupport (5.1.5) lib/active_support/callbacks.rb:130:in run_callbacks'" }, { "id": 10, "trace": "actionpack (5.1.5) lib/abstract_controller/callbacks.rb:19:in process_action'"
},
{
"id": 11,
"trace": "actionpack (5.1.5) lib/action_controller/metal/rescue.rb:20:in process_action'" }, { "id": 12, "trace": "actionpack (5.1.5) lib/action_controller/metal/instrumentation.rb:32:in block in process_action'"
},
{
"id": 13,
"trace": "activesupport (5.1.5) lib/active_support/notifications.rb:166:in block in instrument'" }, { "id": 14, "trace": "activesupport (5.1.5) lib/active_support/notifications/instrumenter.rb:21:in instrument'"
},
{
"id": 15,
"trace": "activesupport (5.1.5) lib/active_support/notifications.rb:166:in instrument'" }, { "id": 16, "trace": "actionpack (5.1.5) lib/action_controller/metal/instrumentation.rb:30:in process_action'"
},
{
"id": 17,
"trace": "actionpack (5.1.5) lib/action_controller/metal/params_wrapper.rb:252:in process_action'" }, { "id": 18, "trace": "activerecord (5.1.5) lib/active_record/railties/controller_runtime.rb:22:in process_action'"
},
{
"id": 19,
"trace": "actionpack (5.1.5) lib/abstract_controller/base.rb:124:in process'" }, { "id": 20, "trace": "actionpack (5.1.5) lib/action_controller/metal.rb:189:in dispatch'"
},
{
"id": 21,
"trace": "actionpack (5.1.5) lib/action_controller/metal.rb:253:in dispatch'" }, { "id": 22, "trace": "actionpack (5.1.5) lib/action_dispatch/routing/route_set.rb:49:in dispatch'"
},
{
"id": 23,
"trace": "actionpack (5.1.5) lib/action_dispatch/routing/route_set.rb:31:in serve'" }, { "id": 24, "trace": "actionpack (5.1.5) lib/action_dispatch/journey/router.rb:50:in block in serve'"
},
{
"id": 25,
"trace": "actionpack (5.1.5) lib/action_dispatch/journey/router.rb:33:in each'" }, { "id": 26, "trace": "actionpack (5.1.5) lib/action_dispatch/journey/router.rb:33:in serve'"
},
{
"id": 27,
"trace": "actionpack (5.1.5) lib/action_dispatch/routing/route_set.rb:844:in call'" }, { "id": 28, "trace": "apipie-rails (0.5.6) lib/apipie/static_dispatcher.rb:65:in call'"
},
{
"id": 29,
"trace": "apipie-rails (0.5.6) lib/apipie/extractor/recorder.rb:136:in call'" }, { "id": 30, "trace": "rack (2.0.4) lib/rack/session/abstract/id.rb:232:in context'"
},
{
"id": 31,
"trace": "rack (2.0.4) lib/rack/session/abstract/id.rb:226:in call'" }, { "id": 32, "trace": "actionpack (5.1.5) lib/action_dispatch/middleware/cookies.rb:613:in call'"
},
{
"id": 33,
"trace": "warden (1.2.7) lib/warden/manager.rb:36:in block in call'" }, { "id": 34, "trace": "warden (1.2.7) lib/warden/manager.rb:35:in catch'"
},
{
"id": 35,
"trace": "warden (1.2.7) lib/warden/manager.rb:35:in call'" }, { "id": 36, "trace": "rack (2.0.4) lib/rack/etag.rb:25:in call'"
},
{
"id": 37,
"trace": "rack (2.0.4) lib/rack/conditional_get.rb:25:in call'" }, { "id": 38, "trace": "rack (2.0.4) lib/rack/head.rb:12:in call'"
},
{
"id": 39,
"trace": "activerecord (5.1.5) lib/active_record/migration.rb:556:in call'" }, { "id": 40, "trace": "actionpack (5.1.5) lib/action_dispatch/middleware/callbacks.rb:26:in block in call'"
},
{
"id": 41,
"trace": "activesupport (5.1.5) lib/active_support/callbacks.rb:97:in run_callbacks'" }, { "id": 42, "trace": "actionpack (5.1.5) lib/action_dispatch/middleware/callbacks.rb:24:in call'"
},
{
"id": 43,
"trace": "actionpack (5.1.5) lib/action_dispatch/middleware/executor.rb:12:in call'" }, { "id": 44, "trace": "actionpack (5.1.5) lib/action_dispatch/middleware/debug_exceptions.rb:59:in call'"
},
{
"id": 45,
"trace": "actionpack (5.1.5) lib/action_dispatch/middleware/show_exceptions.rb:31:in call'" }, { "id": 46, "trace": "railties (5.1.5) lib/rails/rack/logger.rb:36:in call_app'"
},
{
"id": 47,
"trace": "railties (5.1.5) lib/rails/rack/logger.rb:24:in block in call'" }, { "id": 48, "trace": "activesupport (5.1.5) lib/active_support/tagged_logging.rb:69:in block in tagged'"
},
{
"id": 49,
"trace": "activesupport (5.1.5) lib/active_support/tagged_logging.rb:26:in tagged'" }, { "id": 50, "trace": "activesupport (5.1.5) lib/active_support/tagged_logging.rb:69:in tagged'"
},
{
"id": 51,
"trace": "railties (5.1.5) lib/rails/rack/logger.rb:24:in call'" }, { "id": 52, "trace": "actionpack (5.1.5) lib/action_dispatch/middleware/remote_ip.rb:79:in call'"
},
{
"id": 53,
"trace": "actionpack (5.1.5) lib/action_dispatch/middleware/request_id.rb:25:in call'" }, { "id": 54, "trace": "rack (2.0.4) lib/rack/runtime.rb:22:in call'"
},
{
"id": 55,
"trace": "activesupport (5.1.5) lib/active_support/cache/strategy/local_cache_middleware.rb:27:in call'" }, { "id": 56, "trace": "actionpack (5.1.5) lib/action_dispatch/middleware/executor.rb:12:in call'"
},
{
"id": 57,
"trace": "actionpack (5.1.5) lib/action_dispatch/middleware/static.rb:125:in call'" }, { "id": 58, "trace": "rack (2.0.4) lib/rack/sendfile.rb:111:in call'"
},
{
"id": 59,
"trace": "rack-cors (1.0.2) lib/rack/cors.rb:97:in call'" }, { "id": 60, "trace": "railties (5.1.5) lib/rails/engine.rb:522:in call'"
},
{
"id": 61,
"trace": "puma (3.11.3) lib/puma/configuration.rb:225:in call'" }, { "id": 62, "trace": "puma (3.11.3) lib/puma/server.rb:624:in handle_request'"
},
{
"id": 63,
"trace": "puma (3.11.3) lib/puma/server.rb:438:in process_client'" }, { "id": 64, "trace": "puma (3.11.3) lib/puma/server.rb:302:in block in run'"
},
{
"id": 65,
"trace": "puma (3.11.3) lib/puma/thread_pool.rb:120:in block in spawn_thread'" } ], "Full Trace": [ { "id": 0, "trace": "google-authenticator-rails (1.6.1) lib/google-authenticator-rails/session/persistence.rb:16:in find'"
},
{
"id": 1,
"trace": "app/controllers/api/v1/user_mfa_sessions_controller.rb:26:in check_mfa'" }, { "id": 2, "trace": "activesupport (5.1.5) lib/active_support/callbacks.rb:413:in block in make_lambda'"
},
{
"id": 3,
"trace": "activesupport (5.1.5) lib/active_support/callbacks.rb:197:in block (2 levels) in halting'" }, { "id": 4, "trace": "actionpack (5.1.5) lib/abstract_controller/callbacks.rb:12:in block (2 levels) in module:Callbacks'"
},
{
"id": 5,
"trace": "activesupport (5.1.5) lib/active_support/callbacks.rb:198:in block in halting'" }, { "id": 6, "trace": "activesupport (5.1.5) lib/active_support/callbacks.rb:507:in block in invoke_before'"
},
{
"id": 7,
"trace": "activesupport (5.1.5) lib/active_support/callbacks.rb:507:in each'" }, { "id": 8, "trace": "activesupport (5.1.5) lib/active_support/callbacks.rb:507:in invoke_before'"
},
{
"id": 9,
"trace": "activesupport (5.1.5) lib/active_support/callbacks.rb:130:in run_callbacks'" }, { "id": 10, "trace": "actionpack (5.1.5) lib/abstract_controller/callbacks.rb:19:in process_action'"
},
{
"id": 11,
"trace": "actionpack (5.1.5) lib/action_controller/metal/rescue.rb:20:in process_action'" }, { "id": 12, "trace": "actionpack (5.1.5) lib/action_controller/metal/instrumentation.rb:32:in block in process_action'"
},
{
"id": 13,
"trace": "activesupport (5.1.5) lib/active_support/notifications.rb:166:in block in instrument'" }, { "id": 14, "trace": "activesupport (5.1.5) lib/active_support/notifications/instrumenter.rb:21:in instrument'"
},
{
"id": 15,
"trace": "activesupport (5.1.5) lib/active_support/notifications.rb:166:in instrument'" }, { "id": 16, "trace": "actionpack (5.1.5) lib/action_controller/metal/instrumentation.rb:30:in process_action'"
},
{
"id": 17,
"trace": "actionpack (5.1.5) lib/action_controller/metal/params_wrapper.rb:252:in process_action'" }, { "id": 18, "trace": "activerecord (5.1.5) lib/active_record/railties/controller_runtime.rb:22:in process_action'"
},
{
"id": 19,
"trace": "actionpack (5.1.5) lib/abstract_controller/base.rb:124:in process'" }, { "id": 20, "trace": "actionpack (5.1.5) lib/action_controller/metal.rb:189:in dispatch'"
},
{
"id": 21,
"trace": "actionpack (5.1.5) lib/action_controller/metal.rb:253:in dispatch'" }, { "id": 22, "trace": "actionpack (5.1.5) lib/action_dispatch/routing/route_set.rb:49:in dispatch'"
},
{
"id": 23,
"trace": "actionpack (5.1.5) lib/action_dispatch/routing/route_set.rb:31:in serve'" }, { "id": 24, "trace": "actionpack (5.1.5) lib/action_dispatch/journey/router.rb:50:in block in serve'"
},
{
"id": 25,
"trace": "actionpack (5.1.5) lib/action_dispatch/journey/router.rb:33:in each'" }, { "id": 26, "trace": "actionpack (5.1.5) lib/action_dispatch/journey/router.rb:33:in serve'"
},
{
"id": 27,
"trace": "actionpack (5.1.5) lib/action_dispatch/routing/route_set.rb:844:in call'" }, { "id": 28, "trace": "apipie-rails (0.5.6) lib/apipie/static_dispatcher.rb:65:in call'"
},
{
"id": 29,
"trace": "apipie-rails (0.5.6) lib/apipie/extractor/recorder.rb:136:in call'" }, { "id": 30, "trace": "rack (2.0.4) lib/rack/session/abstract/id.rb:232:in context'"
},
{
"id": 31,
"trace": "rack (2.0.4) lib/rack/session/abstract/id.rb:226:in call'" }, { "id": 32, "trace": "actionpack (5.1.5) lib/action_dispatch/middleware/cookies.rb:613:in call'"
},
{
"id": 33,
"trace": "warden (1.2.7) lib/warden/manager.rb:36:in block in call'" }, { "id": 34, "trace": "warden (1.2.7) lib/warden/manager.rb:35:in catch'"
},
{
"id": 35,
"trace": "warden (1.2.7) lib/warden/manager.rb:35:in call'" }, { "id": 36, "trace": "rack (2.0.4) lib/rack/etag.rb:25:in call'"
},
{
"id": 37,
"trace": "rack (2.0.4) lib/rack/conditional_get.rb:25:in call'" }, { "id": 38, "trace": "rack (2.0.4) lib/rack/head.rb:12:in call'"
},
{
"id": 39,
"trace": "activerecord (5.1.5) lib/active_record/migration.rb:556:in call'" }, { "id": 40, "trace": "actionpack (5.1.5) lib/action_dispatch/middleware/callbacks.rb:26:in block in call'"
},
{
"id": 41,
"trace": "activesupport (5.1.5) lib/active_support/callbacks.rb:97:in run_callbacks'" }, { "id": 42, "trace": "actionpack (5.1.5) lib/action_dispatch/middleware/callbacks.rb:24:in call'"
},
{
"id": 43,
"trace": "actionpack (5.1.5) lib/action_dispatch/middleware/executor.rb:12:in call'" }, { "id": 44, "trace": "actionpack (5.1.5) lib/action_dispatch/middleware/debug_exceptions.rb:59:in call'"
},
{
"id": 45,
"trace": "actionpack (5.1.5) lib/action_dispatch/middleware/show_exceptions.rb:31:in call'" }, { "id": 46, "trace": "railties (5.1.5) lib/rails/rack/logger.rb:36:in call_app'"
},
{
"id": 47,
"trace": "railties (5.1.5) lib/rails/rack/logger.rb:24:in block in call'" }, { "id": 48, "trace": "activesupport (5.1.5) lib/active_support/tagged_logging.rb:69:in block in tagged'"
},
{
"id": 49,
"trace": "activesupport (5.1.5) lib/active_support/tagged_logging.rb:26:in tagged'" }, { "id": 50, "trace": "activesupport (5.1.5) lib/active_support/tagged_logging.rb:69:in tagged'"
},
{
"id": 51,
"trace": "railties (5.1.5) lib/rails/rack/logger.rb:24:in call'" }, { "id": 52, "trace": "actionpack (5.1.5) lib/action_dispatch/middleware/remote_ip.rb:79:in call'"
},
{
"id": 53,
"trace": "actionpack (5.1.5) lib/action_dispatch/middleware/request_id.rb:25:in call'" }, { "id": 54, "trace": "rack (2.0.4) lib/rack/runtime.rb:22:in call'"
},
{
"id": 55,
"trace": "activesupport (5.1.5) lib/active_support/cache/strategy/local_cache_middleware.rb:27:in call'" }, { "id": 56, "trace": "actionpack (5.1.5) lib/action_dispatch/middleware/executor.rb:12:in call'"
},
{
"id": 57,
"trace": "actionpack (5.1.5) lib/action_dispatch/middleware/static.rb:125:in call'" }, { "id": 58, "trace": "rack (2.0.4) lib/rack/sendfile.rb:111:in call'"
},
{
"id": 59,
"trace": "rack-cors (1.0.2) lib/rack/cors.rb:97:in call'" }, { "id": 60, "trace": "railties (5.1.5) lib/rails/engine.rb:522:in call'"
},
{
"id": 61,
"trace": "puma (3.11.3) lib/puma/configuration.rb:225:in call'" }, { "id": 62, "trace": "puma (3.11.3) lib/puma/server.rb:624:in handle_request'"
},
{
"id": 63,
"trace": "puma (3.11.3) lib/puma/server.rb:438:in process_client'" }, { "id": 64, "trace": "puma (3.11.3) lib/puma/server.rb:302:in block in run'"
},
{
"id": 65,
"trace": "puma (3.11.3) lib/puma/thread_pool.rb:120:in `block in spawn_thread'"
}
]
}
}

Heya @marknguyen85, can you give me some more details?

Which version of Rails are you using? What are the contents of your Session class? What about the associated ActiveRecord model?

@jaredonline here my code implementation

=======================================

Gemfile

gem 'rails', '~> 5.1.5'

gem 'google-authenticator-rails'

=======================================

ApplicationController.rb

class ApplicationController < ActionController::API
    include Response
    include ExceptionHandler
    include ActionController::Helpers
    include ActionController::Cookies
    def check_mfa
      if !(user_mfa_session = UserMfaSession.find) && (user_mfa_session ? user_mfa_session.record == @current_user : !user_mfa_session)
        redirect_to new_user_mfa_session_path
      end
    end
 end

=======================================

app/controllers/user_mfa_sessions_controller.rb

module Api
  module V1
    class UserMfaSessionsController < ApplicationController
      before_action :check_mfa
      def new
        @user = User.find_by_ermail('admin@gmail.com') 
      end
      def create
        @user = User.find_by_ermail('admin@gmail.com') 
        if @user.google_authentic?(params[:auth][:mfa_code])
          UserMfaSession.create(@user)
          redirect_to root_url
        else
          flash[:error] = "Wrong code"
          render :new
        end
      end
    end
  end
end

=======================================

model/UserMfaSession.rb

class UserMfaSession < GoogleAuthenticatorRails::Session::Base
    #no real code needed here
  end

=======================================

model/User.rb

class User < ApplicationRecord
    devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
        validates :UserName, :email, :presence => true
        validates_uniqueness_of :email

    acts_as_google_authenticated lookup_token: :salt, drift: 30, issuer: 'test'
    before_save {|record| record.salt = SecureRandom.hex unless record.salt }
    after_create {|record| record.set_google_secret }
end

=======================================

config/initializers/google_authenticator_rails.rb

GoogleAuthenticatorRails.time_until_expiration = 1.month
GoogleAuthenticatorRails.cookie_key_suffix = 'mfa_credentials'
GoogleAuthenticatorRails.cookie_options = { :httponly => true, :secure => true, :domain => :all }

=======================================

config/Application.rb

module WebAPIs
  class Application < Rails::Application
    config.load_defaults 5.1
    config.api_only = true
    
    config.middleware.use ActionDispatch::Cookies
    config.middleware.use ActionDispatch::Session::CookieStore
  end
end

Ah! I think this is the problem:

class ApplicationController < ActionController::API

Right now this gem only works with ActionController::Base, its included here:

https://github.com/jaredonline/google-authenticator/blob/master/lib/google-authenticator-rails/action_controller/rails_adapter.rb#L38

There's an open PR here https://github.com/jaredonline/google-authenticator/pull/37/files to add support for ActionController::API, but I never closed it because the author never got back to me.

I'll take a look into adding that support today.

Alternatively, if you don't want to wait, you can have ApplicationController inherit from ActionController::Base instead of ActionController::API.

I will try according to your intructions, thanks

@jaredonline okie my issue resolved. thanks for supported.

Hi there!
I still experience this issue. My app is configured to inherit from ActionController::API and I would rather not change that.
Is it possible to add support for ActionController::API?
Best regards

@PeterKarpinski I just merged a change that should fix it. I'll roll a new version shortly.

@PeterKarpinski Gem 3.3.0 is available now.