diff --git a/Gemfile b/Gemfile index 18a70463f..e2c2022b1 100644 --- a/Gemfile +++ b/Gemfile @@ -31,6 +31,7 @@ gem 'devise-two-factor' gem 'discard' gem 'dotenv-rails', require: 'dotenv/rails-now' # dotenv should always be loaded before rails gem 'dry-monads' +gem 'faraday-jwt' gem 'flipper' gem 'flipper-active_record' gem 'flipper-active_support_cache_store' diff --git a/Gemfile.lock b/Gemfile.lock index 088b30b0f..4a2910f40 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -136,7 +136,7 @@ GEM parser (>= 2.4) smart_properties bigdecimal (3.1.6) - bindata (2.4.15) + bindata (2.5.0) bindex (0.8.1) bootsnap (1.18.3) msgpack (~> 1.2) @@ -223,6 +223,8 @@ GEM dry-core (~> 1.0, < 2) zeitwerk (~> 2.6) dumb_delegator (1.0.0) + email_validator (2.2.4) + activemodel erubi (1.12.0) et-orbi (1.2.7) tzinfo @@ -231,6 +233,15 @@ GEM excon (0.109.0) factory_bot (6.4.6) activesupport (>= 5.0.0) + faraday (2.9.0) + faraday-net_http (>= 2.0, < 3.2) + faraday-follow_redirects (0.3.0) + faraday (>= 1, < 3) + faraday-jwt (0.1.0) + faraday (~> 2.0) + json-jwt (~> 1.16) + faraday-net_http (3.1.0) + net-http ffi (1.16.3) flipper (1.2.2) concurrent-ruby (< 2) @@ -308,8 +319,7 @@ GEM highline (3.0.1) htmlentities (4.3.4) http_accept_language (2.1.1) - httpclient (2.8.3) - i18n (1.14.1) + i18n (1.14.4) concurrent-ruby (~> 1.0) i18n-tasks (1.0.13) activesupport (>= 4.0.2) @@ -341,10 +351,13 @@ GEM railties (>= 4.2.0) thor (>= 0.14, < 2.0) json (2.7.1) - json-jwt (1.13.0) + json-jwt (1.16.6) activesupport (>= 4.2) aes_key_wrap + base64 bindata + faraday (~> 2.0) + faraday-follow_redirects json_schemer (2.1.1) hana (~> 1.3) regexp_parser (~> 2.0) @@ -418,6 +431,8 @@ GEM multi_json (1.15.0) mustermann (3.0.0) ruby2_keywords (~> 0.0.1) + net-http (0.4.1) + uri net-imap (0.4.10) date net-protocol @@ -431,16 +446,19 @@ GEM nokogiri (1.16.2) mini_portile2 (~> 2.8.2) racc (~> 1.4) - openid_connect (1.3.0) + openid_connect (2.3.0) activemodel attr_required (>= 1.0.0) - json-jwt (>= 1.5.0) - rack-oauth2 (>= 1.6.1) - swd (>= 1.0.0) + email_validator + faraday (~> 2.0) + faraday-follow_redirects + json-jwt (>= 1.16) + mail + rack-oauth2 (~> 2.2) + swd (~> 2.0) tzinfo - validate_email validate_url - webfinger (>= 1.0.1) + webfinger (~> 2.0) orm_adapter (0.5.0) parallel (1.24.0) parsby (1.1.1) @@ -482,10 +500,11 @@ GEM rack (>= 1.0, < 4) rack-mini-profiler (3.3.1) rack (>= 1.2.0) - rack-oauth2 (1.19.0) + rack-oauth2 (2.2.1) activesupport attr_required - httpclient + faraday (~> 2.0) + faraday-follow_redirects json-jwt (>= 1.11.0) rack (>= 2.1.0) rack-protection (3.2.0) @@ -710,10 +729,11 @@ GEM stringio (3.1.0) strong_migrations (1.7.0) activerecord (>= 5.2) - swd (1.3.0) + swd (2.0.3) activesupport (>= 3) attr_required (>= 0.0.5) - httpclient (>= 2.4) + faraday (~> 2.0) + faraday-follow_redirects sysexits (1.2.0) temple (0.8.2) terminal-table (3.0.2) @@ -737,9 +757,7 @@ GEM unf_ext unf_ext (0.0.9.1) unicode-display_width (2.5.0) - validate_email (0.1.6) - activemodel (>= 3.0) - mail (>= 2.2.5) + uri (0.13.0) validate_url (1.0.15) activemodel (>= 3.0.0) public_suffix @@ -766,9 +784,10 @@ GEM activemodel (>= 6.0.0) bindex (>= 0.4.0) railties (>= 6.0.0) - webfinger (1.2.0) + webfinger (2.1.3) activesupport - httpclient (>= 2.4) + faraday (~> 2.0) + faraday-follow_redirects webmock (3.20.0) addressable (>= 2.8.0) crack (>= 0.3.2) @@ -834,6 +853,7 @@ DEPENDENCIES dotenv-rails dry-monads factory_bot + faraday-jwt flipper flipper-active_record flipper-active_support_cache_store diff --git a/config/env.example b/config/env.example index fb73329e1..39d6787e2 100644 --- a/config/env.example +++ b/config/env.example @@ -56,7 +56,6 @@ FC_PARTICULIER_BASE_URL="" AGENT_CONNECT_ID="" AGENT_CONNECT_SECRET="" AGENT_CONNECT_BASE_URL="" -AGENT_CONNECT_JWKS="" AGENT_CONNECT_REDIRECT="" # External service: integration with HelpScout (optional) diff --git a/config/initializers/open_id_connect.rb b/config/initializers/open_id_connect.rb index 5266653b8..2234fd763 100644 --- a/config/initializers/open_id_connect.rb +++ b/config/initializers/open_id_connect.rb @@ -1,61 +1,7 @@ -OpenIDConnect.debug! -OpenIDConnect.logger = Rails.logger -Rack::OAuth2.logger = Rails.logger -# Webfinger.logger = Rails.logger -SWD.logger = Rails.logger +OpenIDConnect.http_config do |config| + config.response :jwt -# the openid_connect gem does not support -# jwt format in the userinfo call. -# A PR is open to improve the situation -# https://github.com/nov/openid_connect/pull/54 -module OpenIDConnect - class AccessToken < Rack::OAuth2::AccessToken::Bearer - private - - def jwk_loader - JSON.parse(URI.parse(ENV['AGENT_CONNECT_JWKS']).read).deep_symbolize_keys - end - - def decode_jwt(requested_host, jwt) - agent_connect_host = URI.parse(ENV['AGENT_CONNECT_BASE_URL']).host - - if requested_host == agent_connect_host - # rubocop:disable Lint/UselessAssignment - JWT.decode(jwt, key = nil, verify = true, { algorithms: ['ES256'], jwks: jwk_loader })[0] - # rubocop:enable Lint/UselessAssignment - else - raise "unknwon host : #{requested_host}" - end - end - - def resource_request - res = yield - case res.status - when 200 - hash = case parse_type_and_subtype(res.content_type) - when 'application/jwt' - requested_host = URI.parse(client.userinfo_endpoint).host - decode_jwt(requested_host, res.body) - when 'application/json' - JSON.parse(res.body) - end - hash&.with_indifferent_access - when 400 - raise BadRequest.new('API Access Faild', res) - when 401 - raise Unauthorized.new('Access Token Invalid or Expired', res) - when 403 - raise Forbidden.new('Insufficient Scope', res) - else - raise HttpError.new(res.status, 'Unknown HttpError', res) - end - end - - # https://datatracker.ietf.org/doc/html/rfc2045#section-5.1 - # - type and subtype are the first member - # they are case insensitive - def parse_type_and_subtype(content_type) - content_type.split(';')[0].strip.downcase - end + if ENV['http_proxy'].present? + config.proxy = ENV['http_proxy'] end end