Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting a NameError - undefined method `authenticate_user!'? (R: Check the token authenticatable model name.) #42

Closed
JeskTop opened this issue Mar 17, 2014 · 13 comments
Labels
question When closed, this issue will become part of the FAQ.

Comments

@JeskTop
Copy link

JeskTop commented Mar 17, 2014

Why I set acts_as_token_authentication_handler_for User to my ApplicationController, I will have the problem is NameError - undefined methodauthenticate_user!'`. I am the reference document, but also has this problem, I don't know what is happen.

@gonzalo-bulnes
Copy link
Owner

Hello @JeskTop!

Did you install Devise before installing Simple Token Authentication? (It's a requirement because Simple Token Authentication relies on it to authenticate users.)

@JeskTop
Copy link
Author

JeskTop commented Mar 17, 2014

Hi. @gonzalo-bulnes
My rails version is 4.0.4, and I installing Devise 3.2.4

@Think4866
Copy link

@JeskTop when I had this issue, it was because I did not type the correct resource name after acts_as_token_authentication_handler_for.

The other time this happened was while writing specifications in rspec. As a matter of fact, I just replicated this issue when running rspec. It was not fixed by including the Devise::TestHelpers. It only seems to happen for me when using rspec.

Are you getting this with rspec by chance?

@gonzalo-bulnes
Copy link
Owner

@JeskTop Both gems versions are compatibe with the use of Simple Token Authentication.

The authenticate_user! method is provided by Devise, maybe you skipped a step from its setup?
Are you able to sign in users?

Oh, did you install Devise for the User model? If the Devise-enabled model were Admin (for example), you should ensure the controller acts_as_token_authentication_handler_for Admin.

@gonzalo-bulnes gonzalo-bulnes changed the title NameError - undefined method `authenticate_user!' NameError - undefined method `authenticate_user!' (R: Check the token authenticatable model name.) Apr 26, 2014
@gonzalo-bulnes gonzalo-bulnes changed the title NameError - undefined method `authenticate_user!' (R: Check the token authenticatable model name.) Getting a NameError - undefined method `authenticate_user!'? (R: Check the token authenticatable model name.) Apr 26, 2014
@gonzalo-bulnes
Copy link
Owner

Hi @nicolo! First of all: could you please re-post your question here? The cause of it , hence the response, may be different, but the issue you're facing is the same. In order to keep the questions easy to browse, I would prefer to keep together all aspects of each strange/confusing/unexpected behaviour, and only separate topics when they clearly diverge.

@nicolo
Copy link
Contributor

nicolo commented Jun 19, 2014

I've read this #67
I've done this

  1. config.sign_in_token = false

  2. acts_as_token_authentication_handler_for User, fallback_to_devise: false

Once I do this, I'm able to access any controller without any token provided. It's basically like authentication doesn't exist.

If I don't include fallback_to_devise: false, I get undefined method `authenticate_user!' on every request.
I've read this #42
Yes my User model is setup for devise and I've installed devise.

I'm trying to create an app which is purely an API like explained in issue 67. Feels like I'm missing something major. Thanks in advance for any help.

Here are some relevant files that should help with troubleshooting

class User < ActiveRecord::Base
  acts_as_token_authenticatable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
end
class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.

  protect_from_forgery with: :null_session#, :if => Proc.new { |c| c.request.format == 'application/json' }

  acts_as_token_authentication_handler_for User, fallback_to_devise: false

end
SimpleTokenAuthentication.configure do |config|

  # Configure the session persistence policy after a successful sign in,
  # in other words, if the authentication token acts as a signin token.
  # If true, user is stored in the session and the authentication token and
  # email may be provided only once.
  # If false, users must provide their authentication token and email at every request.
  config.sign_in_token = false

  # Configure the name of the HTTP headers watched for authentication.
  #
  # Default header names for a given token authenticatable entity follow the pattern:
  #   { entity: { authentication_token: 'X-Entity-Token', email: 'X-Entity-Email'} }
  #
  # When several token authenticatable models are defined, custom header names
  # can be specified for none, any, or all of them.
  #
  # Examples
  #
  #   Given User and SuperAdmin are token authenticatable,
  #   When the following configuration is used:
  #     `config.header_names = { super_admin: { authentication_token: 'X-Admin-Auth-Token' } }`
  #   Then the token authentification handler for User watches the following headers:
  #     `X-User-Token, X-User-Email`
  #   And the token authentification handler for SuperAdmin watches the following headers:
  #     `X-Admin-Auth-Token, X-SuperAdmin-Email`
  #
  # config.header_names = { user: { authentication_token: 'X-User-Token', email: 'X-User-Email' } }

end

@gonzalo-bulnes
Copy link
Owner

@nicolo Now answering your question:

1. The authenticate_user! method is defined by Devise when you add it to your User model:

rails generate devise User

Before installing Simple Token Authentication, as a first step, you must make sure that you can authenticate with the default User and ApplicationController setup:

# app/models/user.rb

class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
end
class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception

  # Enable authentication with Devise
  before_action :authenticate_user!
end

The undefined method: `authenticate_user!' message indicates without doubt that the error, forgotten instruction or misconfiguration occurred within this first step. I know you are sure of having properly set Devise up, but believe me, there is no doubt about that, please give it another chance.

2. Once that solved, I have a few comments about the code you posted:

  • Take care with the default comment: # Prevent CSRF attacks by raising an exception.: it does not reflect the behaviour of your custom protect_from_forgery with: :null_session instruction.
  • In fact, if your application is purely an API, you can either:
    • remove completely the CSRF protection:
class ApplicationController < ActionController::Base
  # Enable token authentication in a context where there is no CSRF protection
  # See https://github.com/gonzalo-bulnes/simple_token_authentication/issues/49
  acts_as_token_authentication_handler_for User, fallback_to_devise: false
end
  • or enable an API-firendly CSRF protection:
class ApplicationController < ActionController::Base
  # Enable CSRF protection for API
  # See https://github.com/gonzalo-bulnes/simple_token_authentication/issues/67 and
  # http://edgeapi.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html
  protect_from_forgery with: :null_session

  # Enable token authentication in this specific CSRF protection context
  acts_as_token_authentication_handler_for User
end

That was a bit long but I hope it helps!

EDIT: Thanks for re-posting your comment, it makes the conversation easier to follow!

@nicolo
Copy link
Contributor

nicolo commented Jun 20, 2014

@gonzalo-bulnes thanks for your help. I appreciate all your work on this gem.

I think I discovered my problem. I did setup Devise correctly, but I then broke things later by tinkering with my routes file. I had moved devise_for users inside my api namespace. It seems like I need to include it within the namespace and outside of it.

*note I added in all the skips for the global devise_for users because I only want to expose those routes within the api

Rails.application.routes.draw do
  devise_for :users, :skip => [:sessions, :passwords, :registrations]
  scope module: :api, defaults: { format: 'json' } do
    namespace :v1 do
      devise_for :users
    end
  end
end

@gonzalo-bulnes
Copy link
Owner

Thanks for your feedback @nicolo, I'll close this issue. Don't hesitate to re-open it if you run into the problem again; even if they're not exactly Simple Token Authentication issues, that's always good to keep a trace of the different kind of issues that can occur when using the gem.

Regards!

@thalespf
Copy link

thalespf commented Jul 2, 2014

Thanks @nicolo. It works for me too. I put devise_for outside namespace api and worked.

@amitfriedman12
Copy link

I added this line to my controller which did the trick for me:

    include Devise::Controllers::Helpers

@gonzalo-bulnes
Copy link
Owner

Thank you for sharing @amitfriedman12!

@erijonhson
Copy link

None of the above works for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question When closed, this issue will become part of the FAQ.
Projects
None yet
Development

No branches or pull requests

7 participants