json-jwt: verify throwing an error in JSON::JWT.decode
In https://github.com/onli/sinatra-browserid/blob/88ae06ebf8248a277759f9917eb65249cf6711c2/lib/sinatra/browserid.rb#L35 I’m calling decode on string which is generated in https://github.com/callahad/authbackend/blob/e14f16899fc7a3dadf84651b897eac2eccc1d74d/server.rb#L381, by JWT.encode. If not skipping verification, this is leading to an error:
NoMethodError - undefined method `verify' for #<String:0x00000003e86478>:
/home/onli/Dropbox-decrypted/ursprung.git/vendor/bundle/ruby/2.2.0/gems/json-jwt-1.5.2/lib/json/jws.rb:94:in `valid?'
/home/onli/Dropbox-decrypted/ursprung.git/vendor/bundle/ruby/2.2.0/gems/json-jwt-1.5.2/lib/json/jws.rb:25:in `verify!'
/home/onli/Dropbox-decrypted/ursprung.git/vendor/bundle/ruby/2.2.0/gems/json-jwt-1.5.2/lib/json/jws.rb:162:in `decode_compact_serialized'
/home/onli/Dropbox-decrypted/ursprung.git/vendor/bundle/ruby/2.2.0/gems/json-jwt-1.5.2/lib/json/jwt.rb:77:in `decode_compact_serialized'
/home/onli/Dropbox-decrypted/ursprung.git/vendor/bundle/ruby/2.2.0/gems/json-jwt-1.5.2/lib/json/jose.rb:39:in `decode'
I’m assuming I have to wrap the jwt-token-string in something. But this is not covered by the docu in https://github.com/nov/json-jwt/wiki/JWS#verifying, where that function is called with a normal string. Thus I assume this is a bug in docu or implementation.
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 2
- Comments: 20 (7 by maintainers)
Ah, JWKS (JSON::JWK::Set, an array of JWKs) is different from JWK (JSON::JWK). Try this.
I assume your
public_keyonJSON::JWT.decode params[:id_token], public_keycall is aString, and your JWT header includesalg=RS256.In that case, you need to put a
OpenSSL::PKey::RSAorJSON::JWKas thepublic_key.like
JSON::JWT.decode params[:id_token], OpenSSL::PKey::RSA.new(public_key)Ran into same issue, better error message/general fix on the JSON JWT side for handling this case would be very helpful
Thanks for the answer, and sorry for the delay.
That is sadly leading to a different error message:
I debugged this as far as I could. In
with_jwk_supportin jose.rb, https://github.com/nov/json-jwt/blob/master/lib/json/jose.rb#L28, this is how key looks like:Please notice the kid below k, and the other kid above. The kid at the top level is coming from the jwk constructor in jwk.rb:
thumbprint is what ends up in key. I read up the code of that, it seems to be the base64 encoded sha256 hash of parts of the jwk, e kty and n. But my backend is defining the kid as such:
As far as I know the spec, how kid defined is unspecified. But to change the backend to work with one specific jwk library seems wrong. May I suggest changing that code to work with the inner kid? Assuming I’m not on the wrong track here.
Hi @nov, thanks for your answer!
My JWT header indeed includesI’m actually not sure whether the header is properly set. But public_key is not a string, it is already aalg=RS256JSON::JWK.params[:id_token]is aString, but this is the whole idea of the decode function, isn’t it? This is the relevant code on my side:The jwks.json on the server is (linked above) defined like this:
I think it is something in the internals of JSON::JWT.decode that makes the verify try to work on a string.
I did not highlight that properly above, but the
JWT.encodethat encodesparams[:id_token]for transport is coming from the ‘jwt’ gem, not ‘json/jwt’. That’s the call:An incompatibility?
I’m not sure I follow. Could you point out more directly what the solution would be? Instead of
JSON::JWT.decode params[:id_token], public_keyfor decoding the encoded string, I would use a different call? Or would the server have to change something?Thank you for putting this doc here, I was having problems in Rails with this, and couldn’t spin my head around. I would suggest to check the algorithm you are using, and should be HMAC for strings! The document you provided actually states it, and ended up fixing it for me: