omniauth-latvija 2.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 +5 -5
- data/README.md +31 -1
- data/lib/omniauth-latvija/version.rb +1 -1
- data/lib/omniauth/strategies/latvija.rb +43 -12
- data/lib/omniauth/strategies/latvija/response.rb +50 -7
- data/lib/omniauth/strategies/latvija/signed_document.rb +13 -3
- metadata +27 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b501b35e3685a3963f0f38ec951a345aae8d534dd3ce323566775eda8bb048bf
|
4
|
+
data.tar.gz: f9e4ef1dff0294bd8ff5a4389be6bb6964a55b7fe5534c2c266d957515e33a4b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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'
|
22
|
+
gem 'omniauth-latvija'
|
23
23
|
```
|
24
24
|
|
25
25
|
## Usage
|
@@ -39,6 +39,36 @@ Rails.application.config.middleware.use OmniAuth::Builder do
|
|
39
39
|
end
|
40
40
|
```
|
41
41
|
|
42
|
+
|
43
|
+
## Auth Hash
|
44
|
+
|
45
|
+
Here's an example hash available in `request.env['omniauth.auth']`
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
{
|
49
|
+
provider: 'latvija',
|
50
|
+
uid: 'PK:12345612345',
|
51
|
+
info: {
|
52
|
+
name: 'JANIS BERZINS',
|
53
|
+
first_name: 'JANIS',
|
54
|
+
last_name: 'BERZINS',
|
55
|
+
private_personal_identifier: '12345612345'
|
56
|
+
},
|
57
|
+
extra: {
|
58
|
+
raw_info: {
|
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'
|
65
|
+
},
|
66
|
+
authentication_method: 'SWEDBANK',
|
67
|
+
legacy_uids: ['JANIS BERZINS, 12345612345']
|
68
|
+
}
|
69
|
+
}
|
70
|
+
```
|
71
|
+
|
42
72
|
## References
|
43
73
|
|
44
74
|
* http://docs.oasis-open.org/wsfed/federation/v1.2/os/ws-federation-1.2-spec-os.html
|
@@ -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,6 +35,23 @@ module OmniAuth::Strategies
|
|
34
35
|
option :certificate, nil
|
35
36
|
option :private_key, nil
|
36
37
|
|
38
|
+
info do
|
39
|
+
{
|
40
|
+
name: full_name,
|
41
|
+
first_name: raw_info['givenname'],
|
42
|
+
last_name: raw_info['surname'],
|
43
|
+
private_personal_identifier: raw_info['privatepersonalidentifier']
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
extra do
|
48
|
+
{
|
49
|
+
raw_info: raw_info,
|
50
|
+
authentication_method: @response.authentication_method,
|
51
|
+
legacy_uids: legacy_uids
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
37
55
|
def request_phase
|
38
56
|
params = {
|
39
57
|
wa: 'wsignin1.0',
|
@@ -64,18 +82,31 @@ module OmniAuth::Strategies
|
|
64
82
|
fail!(:invalid_response, e)
|
65
83
|
end
|
66
84
|
|
67
|
-
def
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
85
|
+
def raw_info
|
86
|
+
@response.attributes
|
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
|
79
110
|
end
|
80
111
|
end
|
81
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
|
-
|
35
|
-
return {} if stmt_elements.nil?
|
47
|
+
return attrs if stmt_elements.nil?
|
36
48
|
|
37
|
-
stmt_elements.
|
38
|
-
|
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
|
-
|
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::
|
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::
|
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(
|
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(
|
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:
|
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:
|
11
|
+
date: 2020-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: omniauth
|
@@ -56,30 +56,30 @@ dependencies:
|
|
56
56
|
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '12.1'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '12.1'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rspec
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '3.7'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '3.7'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: byebug
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -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
|
-
|
159
|
-
|
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: []
|