diff --git a/CHANGELOG.md b/CHANGELOG.md index 9dfa215..d465cc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ - [#180] Add PKCE support to OpenID discovery endpoint. +## Unreleased next + +- [#177] Replace `json-jwt` with `ruby-jwt` to align with doorkeeper-jwt. + ## v1.8.2 (2022-07-13) - [#168] Allow to use custom doorkeeper access grant model (thanks @nov). diff --git a/doorkeeper-openid_connect.gemspec b/doorkeeper-openid_connect.gemspec index fd3ab31..2faf8fa 100644 --- a/doorkeeper-openid_connect.gemspec +++ b/doorkeeper-openid_connect.gemspec @@ -25,7 +25,7 @@ Gem::Specification.new do |spec| spec.required_ruby_version = '>= 2.6' spec.add_runtime_dependency 'doorkeeper', '>= 5.5', '< 5.7' - spec.add_runtime_dependency 'json-jwt', '>= 1.15.0' + spec.add_runtime_dependency 'jwt', '>= 2.5' spec.add_development_dependency 'conventional-changelog', '~> 1.2' spec.add_development_dependency 'factory_bot' diff --git a/lib/doorkeeper/openid_connect.rb b/lib/doorkeeper/openid_connect.rb index 51998d5..93e227f 100644 --- a/lib/doorkeeper/openid_connect.rb +++ b/lib/doorkeeper/openid_connect.rb @@ -2,7 +2,7 @@ require 'doorkeeper' require 'active_model' -require 'json/jwt' +require 'jwt' require 'doorkeeper/request' require 'doorkeeper/request/id_token' @@ -48,19 +48,11 @@ def self.signing_key else OpenSSL::PKey.read(configuration.signing_key) end - JSON::JWK.new(key) + JWT::JWK.new(key) end def self.signing_key_normalized - key = signing_key - case key[:kty].to_sym - when :RSA - key.slice(:kty, :kid, :e, :n) - when :EC - key.slice(:kty, :kid, :crv, :x, :y) - when :oct - key.slice(:kty, :kid) - end + signing_key.export end Doorkeeper::GrantFlow.register( diff --git a/lib/doorkeeper/openid_connect/id_token.rb b/lib/doorkeeper/openid_connect/id_token.rb index 1064007..f003637 100644 --- a/lib/doorkeeper/openid_connect/id_token.rb +++ b/lib/doorkeeper/openid_connect/id_token.rb @@ -31,9 +31,10 @@ def as_json(*_) end def as_jws_token - JSON::JWT.new(as_json).sign( - Doorkeeper::OpenidConnect.signing_key, - Doorkeeper::OpenidConnect.signing_algorithm + JWT.encode(as_json, + Doorkeeper::OpenidConnect.signing_key.keypair, + Doorkeeper::OpenidConnect.signing_algorithm.to_s, + { kid: Doorkeeper::OpenidConnect.signing_key.kid } ).to_s end diff --git a/spec/dummy/config/initializers/jwt.rb b/spec/dummy/config/initializers/jwt.rb new file mode 100644 index 0000000..568fe11 --- /dev/null +++ b/spec/dummy/config/initializers/jwt.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +JWT.configuration.jwk.kid_generator_type = :rfc7638_thumbprint diff --git a/spec/lib/id_token_spec.rb b/spec/lib/id_token_spec.rb index 835c373..154f7ec 100644 --- a/spec/lib/id_token_spec.rb +++ b/spec/lib/id_token_spec.rb @@ -72,8 +72,13 @@ describe '#as_jws_token' do shared_examples 'a jws token' do it 'returns claims encoded as JWT' do - jwt = JSON::JWT.decode_compact_serialized subject.as_jws_token, Doorkeeper::OpenidConnect.signing_key - expect(jwt.to_hash).to eq subject.as_json.stringify_keys + algorithms = [Doorkeeper::OpenidConnect.signing_algorithm.to_s] + + data, headers = JWT.decode subject.as_jws_token, Doorkeeper::OpenidConnect.signing_key.keypair, true, { algorithms: algorithms } + + expect(data.to_hash).to eq subject.as_json.stringify_keys + expect(headers["kid"]).to eq Doorkeeper::OpenidConnect.signing_key.kid + expect(headers["alg"]).to eq Doorkeeper::OpenidConnect.signing_algorithm.to_s end end diff --git a/spec/lib/openid_connect_spec.rb b/spec/lib/openid_connect_spec.rb index 813d8d0..0c968ff 100644 --- a/spec/lib/openid_connect_spec.rb +++ b/spec/lib/openid_connect_spec.rb @@ -11,8 +11,8 @@ describe '.signing_key' do it 'returns the private key as JWK instance' do - expect(subject.signing_key).to be_instance_of JSON::JWK - expect(subject.signing_key[:kid]).to eq 'IqYwZo2cE6hsyhs48cU8QHH4GanKIx0S4Dc99kgTIMA' + expect(subject.signing_key).to be_a JWT::JWK::KeyBase + expect(subject.signing_key.kid).to eq 'IqYwZo2cE6hsyhs48cU8QHH4GanKIx0S4Dc99kgTIMA' end end @@ -20,10 +20,10 @@ context 'when signing key is RSA' do it 'returns the RSA public key parameters' do expect(subject.signing_key_normalized).to eq( - 'kty' => :RSA, - 'kid' => 'IqYwZo2cE6hsyhs48cU8QHH4GanKIx0S4Dc99kgTIMA', - 'e' => 'AQAB', - 'n' => 'sjdnSA6UWUQQHf6BLIkIEUhMRNBJC1NN_pFt1EJmEiI88GS0ceROO5B5Ooo9Y3QOWJ_n-u1uwTHBz0HCTN4wgArWd1TcqB5GQzQRP4eYnWyPfi4CfeqAHzQp-v4VwbcK0LW4FqtW5D0dtrFtI281FDxLhARzkhU2y7fuYhL8fVw5rUhE8uwvHRZ5CEZyxf7BSHxIvOZAAymhuzNLATt2DGkDInU1BmF75tEtBJAVLzWG_j4LPZh1EpSdfezqaXQlcy9PJi916UzTl0P7Yy-ulOdUsMlB6yo8qKTY1-AbZ5jzneHbGDU_O8QjYvii1WDmJ60t0jXicmOkGrOhruOptw' + :kty => 'RSA', + :kid => 'IqYwZo2cE6hsyhs48cU8QHH4GanKIx0S4Dc99kgTIMA', + :e => 'AQAB', + :n => 'sjdnSA6UWUQQHf6BLIkIEUhMRNBJC1NN_pFt1EJmEiI88GS0ceROO5B5Ooo9Y3QOWJ_n-u1uwTHBz0HCTN4wgArWd1TcqB5GQzQRP4eYnWyPfi4CfeqAHzQp-v4VwbcK0LW4FqtW5D0dtrFtI281FDxLhARzkhU2y7fuYhL8fVw5rUhE8uwvHRZ5CEZyxf7BSHxIvOZAAymhuzNLATt2DGkDInU1BmF75tEtBJAVLzWG_j4LPZh1EpSdfezqaXQlcy9PJi916UzTl0P7Yy-ulOdUsMlB6yo8qKTY1-AbZ5jzneHbGDU_O8QjYvii1WDmJ60t0jXicmOkGrOhruOptw' ) end end @@ -33,11 +33,11 @@ it 'returns the EC public key parameters' do expect(subject.signing_key_normalized).to eq( - 'kty' => :EC, - 'kid' => 'dOx_AhaepicN2r2M-sxZhgkYZMCX7dYhPsNOw1ZiFnI', - 'crv' => :'P-521', - 'x' => 'AeYVvbl3zZcFCdE-0msqOowYODjzeXAhjsZKhdNjGlDREvko3UFOw6S43g-s8bvVBmBz3fCodEzFRYQqJVI4UFvF', - 'y' => 'AYJ7GYeBm_Fb6liN53xGASdbRSzF34h4BDSVYzjtQc7I-1LK17fwwS3VfQCJwaT6zX33HTrhR4VoUEUJHKwR3dNs' + :kty => 'EC', + :kid => 'dOx_AhaepicN2r2M-sxZhgkYZMCX7dYhPsNOw1ZiFnI', + :crv => 'P-521', + :x => 'AeYVvbl3zZcFCdE-0msqOowYODjzeXAhjsZKhdNjGlDREvko3UFOw6S43g-s8bvVBmBz3fCodEzFRYQqJVI4UFvF', + :y => 'AYJ7GYeBm_Fb6liN53xGASdbRSzF34h4BDSVYzjtQc7I-1LK17fwwS3VfQCJwaT6zX33HTrhR4VoUEUJHKwR3dNs' ) end end @@ -47,8 +47,8 @@ it 'returns the HMAC public key parameters' do expect(subject.signing_key_normalized).to eq( - 'kty' => :oct, - 'kid' => 'lyAW7LdxryFWQtLdgxZpOrI87APHrzJKgWLT0BkWVog' + :kty => 'oct', + :kid => 'lyAW7LdxryFWQtLdgxZpOrI87APHrzJKgWLT0BkWVog' ) end end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 79b9c48..ba7737d 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -53,6 +53,7 @@ # Reinitialize configuration after each example config.after do + load Rails.root.join('config/initializers/jwt.rb') load Rails.root.join('config/initializers/doorkeeper.rb') load Rails.root.join('config/initializers/doorkeeper_openid_connect.rb') end