nsarno / knock

Seamless JWT authentication for Rails API

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

eddy-k opened this issue · comments

commented

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"