omniauth-latvija 3.0.0 → 6.1.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
- SHA1:
3
- metadata.gz: 61e8e173bd8c5e154333778d5838d7c8d5d858dd
4
- data.tar.gz: 698200a449f8c9047d87690e2221e36022a926c7
2
+ SHA256:
3
+ metadata.gz: b501b35e3685a3963f0f38ec951a345aae8d534dd3ce323566775eda8bb048bf
4
+ data.tar.gz: f9e4ef1dff0294bd8ff5a4389be6bb6964a55b7fe5534c2c266d957515e33a4b
5
5
  SHA512:
6
- metadata.gz: 2f90ced3cba761f56ce57a2d24ecc684cb69e451008d72fa78d659b5496f995a566f368200ad1c67dd673f6efaefba196b29a29d6146231223d34c8b55fb8a2f
7
- data.tar.gz: a9dafe2e3b298c9593e23918de155ebc8d6150583812744582e85c992a29b69aaa6bd21f91d66ccf3f397c0e19dc289c31eef921624392da281f8096b461911d
6
+ metadata.gz: 03c8dc65d2f8a0290756e5b91d8b01bf9fff8dbbf038685566223e3ebb710fc5080e54c91c2b85fc22a32baa182fff4a00c7158d1f9868fce257ea7d3bc6de45
7
+ data.tar.gz: 13a84d4d7b8caa0dbc8685fa7f18eb322d1319ce22f074aeefaa1cd169593abd4f7f3c0853174d640de0b69716c14a507abc04fa33e04272e130393e49118145
data/README.md CHANGED
@@ -19,7 +19,7 @@ Provides the following authentication types:
19
19
  ## Installation
20
20
 
21
21
  ```ruby
22
- gem 'omniauth-latvija', '~> 2.0'
22
+ gem 'omniauth-latvija'
23
23
  ```
24
24
 
25
25
  ## Usage
@@ -47,7 +47,7 @@ Here's an example hash available in `request.env['omniauth.auth']`
47
47
  ```ruby
48
48
  {
49
49
  provider: 'latvija',
50
- uid: 'JANIS BERZINS, 12345612345',
50
+ uid: 'PK:12345612345',
51
51
  info: {
52
52
  name: 'JANIS BERZINS',
53
53
  first_name: 'JANIS',
@@ -56,12 +56,15 @@ Here's an example hash available in `request.env['omniauth.auth']`
56
56
  },
57
57
  extra: {
58
58
  raw_info: {
59
- name: 'JANIS BERZINS',
60
- first_name: 'JANIS',
61
- last_name: 'BERZINS',
62
- private_personal_identifier: '12345612345'
59
+ givenname: 'JANIS',
60
+ surname: 'BERZINS',
61
+ privatepersonalidentifier: '12345612345',
62
+ historical_privatepersonalidentifier: [],
63
+ not_valid_before: '2019-05-09T07:29:41Z',
64
+ not_valid_on_or_after: '2019-05-09T08:29:41Z'
63
65
  },
64
- authentication_method: 'SWEDBANK'
66
+ authentication_method: 'SWEDBANK',
67
+ legacy_uids: ['JANIS BERZINS, 12345612345']
65
68
  }
66
69
  }
67
70
  ```
@@ -1,5 +1,5 @@
1
1
  module OmniAuth
2
2
  module Latvija
3
- VERSION = '3.0.0'
3
+ VERSION = '6.1.0'
4
4
  end
5
5
  end
@@ -1,6 +1,7 @@
1
1
  require 'time'
2
2
  require 'openssl'
3
3
  require 'digest/sha1'
4
+ require 'digest/sha2'
4
5
  require 'xmlenc'
5
6
  require 'nokogiri'
6
7
  require 'omniauth/strategies/latvija/response'
@@ -34,11 +35,9 @@ module OmniAuth::Strategies
34
35
  option :certificate, nil
35
36
  option :private_key, nil
36
37
 
37
- uid { "#{raw_info['givenname']} #{raw_info['surname']}, #{raw_info["privatepersonalidentifier"]}" }
38
-
39
38
  info do
40
39
  {
41
- name: "#{raw_info['givenname']} #{raw_info['surname']}",
40
+ name: full_name,
42
41
  first_name: raw_info['givenname'],
43
42
  last_name: raw_info['surname'],
44
43
  private_personal_identifier: raw_info['privatepersonalidentifier']
@@ -48,7 +47,8 @@ module OmniAuth::Strategies
48
47
  extra do
49
48
  {
50
49
  raw_info: raw_info,
51
- authentication_method: @response.authentication_method
50
+ authentication_method: @response.authentication_method,
51
+ legacy_uids: legacy_uids
52
52
  }
53
53
  end
54
54
 
@@ -85,5 +85,28 @@ module OmniAuth::Strategies
85
85
  def raw_info
86
86
  @response.attributes
87
87
  end
88
+
89
+ def uid
90
+ @response.name_identifier
91
+ end
92
+
93
+ def full_name
94
+ @full_name ||= "#{raw_info['givenname']} #{raw_info['surname']}"
95
+ end
96
+
97
+ def legacy_uids
98
+ # UIDs that could have been assigned to this identity by previous versions of the gem, or due to peronal identifier change
99
+
100
+ legacy_uids = [
101
+ "#{full_name}, #{raw_info["privatepersonalidentifier"]}" # generated by gem version <= 4.0
102
+ ]
103
+
104
+ raw_info.fetch('historical_privatepersonalidentifier', []).each do |historical_identifier|
105
+ legacy_uids << "#{full_name}, #{historical_identifier}" # generated by gem version <= 4.0
106
+ legacy_uids << "PK:#{historical_identifier}" # due to personal identifier change
107
+ end
108
+
109
+ legacy_uids
110
+ end
88
111
  end
89
112
  end
@@ -13,7 +13,7 @@ module OmniAuth::Strategies
13
13
  end
14
14
 
15
15
  def validate!
16
- @document.validate!(fingerprint)
16
+ @document.validate!(fingerprint) && validate_conditions!
17
17
  end
18
18
 
19
19
  def xml
@@ -26,19 +26,42 @@ module OmniAuth::Strategies
26
26
  end
27
27
  end
28
28
 
29
+ def name_identifier
30
+ @name_identifier ||= begin
31
+ xml.xpath('//saml:AuthenticationStatement/saml:Subject/saml:NameIdentifier', saml: ASSERTION).text()
32
+ end
33
+ end
34
+
29
35
  # A hash of all the attributes with the response.
30
36
  # Assuming there is only one value for each key
31
37
  def attributes
32
38
  @attributes ||= begin
39
+ attrs = {
40
+ 'not_valid_before' => not_valid_before,
41
+ 'not_valid_on_or_after' => not_valid_on_or_after,
42
+ 'historical_privatepersonalidentifier' => []
43
+ }
44
+
45
+ stmt_elements = xml.xpath('//saml:Attribute', saml: ASSERTION)
33
46
 
34
- stmt_elements = xml.xpath('//a:Attribute', a: ASSERTION)
35
- return {} if stmt_elements.nil?
47
+ return attrs if stmt_elements.nil?
36
48
 
37
- stmt_elements.each_with_object({}) do |element, result|
38
- name = element.attribute('AttributeName').value
49
+ identifiers = stmt_elements.xpath("//saml:Attribute[@AttributeName='privatepersonalidentifier']", saml: ASSERTION)
50
+
51
+ stmt_elements.each_with_object(attrs) do |element, result|
52
+ name = element.attribute('AttributeName').value
39
53
  value = element.text
40
54
 
41
- result[name] = value
55
+ case name
56
+ when 'privatepersonalidentifier' # person can change their identifier, service will return all the versions
57
+ if identifiers.length == 1 || element.attribute('OriginalIssuer') # this is the primary identifier, as returned by third party auth service
58
+ result[name] = value
59
+ else
60
+ result['historical_privatepersonalidentifier'] << value
61
+ end
62
+ else
63
+ result[name] = value
64
+ end
42
65
  end
43
66
  end
44
67
  end
@@ -47,7 +70,27 @@ module OmniAuth::Strategies
47
70
 
48
71
  def fingerprint
49
72
  cert = OpenSSL::X509::Certificate.new(options[:certificate])
50
- Digest::SHA1.hexdigest(cert.to_der).upcase.scan(/../).join(':')
73
+ Digest::SHA256.hexdigest(cert.to_der).upcase.scan(/../).join(':')
74
+ end
75
+
76
+ def conditions_tag
77
+ @conditions_tag ||= xml.xpath('//saml:Conditions', saml: ASSERTION)
78
+ end
79
+
80
+ def not_valid_before
81
+ @not_valid_before ||= conditions_tag.attribute('NotBefore').value
82
+ end
83
+
84
+ def not_valid_on_or_after
85
+ @not_valid_on_or_after ||= conditions_tag.attribute('NotOnOrAfter').value
86
+ end
87
+
88
+ def validate_conditions!
89
+ if not_valid_on_or_after.present? && Time.current < Time.parse(not_valid_on_or_after)
90
+ true
91
+ else
92
+ raise ValidationError, 'Current time is on or after NotOnOrAfter condition'
93
+ end
51
94
  end
52
95
  end
53
96
  end
@@ -64,8 +64,18 @@ module OmniAuth::Strategies
64
64
  end
65
65
  end
66
66
 
67
+ def digest_method_class(reference)
68
+ value = reference.xpath('.//xmlns:DigestMethod', xmlns: DSIG).attribute('Algorithm').value
69
+ value == "#{DSIG}sha1" ? Digest::SHA1 : Digest::SHA256
70
+ end
71
+
72
+ def signature_method_class(sig_element)
73
+ value = sig_element.xpath('.//xmlns:SignatureMethod', xmlns: DSIG).attribute('Algorithm').value
74
+ value == "#{DSIG}rsa-sha1" ? OpenSSL::Digest::SHA1 : OpenSSL::Digest::SHA256
75
+ end
76
+
67
77
  def validate_fingerprint!(idp_cert_fingerprint)
68
- fingerprint = Digest::SHA1.hexdigest(certificate.to_der)
78
+ fingerprint = Digest::SHA256.hexdigest(certificate.to_der)
69
79
  if fingerprint != idp_cert_fingerprint.gsub(/[^a-zA-Z0-9]/, '').downcase
70
80
  raise ValidationError, 'Fingerprint mismatch'
71
81
  end
@@ -80,7 +90,7 @@ module OmniAuth::Strategies
80
90
  hashed_element = response_without_signature.
81
91
  at_xpath("//*[@AssertionID='#{uri[1, uri.size]}']").
82
92
  canonicalize(CANON_MODE)
83
- hash = Base64.encode64(Digest::SHA1.digest(hashed_element)).chomp
93
+ hash = Base64.encode64(digest_method_class(ref).digest(hashed_element)).chomp
84
94
  digest_value = ref.xpath('.//xmlns:DigestValue', xmlns: DSIG).text
85
95
 
86
96
  raise ValidationError, 'Digest mismatch' if hash != digest_value
@@ -94,7 +104,7 @@ module OmniAuth::Strategies
94
104
  base64_signature = sig_element.xpath('.//xmlns:SignatureValue', xmlns: DSIG).text
95
105
  signature = Base64.decode64(base64_signature)
96
106
 
97
- unless certificate.public_key.verify(OpenSSL::Digest::SHA1.new, signature, signed_info_element)
107
+ unless certificate.public_key.verify(signature_method_class(sig_element).new, signature, signed_info_element)
98
108
  raise ValidationError, 'Key validation error'
99
109
  end
100
110
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniauth-latvija
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 6.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Edgars Beigarts
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-12 00:00:00.000000000 Z
11
+ date: 2020-09-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: omniauth
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: timecop
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
125
139
  description: Latvija.lv authentication strategy for OmniAuth
126
140
  email:
127
141
  - edgars.beigarts@makit.lv
@@ -137,10 +151,10 @@ files:
137
151
  - lib/omniauth/strategies/latvija/decryptor.rb
138
152
  - lib/omniauth/strategies/latvija/response.rb
139
153
  - lib/omniauth/strategies/latvija/signed_document.rb
140
- homepage:
154
+ homepage:
141
155
  licenses: []
142
156
  metadata: {}
143
- post_install_message:
157
+ post_install_message:
144
158
  rdoc_options: []
145
159
  require_paths:
146
160
  - lib
@@ -155,9 +169,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
155
169
  - !ruby/object:Gem::Version
156
170
  version: '0'
157
171
  requirements: []
158
- rubyforge_project:
159
- rubygems_version: 2.6.11
160
- signing_key:
172
+ rubygems_version: 3.0.6
173
+ signing_key:
161
174
  specification_version: 4
162
175
  summary: Latvija.lv authentication strategy for OmniAuth
163
176
  test_files: []