Skip to content
This repository has been archived by the owner on Mar 22, 2021. It is now read-only.

When no token is passed, Knock generates a new token by itself #195

Open
eddy-k opened this issue Nov 28, 2017 · 1 comment
Open

When no token is passed, Knock generates a new token by itself #195

eddy-k opened this issue Nov 28, 2017 · 1 comment

Comments

@eddy-k
Copy link

eddy-k commented Nov 28, 2017

How to reproduce:

Do not use ActiveRecord for the user model
Add include Knock::Authenticable to a controller

send request to that controller without a token

expected result:
I should get a not authorized request

actual result:
I get that the current_user is nil and respond with 'Internal server error'

@JoshCheek
Copy link

+1

The problem is that it lazily creates the current_user method lazily when the token is passed. This is done via method_missing. If it is called without the token, it returns nil. If it is called with the token, it defines the method. The second time you call the method, then, it hits the newly defined current_user, instead of method_missing. This implementation of the method doesn't return nil when there is no token, instead it delegates to the entity getter, which returns an empty User object. This is probably dependent on how the entity getter is defined, but at the very least, the behaviour is nondeterministic.

See knock/authenticatable for details, and then follow it down the current_user path of method_missing, with and without a token.

Here is an minimal example of what is ultimately happening:

class MahController < Struct.new(:token)
  def method_missing(name)
    token && self.class.send(:define_method, name) { "Josh" } && send(name)
  end
end

# returns nil
MahController.new().current_user             # => nil

# then someone signs in with a token
MahController.new("some token").current_user # => "Josh"

# now, this is the same call as before, but it returns "Josh" instead of nil,
# b/c the behaviour of `method_missing` is different than the method it defines
MahController.new().current_user             # => "Josh"

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants