Knock: Filter chain halted as :authenticate_user rendered or redirected Completed 401 Unauthorized

Created on 24 Feb 2017  路  3Comments  路  Source: nsarno/knock

I'm opening this separate from #139 , same result, perhaps different reasons ... hopefully just my ignorance.

I'm not seeing how to get passed decoding the JWT from Auth0 ... so a User can be generated by before_action :authenticate_user on the controller and self.from_token_payload on the model. I'm seeing that Auth0 always uses RS256 algorithm (and recommends it as secure, while HS256 is not), so I changed it in the knock.rb config config.token_signature_algorithm = 'RS256' and added the config.token_public_key as well.

Stepping through I see the algorithms match:

(byebug) options
{:verify_expiration=>true, :verify_not_before=>true, :verify_iss=>false, :verify_iat=>false, :verify_jti=>false, :verify_aud=>true, :verify_sub=>false, :leeway=>0, :aud=>"...secret...", :algorithm=>"RS256"}
(byebug) algo
"RS256"

Along with the algorithm (algo) , I've also verified the presence of the jwt(signing_input), key, and signature.

My JWT validates and signature verifies at jwt.io but when I step through the decoding it always falls right into:

``` 142: key = yield(header) if keyfinder
143: [header['alg'], key]
144: end
145:
146: def verify_signature(algo, key, signing_input, signature)
=> 147: verify_signature_algo(algo, key, signing_input, signature)
148: rescue OpenSSL::PKey::PKeyError
149: raise JWT::VerificationError, 'Signature verification raised'
150: ensure
151: OpenSSL.errors.clear
(byebug) next

[146, 155] in .gem/ruby/2.4.0/gems/jwt-1.5.6/lib/jwt.rb
146: def verify_signature(algo, key, signing_input, signature)
147: verify_signature_algo(algo, key, signing_input, signature)
148: rescue OpenSSL::PKey::PKeyError
149: raise JWT::VerificationError, 'Signature verification raised'
150: ensure
=> 151: OpenSSL.errors.clear
152: end
153:
154: def verify_signature_algo(algo, key, signing_input, signature)
155: if %w(HS256 HS384 HS512).include?(algo)
(byebug) next

[47, 56] in .gem/ruby/2.4.0/gems/knock-2.1.1/lib/knock/authenticable.rb
47: unless instance_variable_defined?(memoization_var_name)
48: current =
49: begin
50: Knock::AuthToken.new(token: token).entity_for(entity_class)
51: rescue
=> 52: nil
53: end
54: instance_variable_set(memoization_var_name, current)
55: end
56: instance_variable_get(memoization_var_name)
```

Continuing to result in 'Filter chain halted as :authenticate_user rendered or redirected Completed 401 Unauthorized'

Most helpful comment

@jessecravens I have a Rails API that just ran into this problem, and it was for two reasons:

1) Like SiDevesh commented before the issue was closed, apps made past Dec 6th no longer have their secret Base64 encoded, so I needed to change the initializer to remove the Base64 decode that is mentioned in the quickstart docs.

The second thing I did was throw the error inside define_current_entity_getter by redefining it in my controller that is including Knock::Authenticable:

class Api::SomeController < ActionController::API
  include Knock::Authenticable
  before_action :authenticate_user

  module Knock::Authenticable
    def define_current_entity_getter entity_class, getter_name
      unless self.respond_to?(getter_name)
        memoization_var_name = "@_#{getter_name}"
        self.class.send(:define_method, getter_name) do
          unless instance_variable_defined?(memoization_var_name)
            current =
              begin
                Knock::AuthToken.new(token: token).entity_for(entity_class)
              rescue => e
                throw e
                #nil
              end
            instance_variable_set(memoization_var_name, current)
          end
          instance_variable_get(memoization_var_name)
        end
      end
    end
  end
end

I found out the error was:

<Invalid JWT: Failed audience check. The right audience is <my-auth0-client-id> but received <none>>

And by adding the aud parameter with my Auth0 Client ID to the payload on jwt.io it worked (I am using HS256).

image

While there could be a dozen different problems you could run into, I hope this helps you track it down.

(I opened an issue previously about not swallowing the error here #122)

All 3 comments

@jessecravens I have a Rails API that just ran into this problem, and it was for two reasons:

1) Like SiDevesh commented before the issue was closed, apps made past Dec 6th no longer have their secret Base64 encoded, so I needed to change the initializer to remove the Base64 decode that is mentioned in the quickstart docs.

The second thing I did was throw the error inside define_current_entity_getter by redefining it in my controller that is including Knock::Authenticable:

class Api::SomeController < ActionController::API
  include Knock::Authenticable
  before_action :authenticate_user

  module Knock::Authenticable
    def define_current_entity_getter entity_class, getter_name
      unless self.respond_to?(getter_name)
        memoization_var_name = "@_#{getter_name}"
        self.class.send(:define_method, getter_name) do
          unless instance_variable_defined?(memoization_var_name)
            current =
              begin
                Knock::AuthToken.new(token: token).entity_for(entity_class)
              rescue => e
                throw e
                #nil
              end
            instance_variable_set(memoization_var_name, current)
          end
          instance_variable_get(memoization_var_name)
        end
      end
    end
  end
end

I found out the error was:

<Invalid JWT: Failed audience check. The right audience is <my-auth0-client-id> but received <none>>

And by adding the aud parameter with my Auth0 Client ID to the payload on jwt.io it worked (I am using HS256).

image

While there could be a dozen different problems you could run into, I hope this helps you track it down.

(I opened an issue previously about not swallowing the error here #122)

Thanks @johnmosesman overriding the method: define_current_entity_getter in my controller ... gives me a better error :

*** NoMethodError Exception: undefined method `verify' for #<String:0x007fdba3a3b138>

which leads me to this issue with knock . ruby-jwt : https://github.com/jwt/ruby-jwt/issues/115 .

I got this working, as I expected I was passing in the token_public_key incorrectly. https://github.com/nsarno/knock/issues/148

Was this page helpful?
0 / 5 - 0 ratings