omniauth-suomifi 0.1.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3bba7a20e137303ea20efd3d2d829c9e37e103b5c47d864188b50a16cce7d758
4
- data.tar.gz: 481a5fe89956132db550b05d7ffd9e997ae377b6dafb4ba096c4e011edaf0fed
3
+ metadata.gz: 541ef437515bdfaca98ec7fe448e82a2c9008910d0937796cde8b92e92642344
4
+ data.tar.gz: 5a0987732cc390c688f58c9f0f48f579d29ade702a462f5295b0399df9675268
5
5
  SHA512:
6
- metadata.gz: 5e58186eca6d49643657a3e421a5417b9caf988d212c78230224ca1e0e7e0819a46c04adf19f3e94554730cb7090c1cdc786cc4e6cdac61cffe96b9ab3cccd5e
7
- data.tar.gz: 4cac68f67dab309856e7919c2b894322dcb90370968ec2772b5b19d738486afd0b8977ec4ece944c653e65fc862372e881f9553e94ea64afceaa77cd7bd6b876
6
+ metadata.gz: 0b87dcd1dc757088bce48a1cc98594f46c594223fc9d80f7c810ca71a87a762eed52c8906690376c034b2ffc59df73b10783198c3162841a53e171986fb467a5
7
+ data.tar.gz: 8d1fe6697ebe488eb7ced33a1e4caf8fdd91803eb256a039fd4d61ad5e6ebe8900952eba478c96d04b608dc31dae11c6161f05168a772738d3dacba88969fd20
@@ -2,3 +2,4 @@
2
2
 
3
3
  require 'omniauth-suomifi/version'
4
4
  require 'omniauth/strategies/suomifi'
5
+ require 'omniauth-suomifi/ruby_saml_extensions'
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This overrides the decryption method in RubySaml in order to add support for
4
+ # AES GCM decryption required by Suomi.fi. The Suomi.fi AES GCM cipher text
5
+ # contains an auth tag that needs to be extracted from the end of the cipher
6
+ # text before decrypting it. Otherwise the `cipher.final` method would fail
7
+ # becuse the decrypted data is incorrect.
8
+ #
9
+ # Related to this GitHub issue:
10
+ # https://github.com/onelogin/ruby-saml/issues/541
11
+ #
12
+ # This differs from the original implementation only with the following aspects:
13
+ # - Detects the AES GCM cipher methods
14
+ # - For the AES CGM cipher methods, extracts the auth tag from the end of the
15
+ # cipher text, assuming it to be 16 bytes in length.
16
+ #
17
+ # Regarding the authentication tag, see:
18
+ # https://tools.ietf.org/html/rfc5116#section-5.1
19
+ #
20
+ # > An authentication tag with a length of 16 octets (128
21
+ # > bits) is used. The AEAD_AES_128_GCM ciphertext is formed by
22
+ # > appending the authentication tag provided as an output to the GCM
23
+ # > encryption operation to the ciphertext that is output by that
24
+ # > operation.
25
+ OneLogin::RubySaml::Utils.class_eval do
26
+ # Obtains the deciphered text
27
+ # @param cipher_text [String] The ciphered text
28
+ # @param symmetric_key [String] The symetric key used to encrypt the text
29
+ # @param algorithm [String] The encrypted algorithm
30
+ # @return [String] The deciphered text
31
+ def self.retrieve_plaintext(cipher_text, symmetric_key, algorithm)
32
+ case algorithm
33
+ when 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc' then cipher = OpenSSL::Cipher.new('DES-EDE3-CBC').decrypt
34
+ when 'http://www.w3.org/2001/04/xmlenc#aes128-cbc' then cipher = OpenSSL::Cipher.new('AES-128-CBC').decrypt
35
+ when 'http://www.w3.org/2001/04/xmlenc#aes192-cbc' then cipher = OpenSSL::Cipher.new('AES-192-CBC').decrypt
36
+ when 'http://www.w3.org/2001/04/xmlenc#aes256-cbc' then cipher = OpenSSL::Cipher.new('AES-256-CBC').decrypt
37
+ when 'http://www.w3.org/2009/xmlenc11#aes128-gcm' then auth_cipher = OpenSSL::Cipher.new('AES-128-GCM').decrypt
38
+ when 'http://www.w3.org/2009/xmlenc11#aes192-gcm' then auth_cipher = OpenSSL::Cipher.new('AES-192-GCM').decrypt
39
+ when 'http://www.w3.org/2009/xmlenc11#aes256-gcm' then auth_cipher = OpenSSL::Cipher.new('AES-256-GCM').decrypt
40
+ when 'http://www.w3.org/2001/04/xmlenc#rsa-1_5' then rsa = symmetric_key
41
+ when 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p' then oaep = symmetric_key
42
+ end
43
+
44
+ if cipher
45
+ iv_len = cipher.iv_len
46
+ data = cipher_text[iv_len..-1]
47
+ cipher.padding = 0
48
+ cipher.key = symmetric_key
49
+ cipher.iv = cipher_text[0..iv_len - 1]
50
+ assertion_plaintext = cipher.update(data)
51
+ assertion_plaintext << cipher.final
52
+ elsif auth_cipher
53
+ iv_len = auth_cipher.iv_len
54
+ text_len = cipher_text.length
55
+ tag_len = 16
56
+ data = cipher_text[iv_len..text_len - 1 - tag_len]
57
+ auth_cipher.padding = 0
58
+ auth_cipher.key = symmetric_key
59
+ auth_cipher.iv = cipher_text[0..iv_len - 1]
60
+ auth_cipher.auth_data = ''
61
+ auth_cipher.auth_tag = cipher_text[text_len - tag_len..-1]
62
+ assertion_plaintext = auth_cipher.update(data)
63
+ assertion_plaintext << auth_cipher.final
64
+ elsif rsa
65
+ rsa.private_decrypt(cipher_text)
66
+ elsif oaep
67
+ oaep.private_decrypt(cipher_text, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
68
+ else
69
+ cipher_text
70
+ end
71
+ end
72
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module OmniAuth
4
4
  module Suomifi
5
- VERSION = '0.1.0'
5
+ VERSION = '0.5.0'
6
6
  end
7
7
  end
@@ -16,6 +16,29 @@ module OmniAuth
16
16
  # The private key file to define the private key.
17
17
  option :private_key_file, nil
18
18
 
19
+ # Defines the locale parameters to check from the request phase request
20
+ # parameters. A valid language will be added to the IdP sign in redirect
21
+ # URL as the last parameter (with the name `locale` as expected by
22
+ # Suomi.fi).
23
+ #
24
+ # Suomi.fi accepts `fi`, `sv` or `en` in this parameter. The language can
25
+ # be parsed from the following kind of strings:
26
+ # - fi
27
+ # - sv-SE
28
+ # - en_US
29
+ #
30
+ # In case a valid language cannot be parsed from the parameter, the locale
31
+ # parameter will default to `:idp_sso_service_url_default_locale`.
32
+ #
33
+ # Note that the locale parameter is always added as the last parameter in
34
+ # in the redirect URL as expected by Suomi.fi.
35
+ option :idp_sso_service_url_locale_params, %w[locale language lang]
36
+
37
+ # This is the default locale to be passed to IdP sign in redirect URL as
38
+ # defined above. In case a valid locale is not found from the request
39
+ # parameters, this will be used instead.
40
+ option :idp_sso_service_url_default_locale, 'fi'
41
+
19
42
  # The request attributes for Suomi.fi
20
43
  option :possible_request_attributes, [
21
44
  ##############################
@@ -493,6 +516,20 @@ module OmniAuth
493
516
  )
494
517
  end
495
518
 
519
+ # Override the request phase to be able to pass the locale parameter to
520
+ # the redirect URL. Note that this needs to be the last parameter to
521
+ # be passed to the redirect URL.
522
+ def request_phase
523
+ authn_request = OneLogin::RubySaml::Authrequest.new
524
+ locale = locale_for_authn_request
525
+
526
+ with_settings do |settings|
527
+ url = authn_request.create(settings, additional_params_for_authn_request)
528
+ url += "&locale=#{CGI.escape(locale)}" unless locale.nil?
529
+ redirect(url)
530
+ end
531
+ end
532
+
496
533
  # This method can be used externally to fetch information about the
497
534
  # response, e.g. in case of failures.
498
535
  def response_object
@@ -508,12 +545,19 @@ module OmniAuth
508
545
  end
509
546
  end
510
547
 
548
+ # Override the callback URL so that it always matches the one expected by
549
+ # Suomi.fi. No additional query string parameters can be included in the
550
+ # string.
551
+ def callback_url
552
+ full_host + script_name + callback_path
553
+ end
554
+
511
555
  private
512
556
 
513
557
  # Suomi.fi requires that the service provider needs to end the local user
514
558
  # session BEFORE sending the logout request to the identity provider.
515
559
  def other_phase_for_spslo
516
- return super unless options.idp_slo_target_url
560
+ return super unless options.idp_slo_service_url
517
561
 
518
562
  with_settings do |settings|
519
563
  # Some session variables are needed when generating the logout request
@@ -525,6 +569,19 @@ module OmniAuth
525
569
  end
526
570
  end
527
571
 
572
+ # Overridden to disable passing the relay state with a request parameter
573
+ # which is possible in the default implementation.
574
+ def slo_relay_state
575
+ state = super
576
+
577
+ # Ensure that we are only using the relay states to redirect the user
578
+ # within the current website. This forces the relay state to always
579
+ # start with a single forward slash character (/).
580
+ return '/' unless state =~ %r{^/[^/].*}
581
+
582
+ state
583
+ end
584
+
528
585
  def scoped_request_attributes
529
586
  scopes = [:limited]
530
587
  scopes << :medium_extensive if options.scope_of_data == :medium_extensive
@@ -552,8 +609,8 @@ module OmniAuth
552
609
  case options.mode
553
610
  when :test
554
611
  'https://testi.apro.tunnistus.fi/static/metadata/idp-metadata.xml'
555
- else
556
- 'https://tunnistus.suomi.fi/static/metadata/idp-metadata-secondary.xml'
612
+ else # :production
613
+ 'https://tunnistus.suomi.fi/static/metadata/idp-metadata-tunnistautuminen.xml'
557
614
  end
558
615
  end
559
616
 
@@ -572,6 +629,16 @@ module OmniAuth
572
629
  slo_binding: ['urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect']
573
630
  )
574
631
 
632
+ if settings[:idp_slo_response_service_url].nil? && settings[:idp_slo_target_url].nil?
633
+ # Mitigation after ruby-saml update to 1.12.x. This gem has been
634
+ # originally developed relying on the `:idp_slo_target_url` settings
635
+ # which was removed from the newer versions. The SLO requests won't
636
+ # work unless `:idp_slo_response_service_url` is defined in the
637
+ # metadata through the `ResponseLocation` attribute in the
638
+ # `<SingleLogoutService />` node.
639
+ settings[:idp_slo_target_url] ||= settings[:idp_slo_service_url]
640
+ end
641
+
575
642
  # Local certificate and private key to decrypt the responses
576
643
  settings[:certificate] = certificate
577
644
  settings[:private_key] = private_key
@@ -603,6 +670,25 @@ module OmniAuth
603
670
  end
604
671
  end
605
672
  end
673
+
674
+ def locale_for_authn_request
675
+ if options.idp_sso_service_url_locale_params.is_a?(Array)
676
+ options.idp_sso_service_url_locale_params.each do |param|
677
+ next unless request.params.key?(param.to_s)
678
+
679
+ locale = parse_language_value(request.params[param.to_s])
680
+ return locale unless locale.nil?
681
+ end
682
+ end
683
+
684
+ options.idp_sso_service_url_default_locale
685
+ end
686
+
687
+ def parse_language_value(string)
688
+ language = string.sub('_', '-').split('-').first
689
+
690
+ language if language =~ /^(fi|sv|en)$/
691
+ end
606
692
  end
607
693
  end
608
694
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniauth-suomifi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Antti Hukkanen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-15 00:00:00.000000000 Z
11
+ date: 2021-04-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: omniauth-saml
@@ -16,42 +16,56 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.10.1
19
+ version: 1.10.3
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 1.10.1
26
+ version: 1.10.3
27
+ - !ruby/object:Gem::Dependency
28
+ name: ruby-saml
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.12.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.12.1
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - "~>"
32
46
  - !ruby/object:Gem::Version
33
- version: '12.3'
47
+ version: '13.0'
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
- version: '12.3'
54
+ version: '13.0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rspec
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: '3.8'
61
+ version: '3.9'
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: '3.8'
68
+ version: '3.9'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: rack-test
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -106,14 +120,14 @@ dependencies:
106
120
  requirements:
107
121
  - - "~>"
108
122
  - !ruby/object:Gem::Version
109
- version: 0.16.0
123
+ version: 0.19.0
110
124
  type: :development
111
125
  prerelease: false
112
126
  version_requirements: !ruby/object:Gem::Requirement
113
127
  requirements:
114
128
  - - "~>"
115
129
  - !ruby/object:Gem::Version
116
- version: 0.16.0
130
+ version: 0.19.0
117
131
  description: Suomi.fi e-Identification service integration for OmniAuth.
118
132
  email:
119
133
  - antti.hukkanen@mainiotech.fi
@@ -125,6 +139,7 @@ files:
125
139
  - README.md
126
140
  - Rakefile
127
141
  - lib/omniauth-suomifi.rb
142
+ - lib/omniauth-suomifi/ruby_saml_extensions.rb
128
143
  - lib/omniauth-suomifi/test.rb
129
144
  - lib/omniauth-suomifi/test/certificate_generator.rb
130
145
  - lib/omniauth-suomifi/test/templates/encrypted_data_template.xml