knock
knock copied to clipboard
When no token is passed, Knock generates a new token by itself
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'
+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"