From 55a5923ed6d8939a852cd0a81ed9f631d321650d Mon Sep 17 00:00:00 2001 From: 5andi5 <5andi5@inbox.lv> Date: Mon, 22 May 2023 15:05:58 +0300 Subject: [PATCH 1/6] Upgrade from OmniAuth 1 to OmniAuth 2. Update company info. Other tiny fixes. --- .travis.yml | 1 + Gemfile | 4 ++-- README.md | 6 ++++-- lib/omniauth/strategies/seb.rb | 11 ++++++++++- omniauth-seb-elink.gemspec | 8 ++++---- spec/omniauth/strategies/seb_spec.rb | 12 +++++++++++- 6 files changed, 32 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4d53987..3756708 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,4 +4,5 @@ rvm: - 2.4 - 2.5 - 2.6 + - 3.2 script: bundle exec rspec diff --git a/Gemfile b/Gemfile index 2119b36..88f3cf4 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,4 @@ source 'https://rubygems.org' -# Specify your gem's dependencies in omniauth-nordea.gemspec -gemspec \ No newline at end of file +# Specify your gem's dependencies in omniauth-seb-elink.gemspec +gemspec diff --git a/README.md b/README.md index e6539c9..ecc5e3b 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ Omniauth strategy for using SEB e-link as an authentication service provider. Supported Ruby versions: 2.2+ ## Related projects + - [omniauth-citadele](https://github.com/mak-it/omniauth-citadele) - strategy for authenticating with Citadele - [omniauth-dnb](https://github.com/mak-it/omniauth-dnb) - strategy for authenticating with DNB - [omniauth-nordea](https://github.com/mak-it/omniauth-nordea) - strategy for authenticating with Nordea @@ -14,8 +15,9 @@ Supported Ruby versions: 2.2+ ## Installation -Add this line to your application's Gemfile: +Add these lines to your application's Gemfile (omniauth-rails_csrf_protection is required if using Rails): + gem 'omniauth-rails_csrf_protection' gem 'omniauth-seb-elink' And then execute: @@ -24,7 +26,7 @@ And then execute: Or install it yourself as: - $ gem install omniauth-seb-elink + $ gem install gem omniauth-rails_csrf_protection omniauth-seb-elink ## Usage diff --git a/lib/omniauth/strategies/seb.rb b/lib/omniauth/strategies/seb.rb index a749be1..348bb86 100644 --- a/lib/omniauth/strategies/seb.rb +++ b/lib/omniauth/strategies/seb.rb @@ -71,8 +71,13 @@ def request_phase # Build redirect form form = OmniAuth::Form.new(title: I18n.t('omniauth.seb.please_wait'), url: options.site) + csrf = request.env["rack.session"]["csrf"] + unless csrf.nil? + form.html "" + end + message.each_pair do |k,v| - form.html "" + form.html "" end form.button I18n.t('omniauth.seb.click_here_if_not_redirected') @@ -80,6 +85,10 @@ def request_phase form.to_html.gsub('', '')) form.to_response end + + def escape(html_attribute_value) + CGI.escapeHTML(html_attribute_value) unless html_attribute_value.nil? + end end end end diff --git a/omniauth-seb-elink.gemspec b/omniauth-seb-elink.gemspec index 8a10b1e..7d2f9d6 100644 --- a/omniauth-seb-elink.gemspec +++ b/omniauth-seb-elink.gemspec @@ -6,11 +6,11 @@ require 'omniauth/seb/version' Gem::Specification.new do |gem| gem.name = 'omniauth-seb-elink' gem.version = Omniauth::Seb::VERSION - gem.authors = ['MAK IT'] - gem.email = ['admin@makit.lv'] + gem.authors = ['Mitigate'] + gem.email = ['admin@mitigate.dev'] gem.description = %q{OmniAuth strategy for SEB e-link} gem.summary = %q{OmniAuth strategy for SEB e-link} - gem.homepage = 'https://github.com/mak-it/omniauth-seb-elink' + gem.homepage = 'https://github.com/mitigate-dev/omniauth-seb-elink' gem.license = 'MIT' gem.files = `git ls-files`.split($/) @@ -20,7 +20,7 @@ Gem::Specification.new do |gem| gem.required_ruby_version = '>= 2.2.2' - gem.add_runtime_dependency 'omniauth', '~> 1.0' + gem.add_runtime_dependency 'omniauth', '~> 2.1' gem.add_runtime_dependency 'i18n' gem.add_development_dependency 'rack-test' diff --git a/spec/omniauth/strategies/seb_spec.rb b/spec/omniauth/strategies/seb_spec.rb index 8d0d206..c39f3d7 100644 --- a/spec/omniauth/strategies/seb_spec.rb +++ b/spec/omniauth/strategies/seb_spec.rb @@ -1,4 +1,5 @@ require 'spec_helper' +require 'rack-protection' describe OmniAuth::Strategies::Seb do PUBLIC_CRT = File.read(File.join(RSpec.configuration.cert_folder, 'response.public.pem')) @@ -10,8 +11,17 @@ b.run lambda{|env| [404, {}, ['Not Found']]} end.to_app } + let(:token){ Rack::Protection::AuthenticityToken.random_token } + context 'request phase' do - before(:each) { get '/auth/seb' } + before(:each) do + post( + '/auth/seb', + {}, + 'rack.session' => {csrf: token}, + 'HTTP_X_CSRF_TOKEN' => token + ) + end it 'displays a single form' do expect(last_response.status).to eq(200) From 17e2cbe66339c91799786d89f2a90dc8b091dbc4 Mon Sep 17 00:00:00 2001 From: 5andi5 <5andi5@inbox.lv> Date: Mon, 22 May 2023 15:17:27 +0300 Subject: [PATCH 2/6] Add Content Security Policy support. Previously redirect script was blocked unless CSP included script_src unsafe_inline. --- lib/omniauth/strategies/seb.rb | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/omniauth/strategies/seb.rb b/lib/omniauth/strategies/seb.rb index 348bb86..4d5b1b0 100644 --- a/lib/omniauth/strategies/seb.rb +++ b/lib/omniauth/strategies/seb.rb @@ -12,6 +12,14 @@ class ValidationError < StandardError; end include OmniAuth::Strategy + def self.render_nonce + defined?(ActionDispatch::ContentSecurityPolicy::Request) != nil + end + if render_nonce + include ActionDispatch::ContentSecurityPolicy::Request + delegate :get_header, :set_header, to: :request + end + args [:public_crt, :snd_id] option :public_crt, nil @@ -81,8 +89,12 @@ def request_phase end form.button I18n.t('omniauth.seb.click_here_if_not_redirected') + nonce_attribute = nil + if self.class.render_nonce + nonce_attribute = " nonce='#{escape(content_security_policy_nonce)}'" + end form.instance_variable_set('@html', - form.to_html.gsub('', '')) + form.to_html.gsub('', "")) form.to_response end From 3334f8f81134f3c92c3d9415a7bbe2bde469541b Mon Sep 17 00:00:00 2001 From: 5andi5 <5andi5@inbox.lv> Date: Mon, 26 Jun 2023 21:00:06 +0300 Subject: [PATCH 3/6] Fixes --- README.md | 12 ++++++------ lib/omniauth/strategies/seb.rb | 13 +++++-------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index ecc5e3b..b39239b 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,16 @@ Omniauth strategy for using SEB e-link as an authentication service provider. -[![Build Status](https://travis-ci.org/mak-it/omniauth-seb-elink.svg?branch=master)](https://travis-ci.org/mak-it/omniauth-seb-elink) +[![Build Status](https://travis-ci.org/mitigate-dev/omniauth-seb-elink.svg?branch=master)](https://travis-ci.org/mitigate-dev/omniauth-seb-elink) Supported Ruby versions: 2.2+ ## Related projects -- [omniauth-citadele](https://github.com/mak-it/omniauth-citadele) - strategy for authenticating with Citadele -- [omniauth-dnb](https://github.com/mak-it/omniauth-dnb) - strategy for authenticating with DNB -- [omniauth-nordea](https://github.com/mak-it/omniauth-nordea) - strategy for authenticating with Nordea -- [omniauth-swedbank](https://github.com/mak-it/omniauth-swedbank) - strategy for authenticating with Swedbank +- [omniauth-citadele](https://github.com/mitigate-dev/omniauth-citadele) - strategy for authenticating with Citadele +- [omniauth-dnb](https://github.com/mitigate-dev/omniauth-dnb) - strategy for authenticating with DNB +- [omniauth-nordea](https://github.com/mitigate-dev/omniauth-nordea) - strategy for authenticating with Nordea +- [omniauth-swedbank](https://github.com/mitigate-dev/omniauth-swedbank) - strategy for authenticating with Swedbank ## Installation @@ -26,7 +26,7 @@ And then execute: Or install it yourself as: - $ gem install gem omniauth-rails_csrf_protection omniauth-seb-elink + $ gem install omniauth-rails_csrf_protection omniauth-seb-elink ## Usage diff --git a/lib/omniauth/strategies/seb.rb b/lib/omniauth/strategies/seb.rb index 4d5b1b0..044a177 100644 --- a/lib/omniauth/strategies/seb.rb +++ b/lib/omniauth/strategies/seb.rb @@ -12,10 +12,10 @@ class ValidationError < StandardError; end include OmniAuth::Strategy - def self.render_nonce + def self.render_nonce? defined?(ActionDispatch::ContentSecurityPolicy::Request) != nil end - if render_nonce + if render_nonce? include ActionDispatch::ContentSecurityPolicy::Request delegate :get_header, :set_header, to: :request end @@ -79,18 +79,13 @@ def request_phase # Build redirect form form = OmniAuth::Form.new(title: I18n.t('omniauth.seb.please_wait'), url: options.site) - csrf = request.env["rack.session"]["csrf"] - unless csrf.nil? - form.html "" - end - message.each_pair do |k,v| form.html "" end form.button I18n.t('omniauth.seb.click_here_if_not_redirected') nonce_attribute = nil - if self.class.render_nonce + if self.class.render_nonce? nonce_attribute = " nonce='#{escape(content_security_policy_nonce)}'" end form.instance_variable_set('@html', @@ -98,6 +93,8 @@ def request_phase form.to_response end + private + def escape(html_attribute_value) CGI.escapeHTML(html_attribute_value) unless html_attribute_value.nil? end From 293db27a5e577206888b6df5f92d614d81e65a39 Mon Sep 17 00:00:00 2001 From: 5andi5 <5andi5@inbox.lv> Date: Mon, 26 Jun 2023 22:37:23 +0300 Subject: [PATCH 4/6] Resolve bank UI language from I18n locale --- lib/omniauth/strategies/seb.rb | 19 ++++++++++++++++++- spec/omniauth/strategies/seb_spec.rb | 2 +- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/omniauth/strategies/seb.rb b/lib/omniauth/strategies/seb.rb index 044a177..f7f1dc3 100644 --- a/lib/omniauth/strategies/seb.rb +++ b/lib/omniauth/strategies/seb.rb @@ -70,10 +70,12 @@ def callback_phase def request_phase fail!(:invalid_snd_id) if options.snd_id.nil? + set_locale_from_query_param + message = OmniAuth::Strategies::Seb::Message.new( 'IB_SND_ID': options.snd_id, 'IB_SERVICE': AUTH_SERVICE, - 'IB_LANG': 'LAT' + 'IB_LANG': resolve_bank_ui_language ) # Build redirect form @@ -95,6 +97,21 @@ def request_phase private + def set_locale_from_query_param + locale = request.params['locale'] + if (locale != nil && locale.strip != '' && I18n.locale_available?(locale)) + I18n.locale = locale + end + end + + def resolve_bank_ui_language + case I18n.locale + when :ru then 'RUS' + when :en then 'ENG' + else 'LAT' + end + end + def escape(html_attribute_value) CGI.escapeHTML(html_attribute_value) unless html_attribute_value.nil? end diff --git a/spec/omniauth/strategies/seb_spec.rb b/spec/omniauth/strategies/seb_spec.rb index c39f3d7..e61456e 100644 --- a/spec/omniauth/strategies/seb_spec.rb +++ b/spec/omniauth/strategies/seb_spec.rb @@ -35,7 +35,7 @@ EXPECTED_VALUES = { 'IB_SND_ID': SND_ID, 'IB_SERVICE': OmniAuth::Strategies::Seb::AUTH_SERVICE, - 'IB_LANG': 'LAT' + 'IB_LANG': 'ENG' } EXPECTED_VALUES.each_pair do |k,v| From f50bc0df120d3b5fafb2cbb6a03faf8d50bb3315 Mon Sep 17 00:00:00 2001 From: 5andi5 <5andi5@inbox.lv> Date: Tue, 22 Aug 2023 10:13:29 +0300 Subject: [PATCH 5/6] From 30.09.2023 SEB changes signature hashing algorithm to SHA-512. Add fallback for this switch --- lib/omniauth/strategies/seb/response.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/omniauth/strategies/seb/response.rb b/lib/omniauth/strategies/seb/response.rb index adf302b..78b4164 100644 --- a/lib/omniauth/strategies/seb/response.rb +++ b/lib/omniauth/strategies/seb/response.rb @@ -22,8 +22,12 @@ def validate!(pub_key) raw_str = SIGNED_KEYS.map{|k| prepend_length(@hash[k])}.join received_sig_str = Base64.decode64(@hash['IB_CRC']) - if !pub_key.verify(OpenSSL::Digest::SHA1.new, received_sig_str, raw_str) - raise ValidationError, 'Invalid signature' + if !pub_key.verify(OpenSSL::Digest::SHA512.new, received_sig_str, raw_str) + if !pub_key.verify(OpenSSL::Digest::SHA1.new, received_sig_str, raw_str) + raise ValidationError, 'Invalid signature' + else + OmniAuth.logger.debug('Received message with old SHA1 signature from SEB') + end end self From c921f1ebf7dc27792b778dd9ce9c112deec2241b Mon Sep 17 00:00:00 2001 From: 5andi5 <5andi5@inbox.lv> Date: Tue, 26 Sep 2023 16:52:49 +0300 Subject: [PATCH 6/6] Improvements according to code review --- lib/omniauth/strategies/seb.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/omniauth/strategies/seb.rb b/lib/omniauth/strategies/seb.rb index f7f1dc3..c89b15d 100644 --- a/lib/omniauth/strategies/seb.rb +++ b/lib/omniauth/strategies/seb.rb @@ -99,9 +99,7 @@ def request_phase def set_locale_from_query_param locale = request.params['locale'] - if (locale != nil && locale.strip != '' && I18n.locale_available?(locale)) - I18n.locale = locale - end + I18n.locale = locale if I18n.locale_available?(locale) end def resolve_bank_ui_language