Knock: How to reference public key in knock.rb (config.token_public_key) ?

Created on 26 Feb 2017  路  14Comments  路  Source: nsarno/knock

I am trying to properly configure an app that uses auth0js v8.2.0 to use RS256. Since Auth0 is returning a token signed with RS256. I've debugged it down to here: https://github.com/jwt/ruby-jwt/issues/115

One theory that I have is that my reference in config.token_public_key is improper.

Knock.setup do |config|
  config.token_audience = -> { Rails.application.secrets.auth0_client_id }
  config.token_secret_signature_key = -> { Rails.application.secrets.auth0_client_secret }
  config.token_public_key = ????
end

I've tried every which way I can think of, but this methodpublic_key.verify(OpenSSL::Digest.new(algorithm.sub('RS', 'sha')), signature, signing_input) continues to raise a no method error:

no method 'verify' for type String.

Does anyone have a working example?
Or is there something more fundamental that I am missing here?

Most helpful comment

I figured this out .. for anyone else stumped by this, here is my solution:

In secrets.yml:

development:
  secret_key_base: <secret>
  auth0_client_id: <secret>
  auth0_client_secret: <secret>
  auth0_rsa_domain: <link from AuthO : Clients > Advanced Settings > Endpoints > JSON Web Key Set

In knock.rb:

  jwks_raw = Net::HTTP.get URI(Rails.application.secrets.auth0_rsa_domain)
  jwks_keys = Array(JSON.parse(jwks_raw)['keys'])
  config.token_public_key = OpenSSL::X509::Certificate.new(Base64.decode64(jwks_keys[0]['x5c'].first)).public_key

All 14 comments

I figured this out .. for anyone else stumped by this, here is my solution:

In secrets.yml:

development:
  secret_key_base: <secret>
  auth0_client_id: <secret>
  auth0_client_secret: <secret>
  auth0_rsa_domain: <link from AuthO : Clients > Advanced Settings > Endpoints > JSON Web Key Set

In knock.rb:

  jwks_raw = Net::HTTP.get URI(Rails.application.secrets.auth0_rsa_domain)
  jwks_keys = Array(JSON.parse(jwks_raw)['keys'])
  config.token_public_key = OpenSSL::X509::Certificate.new(Base64.decode64(jwks_keys[0]['x5c'].first)).public_key

@jessecravens thanks so much for tracking this down... hours lost here. I'm going to work up a PR to update the initializer with some comments

Thanks @jessecravens, just saved me from setting the keyboard on fire here ;)

@jessecravens, did you need to configure anything else in knock.rb ? I configured it just as you did, stil lgetting the

Filter chain halted as :authenticate_user rendered or redirected
Completed 401 Unauthorized in 0ms (ActiveRecord: 0.0ms)

I used jwt.io debugger to make sure everything was fine, and it is, signature is validated, therefore I guess the problem comes from my app configuration

Thank you so much @jessecravens. Spent hours trying to figure out what the problem was...

@Sashkan make sure you change this line in the knock.rb by
config.token_secret_signature_key = -> { Rails.application.secrets.auth0_client_secret }
as @SiDevesh suggested.

Auth0 algorithm toggle is not working ATM so make sure that you use RS256 by default
config.token_signature_algorithm = 'RS256'

Should work fine after that :+1:

Worth noting that #124 does this same thing, but via JSON::JWT. Introduces a new dependency to knock, but it works transparently, rather than having to generate a new cert just to interpret and decode the public key.

Thanks @jessecravens! This was super frustrating, you're a life saver!

Thanks @jessecravens! Your solution saved me a ton of headache!

@Sashkan did you make progress? I'm stuck with the same piece, though this does give me back the PEM I need...

How is this not part of the core README? It's a breaking change from prior behavior with Auth0...

@jessecravens YOU ARE A HERO!!!!

I also encountered the same problem as described above:
no method 'verify' for type String
but I was not using Auth0 so I had no idea what @jessecravens is talking about.

I think the point that is missing in the description of config/initializers/knock.rb is that token_public_key needs to be of type OpenSSL::PKey::RSA. I passed the public key as a String.
But I got it working with:

config.token_public_key = OpenSSL::PKey::RSA.new(
  File.read('some_key.pub')
)

I think it would be better if knock was accepting a String and creates an OpenSSL::PKey from it internally.

My man, thank you! This one was brutal.

@jessecravens I know this is old, but thank you so much! I was missing the OpenSSL::PKey::RSA bit and it was driving me insane!

Was this page helpful?
0 / 5 - 0 ratings