verify signature JWT
ErnstA opened this issue · 4 comments
I have a JWT
"eyJhbGciOiJSUzI1Ni..."
I can get the public key as a Ruby hash:
{"use"=>"sig",
"kty"=>"RSA",
"kid"=>"public",
"n"=>
"usTrcR3PIAKm37Q1...",
"e"=>"AQAB"}
JSON::JWT.decode jwt, :skip_verification
=> {"aud"=>"e0172bf8-9d09-4ed8-b8ac-b1d07b43ae77",
"exp"=>1487993654,
"jti"=>"131bc753-bdd9-40e3-901c-a80a61240740",
"redir"=> "https://test.....org/oauth2/auth?client_id=e01....",
"scp"=>["hydra", "offline", "openid"]
}
BUT
jwk2 = JSON::JWK.new jwk
JSON::JWT.decode jwt , jwk2
ArgumentError: wrong number of arguments (given 0, expected 1)
from /home/ernst/.rvm/gems/ruby-2.3.0@rails5.0.0.1_students/gems/keystores-0.2.0/lib/keystores/jks/pkcs8_key.rb:63:in `block in <class:RSA>'
BTW
How to convert the key
{"use"=>"sig",
"kty"=>"RSA",
"kid"=>"public",
"n"=>
"usTrcR3PIAKm37Q1...",
"e"=>"AQAB"}
to PEM format? Either in Ruby or if that is not available on the Linux command line.
This code works fine, so I have no idea what's wrong on your side.
See your code around line#63 of "pkcs8_key.rb".
For PEM generation, you can get OpenSSL::PKey::RSA
instance by calling JSON::JWK#to_key
, so that you can get PEMized JWK by calling jwk.to_key.to_pem
.
require 'json/jwt'
private_key = OpenSSL::PKey::RSA.generate 2048
public_jwk = JSON::JWK.new private_key.public_key
puts <<-JWK
# Public JWK
#{JSON.pretty_generate public_jwk}
JWK
jwt_claims = {
foo: :bar
}
plain_jwt = JSON::JWT.new jwt_claims
signed_jwt = plain_jwt.sign private_key
jwt_string = signed_jwt.to_s
puts <<-JWT
# JWT String
#{jwt_string}
JWT
decoded_jwt = JSON::JWT.decode jwt_string, public_jwk
puts <<-JWT
# Decoded JWT
## Header
#{JSON.pretty_generate decoded_jwt.header}
## Payload
#{JSON.pretty_generate decoded_jwt}
JWT
pemized_jwk = public_jwk.to_key.to_pem
puts <<-PEM
# PEMized JWK
#{pemized_jwk}
PEM
Thanks Nov, I run your example from above in an Rspec test and it fails here:
> decoded_jwt = JSON::JWT.decode jwt_string, public_jwk
ArgumentError: wrong number of arguments (given 0, expected 1)
from /home/ernst/.rvm/gems/ruby-2.3.0@rails5.0.0.1_students/gems/keystores-0.2.0/lib/keystores/jks/pkcs8_key.rb:63:in `block in <class:RSA>'
versions: ruby-2.3.0@rails5.0.0.1
pkcs8_key.rb:63
class RSA
original_initialize = instance_method(:initialize)
define_method(:initialize) do |der_or_pem| # line 63
init = original_initialize.bind(self)
begin
init.(der_or_pem)
rescue Exception
RSA.new does not get a parameter
keystores-0.2.0/lib/keystores/jks/pkcs8_key.rb:63:in `block in <class:RSA>'
json-jwt-1.6.5/lib/json/jwk.rb:98:in `new'
json-jwt-1.6.5/lib/json/jwk.rb:98:in `to_rsa_key'
json-jwt-1.6.5/lib/json/jwk.rb:43:in `to_key'
json-jwt-1.6.5/lib/json/jose.rb:26:in `with_jwk_support'
json-jwt-1.6.5/lib/json/jws.rb:88:in `valid?'
json-jwt-1.6.5/lib/json/jws.rb:25:in `verify!'
json-jwt-1.6.5/lib/json/jws.rb:149:in `decode_compact_serialized'
json-jwt-1.6.5/lib/json/jwt.rb:86:in `decode_compact_serialized'
json-jwt-1.6.5/lib/json/jose.rb:52:in `decode
json-jwt-1.6.5/lib/json/jwk.rb
def to_rsa_key
e, n, d, p, q = [:e, :n, :d, :p, :q].collect do |key|
if self[key]
OpenSSL::BN.new UrlSafeBase64.decode64(self[key]), 2
end
end
key = OpenSSL::PKey::RSA.new # line 98
key.e = e
key.n = n
seems there is some incompatibility in the libraries I use.
Now it works. I had in my Gemfile
gem 'keystores' # https://github.com/rylarson/keystores
After removing that gem it works.