omniauth-suomifi 0.1.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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