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

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

Closed
jessecravens opened this issue Feb 24, 2017 · 3 comments

Comments

@jessecravens
Copy link

jessecravens commented Feb 24, 2017

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:

   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'

@johnmosesman
Copy link

@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)

@jessecravens
Copy link
Author

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 : jwt/ruby-jwt#115 .

@jessecravens
Copy link
Author

I got this working, as I expected I was passing in the token_public_key incorrectly. #148

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