omniauth-citadele 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.travis.yml +7 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +71 -0
- data/Rakefile +1 -0
- data/lib/omniauth/citadele/version.rb +5 -0
- data/lib/omniauth/citadele.rb +2 -0
- data/lib/omniauth/locales/omniauth.en.yml +5 -0
- data/lib/omniauth/locales/omniauth.lv.yml +5 -0
- data/lib/omniauth/strategies/citadele.rb +185 -0
- data/lib/omniauth-citadele.rb +4 -0
- data/omniauth-citadele.gemspec +33 -0
- data/spec/certs/request.crt +20 -0
- data/spec/certs/request.key +27 -0
- data/spec/certs/response.crt +17 -0
- data/spec/certs/response.key +28 -0
- data/spec/omniauth/strategies/citadele_spec.rb +194 -0
- data/spec/spec_helper.rb +19 -0
- metadata +180 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c50abe4891bbc8de59fda34ef6363d6512781131ba01f190df835659f1ba941f
|
4
|
+
data.tar.gz: eced906c16eacd3a47d348e8bf36924b85b319b1be0e6be79333e4c6cb635cc1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8e082a3f0960abc213a177f35ce487841573540f9551262faea4d7b72b8e6cfb05a05977ee91dd1e00a40a25f04a93df56646ab897dd46fca0ebc7018d7b7982
|
7
|
+
data.tar.gz: d3bb5d584cffe000098228e7cca7efcbe94b785b85e1e8794d9645235a70c916c1e45f8b3a1019438c8dc22ae98661ea08d88025688c0dd4e3bcdef78d44863a
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2017 MAK IT, Jānis Kiršteins
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# Omniauth Citadele
|
2
|
+
|
3
|
+
Omniauth strategy for using Citadele as an authentication service provider.
|
4
|
+
|
5
|
+
[![Build Status](https://travis-ci.org/mak-it/omniauth-citadele.svg?branch=master)](https://travis-ci.org/mak-it/omniauth-citadele)
|
6
|
+
|
7
|
+
Supported Ruby versions: 2.3+
|
8
|
+
|
9
|
+
## Related projects
|
10
|
+
|
11
|
+
- [omniauth-dnb](https://github.com/mak-it/omniauth-dnb) - strategy for authenticating with DNB
|
12
|
+
- [omniauth-nordea](https://github.com/mak-it/omniauth-nordea) - strategy for authenticating with Nordea
|
13
|
+
- [omniauth-seb-elink](https://github.com/mak-it/omniauth-seb-elink) - strategy for authenticating with SEB
|
14
|
+
- [omniauth-swedbank](https://github.com/mak-it/omniauth-swedbank) - strategy for authenticating with Swedbank
|
15
|
+
|
16
|
+
|
17
|
+
## Installation
|
18
|
+
|
19
|
+
Add this line to your application's Gemfile:
|
20
|
+
|
21
|
+
gem 'omniauth-citadele'
|
22
|
+
|
23
|
+
And then execute:
|
24
|
+
|
25
|
+
$ bundle
|
26
|
+
|
27
|
+
Or install it yourself as:
|
28
|
+
|
29
|
+
$ gem install omniauth-citadele
|
30
|
+
|
31
|
+
## Usage
|
32
|
+
|
33
|
+
Here's a quick example, adding the middleware to a Rails app
|
34
|
+
in `config/initializers/omniauth.rb`:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
Rails.application.config.middleware.use OmniAuth::Builder do
|
38
|
+
provider :citadele,
|
39
|
+
File.read('path/to/private.key'),
|
40
|
+
File.read('path/to/private.crt'),
|
41
|
+
File.read('path/to/bank.crt'),
|
42
|
+
ENV['CITADELE_FROM'], site: ENV['CITADELE_SITE']
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
## Auth Hash
|
47
|
+
|
48
|
+
Here's an example Auth Hash available in `request.env['omniauth.auth']`:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
{
|
52
|
+
provider: 'citadele',
|
53
|
+
uid: '000000-00000',
|
54
|
+
info: {
|
55
|
+
full_name: 'TestDP AŠĶŪO'
|
56
|
+
},
|
57
|
+
extra: {
|
58
|
+
raw_info: {
|
59
|
+
xmldata: '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<FIDAVISTA xmlns=\"http://ivis.eps.gov.lv/XMLSchemas/100017/fidavista/v1-2\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://ivis.eps.gov.lv/XMLSchemas/100017/fidavista/v1-2 http://ivis.eps.gov.lv/XMLSchemas/100017/fidavista/v1-2/fidavista.xsd\"><Header><Timestamp>20170502142652000</Timestamp><From>10000</From><Extension><Amai xmlns=\"http://online.citadele.lv/XMLSchemas/amai/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://online.citadele.lv/XMLSchemas/amai/ http://online.citadele.lv/XMLSchemas/amai/amai.xsd\"><Request>AUTHRESP</Request><RequestUID>258e4526-8129-468f-832a-493807346f96</RequestUID><Version>5.0</Version><Language>LV</Language><PersonCode>00000000000</PersonCode><Person>TestDP AŠĶŪO</Person><Code>100</Code><SignatureData><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\"/><SignatureMethod Algorithm=\"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\"/><Reference URI=\"\"><Transforms><Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#sha256\"/><DigestValue>E3FoLc7qCoWppsPn5BPdY5GJg6CGj3BEOfoaKLsrbqI=</DigestValue></Reference></SignedInfo><SignatureValue>...</SignatureValue><KeyInfo><X509Data><X509SubjectName>...</X509SubjectName><X509Certificate>...</X509Certificate></X509Data></KeyInfo></Signature></SignatureData></Amai></Extension></Header></FIDAVISTA>'
|
60
|
+
}
|
61
|
+
}
|
62
|
+
}
|
63
|
+
```
|
64
|
+
|
65
|
+
## Contributing
|
66
|
+
|
67
|
+
1. Fork it
|
68
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
69
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
70
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
71
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
@@ -0,0 +1,185 @@
|
|
1
|
+
require 'omniauth'
|
2
|
+
require 'base64'
|
3
|
+
require 'xmldsig'
|
4
|
+
|
5
|
+
module OmniAuth
|
6
|
+
module Strategies
|
7
|
+
class Citadele
|
8
|
+
include OmniAuth::Strategy
|
9
|
+
|
10
|
+
PRODUCTION_ENDPOINT = 'https://online.citadele.lv/amai/start.htm'
|
11
|
+
TEST_ENDPOINT = 'https://astra.citadele.lv/amai/start.htm'
|
12
|
+
|
13
|
+
AUTH_REQUEST = 'AUTHREQ'
|
14
|
+
AUTH_VERSION = '5.0'
|
15
|
+
|
16
|
+
args [:private_key, :private_crt, :public_crt, :from]
|
17
|
+
|
18
|
+
option :private_key, nil
|
19
|
+
option :private_crt, nil
|
20
|
+
option :public_crt, nil
|
21
|
+
option :from, nil
|
22
|
+
|
23
|
+
option :name, 'citadele'
|
24
|
+
option :site, PRODUCTION_ENDPOINT
|
25
|
+
|
26
|
+
def timestamp
|
27
|
+
@timestamp ||= Time.now.strftime("%Y%m%d%H%M%S%3N")
|
28
|
+
end
|
29
|
+
|
30
|
+
def request_uid
|
31
|
+
@request_uid ||= SecureRandom.uuid
|
32
|
+
end
|
33
|
+
|
34
|
+
def return_signed_request_xml(request_data, priv_key)
|
35
|
+
unsigned_xml = <<~XML
|
36
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
37
|
+
<FIDAVISTA xmlns="http://ivis.eps.gov.lv/XMLSchemas/100017/fidavista/v1-1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://ivis.eps.gov.lv/XMLSchemas/100017/fidavista/v1-1 http://ivis.eps.gov.lv/XMLSchemas/100017/fidavista/v1-1/fidavista.xsd">
|
38
|
+
<Header>
|
39
|
+
<Timestamp>#{request_data[:timestamp]}</Timestamp>
|
40
|
+
<From>#{request_data[:from]}</From>
|
41
|
+
<Extension>
|
42
|
+
<Amai xmlns="http://online.citadele.lv/XMLSchemas/amai/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://online.citadele.lv/XMLSchemas/amai/ http://online.citadele.lv/XMLSchemas/amai/amai.xsd">
|
43
|
+
<Request>#{request_data[:request]}</Request>
|
44
|
+
<RequestUID>#{request_data[:request_uid]}</RequestUID>
|
45
|
+
<Version>#{request_data[:version]}</Version>
|
46
|
+
<Language>#{request_data[:language]}</Language>
|
47
|
+
<ReturnURL>#{request_data[:return_url]}</ReturnURL>
|
48
|
+
<SignatureData>
|
49
|
+
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
|
50
|
+
<SignedInfo>
|
51
|
+
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
|
52
|
+
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
|
53
|
+
<Reference URI="">
|
54
|
+
<Transforms>
|
55
|
+
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
56
|
+
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
|
57
|
+
</Transforms>
|
58
|
+
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
|
59
|
+
<DigestValue></DigestValue>
|
60
|
+
</Reference>
|
61
|
+
</SignedInfo>
|
62
|
+
<SignatureValue></SignatureValue>
|
63
|
+
<KeyInfo>
|
64
|
+
<X509Data>
|
65
|
+
<X509SubjectName>#{request_data[:x509_subject_name]}</X509SubjectName>
|
66
|
+
<X509Certificate>#{request_data[:x509_certificate]}</X509Certificate>
|
67
|
+
</X509Data>
|
68
|
+
</KeyInfo>
|
69
|
+
</Signature>
|
70
|
+
</SignatureData>
|
71
|
+
</Amai>
|
72
|
+
</Extension>
|
73
|
+
</Header>
|
74
|
+
</FIDAVISTA>
|
75
|
+
XML
|
76
|
+
unsigned_xml.gsub!('\n', '')
|
77
|
+
unsigned_document = Xmldsig::SignedDocument.new(unsigned_xml)
|
78
|
+
unsigned_document.sign(priv_key)
|
79
|
+
end
|
80
|
+
|
81
|
+
def parse_response(xml)
|
82
|
+
doc = Nokogiri::XML(xml) do |config|
|
83
|
+
config.strict.nonet
|
84
|
+
end
|
85
|
+
doc.remove_namespaces!
|
86
|
+
{
|
87
|
+
timestamp: doc.xpath("//Timestamp").text,
|
88
|
+
from: doc.xpath("//From").text,
|
89
|
+
request: doc.xpath("//Request").text,
|
90
|
+
request_uid: doc.xpath("//RequestUID").text,
|
91
|
+
version: doc.xpath("//Version").text,
|
92
|
+
language: doc.xpath("//Language").text,
|
93
|
+
person_code: doc.xpath("//PersonCode").text,
|
94
|
+
person: doc.xpath("//Person").text,
|
95
|
+
code: doc.xpath("//Code").text,
|
96
|
+
message: doc.xpath("//Message").text
|
97
|
+
}
|
98
|
+
end
|
99
|
+
|
100
|
+
def response_data
|
101
|
+
@response_data ||= parse_response(request.params['xmldata'])
|
102
|
+
end
|
103
|
+
|
104
|
+
uid do
|
105
|
+
response_data[:person_code].dup.insert(6, "-")
|
106
|
+
end
|
107
|
+
|
108
|
+
info do
|
109
|
+
{
|
110
|
+
full_name: response_data[:person]
|
111
|
+
}
|
112
|
+
end
|
113
|
+
|
114
|
+
extra do
|
115
|
+
{ raw_info: request.params }
|
116
|
+
end
|
117
|
+
|
118
|
+
def callback_phase
|
119
|
+
begin
|
120
|
+
pub_crt = OpenSSL::X509::Certificate.new(options.public_crt).public_key
|
121
|
+
rescue => e
|
122
|
+
return fail!(:public_crt_load_err, e)
|
123
|
+
end
|
124
|
+
|
125
|
+
# Code = 100 -> success, 200, 300, 400 -> failure
|
126
|
+
case response_data[:code]
|
127
|
+
when '200'
|
128
|
+
return fail!(:authentication_cancelled_error)
|
129
|
+
when '300'
|
130
|
+
return fail!(response_data[:message])
|
131
|
+
end
|
132
|
+
|
133
|
+
if response_data[:request] != 'AUTHRESP'
|
134
|
+
return fail!(:unsupported_response_request)
|
135
|
+
end
|
136
|
+
|
137
|
+
xmldsig = Xmldsig::SignedDocument.new(request.params['xmldata'])
|
138
|
+
if !xmldsig.validate(pub_crt)
|
139
|
+
return fail!(:invalid_response_signature_err)
|
140
|
+
end
|
141
|
+
|
142
|
+
super
|
143
|
+
end
|
144
|
+
|
145
|
+
def request_phase
|
146
|
+
begin
|
147
|
+
priv_key = OpenSSL::PKey::RSA.new(options.private_key)
|
148
|
+
rescue => e
|
149
|
+
return fail!(:private_key_load_err, e)
|
150
|
+
end
|
151
|
+
|
152
|
+
begin
|
153
|
+
private_crt = OpenSSL::X509::Certificate.new(options.private_crt)
|
154
|
+
rescue => e
|
155
|
+
return fail!(:private_crt_load_err, e)
|
156
|
+
end
|
157
|
+
|
158
|
+
x509_subject_name = private_crt.subject.to_s
|
159
|
+
x509_certificate = private_crt.to_s.gsub(/[-]{5}(BEGIN|END).*?[-]{5}/, '').gsub('\n', '')
|
160
|
+
|
161
|
+
request_data = {
|
162
|
+
timestamp: timestamp, # '20170905175959000'
|
163
|
+
from: options.from,
|
164
|
+
request: AUTH_REQUEST,
|
165
|
+
request_uid: request_uid, # '7387bf5b-fa27-4fdd-add6-a6bfb2599f77'
|
166
|
+
version: AUTH_VERSION,
|
167
|
+
language: 'LV',
|
168
|
+
return_url: callback_url,
|
169
|
+
x509_subject_name: x509_subject_name,
|
170
|
+
x509_certificate: x509_certificate
|
171
|
+
}
|
172
|
+
field_value = return_signed_request_xml(request_data, priv_key)
|
173
|
+
field_value.gsub!('"', '"')
|
174
|
+
|
175
|
+
form = OmniAuth::Form.new(title: I18n.t('omniauth.citadele.please_wait'), url: options.site)
|
176
|
+
form.html "<input id=\"xmldata\" name=\"xmldata\" type=\"hidden\" value=\"#{field_value}\" />"
|
177
|
+
form.button I18n.t('omniauth.citadele.click_here_if_not_redirected')
|
178
|
+
|
179
|
+
form.instance_variable_set('@html',
|
180
|
+
form.to_html.gsub('</form>', '</form><script type="text/javascript">document.forms[0].submit();</script>'))
|
181
|
+
form.to_response
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'omniauth/citadele/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'omniauth-citadele'
|
8
|
+
spec.version = Omniauth::Citadele::VERSION
|
9
|
+
spec.authors = ['MAK IT']
|
10
|
+
spec.email = ['admin@makit.lv' ]
|
11
|
+
spec.description = %q{OmniAuth strategy for Citadele Banklink}
|
12
|
+
spec.summary = %q{OmniAuth strategy for Citadele Banklink}
|
13
|
+
spec.homepage = 'https://github.com/mak-it/omniauth-citadele'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.required_ruby_version = '>= 2.3.0'
|
22
|
+
|
23
|
+
spec.add_runtime_dependency 'omniauth', '~> 1.0'
|
24
|
+
spec.add_runtime_dependency 'i18n'
|
25
|
+
|
26
|
+
spec.add_development_dependency 'rack-test'
|
27
|
+
spec.add_development_dependency 'rspec'
|
28
|
+
spec.add_development_dependency 'bundler'
|
29
|
+
spec.add_development_dependency 'rake'
|
30
|
+
|
31
|
+
spec.add_dependency 'xmldsig'
|
32
|
+
spec.add_dependency 'nokogiri'
|
33
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIDQjCCAiqgAwIBAgIJAJ5auG0KG8WMMA0GCSqGSIb3DQEBCwUAMB8xEDAOBgNV
|
3
|
+
BAMTB0ROQlRFU1QxCzAJBgNVBAYTAkxWMB4XDTE3MDQwMzEwMDQzM1oXDTM3MDMy
|
4
|
+
OTEwMDQzM1owHzEQMA4GA1UEAxMHRE5CVEVTVDELMAkGA1UEBhMCTFYwggEiMA0G
|
5
|
+
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMRYJ0rKoiMbUDxiiXT0xaf8yOMu59
|
6
|
+
m5DFe1A5I/1X9IZCaVEMXcd7ZJoovupOU340n2Kq5ez8zeS3mLY3WK+78MFIysc9
|
7
|
+
nM7/MrTB2KYVaEnpzgN0c9MkiUq8G7LTtcLCbK/eEYmXf4vQIAXwHr6JnP7+sPd7
|
8
|
+
XZhgTNbeugxyqL9Nj1zzLUBOH2v1/PzFH2KnSe/srCSb/PQs+YPpNvx8nWu4FY9E
|
9
|
+
S09idp59hKnWS1M5SRWKYrc3YhLYDinV3Tjwe0uSGJIC4DNijP/QgkZ6TSIiSOua
|
10
|
+
TIQofTkFxT9r32SCTjm8oLzK6w8dvPmx2e9Q9urfD99jmiLh7N7hII7TAgMBAAGj
|
11
|
+
gYAwfjAdBgNVHQ4EFgQU3vSU9SHIDGRYCE/bfS9Y27kPKuowTwYDVR0jBEgwRoAU
|
12
|
+
3vSU9SHIDGRYCE/bfS9Y27kPKuqhI6QhMB8xEDAOBgNVBAMTB0ROQlRFU1QxCzAJ
|
13
|
+
BgNVBAYTAkxWggkAnlq4bQobxYwwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsF
|
14
|
+
AAOCAQEApoS7dHifbvMluHL9ypLgJ+SVr/RaAYy8WYE9lfK7CBX0cLzn4pxZm69W
|
15
|
+
pWqp3qB4FxEQS2PNt6TAwexNUeWkKUrMxdnSRRw5gnMM0ELNpWd/xWvu3MHZfR0w
|
16
|
+
hfyQyweipttgcaCOMQoRH/DS2HeS3GcRk5ljHzRhavqqgnLY8WZ/YGtnBqFlanMz
|
17
|
+
F2dfWQqld/73S0v9ygwKaC+SwVHIQ8XwgZkwxM3MxyXOuE4sx5p+KaQ7n/aRRseb
|
18
|
+
EZhMUzYXd0+ekN8cNjefBmCJlkV+VxeZwo7s97A4qYMku6Ac3Zji8SUi+Qz9RD0q
|
19
|
+
E8Sjrn8obEY8rDfkGoPZf+ygH4MkOA==
|
20
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,27 @@
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
2
|
+
MIIEpQIBAAKCAQEAzEWCdKyqIjG1A8Yol09MWn/MjjLufZuQxXtQOSP9V/SGQmlR
|
3
|
+
DF3He2SaKL7qTlN+NJ9iquXs/M3kt5i2N1ivu/DBSMrHPZzO/zK0wdimFWhJ6c4D
|
4
|
+
dHPTJIlKvBuy07XCwmyv3hGJl3+L0CAF8B6+iZz+/rD3e12YYEzW3roMcqi/TY9c
|
5
|
+
8y1ATh9r9fz8xR9ip0nv7Kwkm/z0LPmD6Tb8fJ1ruBWPREtPYnaefYSp1ktTOUkV
|
6
|
+
imK3N2IS2A4p1d048HtLkhiSAuAzYoz/0IJGek0iIkjrmkyEKH05BcU/a99kgk45
|
7
|
+
vKC8yusPHbz5sdnvUPbq3w/fY5oi4eze4SCO0wIDAQABAoIBAQCUmpi+QoJ+38R9
|
8
|
+
G2KaOREl4UUxybGgZVTbpcsF1r3Oh9BIbg+NPIgLp3NS4xjXpHvy0mTYSO6wNyUF
|
9
|
+
v64H85fc1Nf4GbT6iKI6G2xOfUrN1hG3aq0uwbhAIzTgRhJBXEB0atdCaWW8dgiD
|
10
|
+
f1hyiBs7R6BmLt3LvJpGrH/Ahn7ZxcVSwTNb485fl4bAmR1uc3QRi1RUVA/d6BuQ
|
11
|
+
Swm9ahBzgCl66uXDTCwjjOv+JTU1Bn8iMZws4e0A4sfbT/Fs5eoSLEnMQUWjIyQ/
|
12
|
+
/+3YTyohi97sbliA3VNbyHqPOyvgQSrNppdxl75KgBhDXVLBvijBokQWJmPGNEDr
|
13
|
+
efXquhABAoGBAPqCLttuFDFU0pwcZd2JKXCOiylSeywMvozC14c3qG+fPVOTkRWT
|
14
|
+
tGBoe83THAh1d1thwXQCjwU+voTP3HA9gd58SVjElFneAKKjhLg/4QcdlJ8JFdRw
|
15
|
+
itV4pqSzvxkzH+OTvZWa+yxmg2BTP1dDa7RjlNf2LnmhGvs5gW98QlbTAoGBANC/
|
16
|
+
2e4vyXRqwIREyXtopsJns3lHSj50PEkurcaLo4NsFOwBVbAC+qBC+NCS8s0KnhGO
|
17
|
+
1YCaNMEXuVAyXfnlNUtzfWJce8YSqqhyP36d5zQzXBiAj3IVSKHHMN12/oYqlqsl
|
18
|
+
ya+SoUkCXKOZOmcb8f/iwF5ZM6W6dr2ECAyxtegBAoGAUa5LCv9clC09MuvLhy2n
|
19
|
+
Fm1UENg1E0rggtMxJYTPZf39KBgwsWFk6h6HZ7hTJqrujRxV0LbY3XP0+ScxkGNt
|
20
|
+
yhaqb8hBOwA5Is7AgrdJb2GEyUpUFN3RVwOtCn0VbWkPF8xff7118qdGZQ0f1RtF
|
21
|
+
rh7eNICv7LbMLmg0vR4+H0MCgYEAjvCP/fVi8QCYSvn/LS3/4ma4EneqcxGMpl/8
|
22
|
+
RlQf50H/IYvYbOndTBgP4GJ/N7/pdQRlVeZB8WaZUjzq9M7qq3utg8joSD1H9ogk
|
23
|
+
ykK9qpTwnyaJEwlX7s9CuqNcrepDuXXqoPq6zg9799pYj3onP5y5NOHH59fCrwrV
|
24
|
+
qDuX4AECgYEAt/mpBWRilnnnYYoSyiBW9N4MS3t6N88rfR3a0sftfhXEEFBwIIjX
|
25
|
+
gB4xAcbZ/EhghKrnKXh3tTbWkf/46Kscl+BvPLRAVUykAEtRlG/Kt/jvyJtKjfzy
|
26
|
+
9iWKuayWsllLm9q0Os9E8z4g4n8VbtLnCbyN07P+ghRZTB17tk8qJ2Y=
|
27
|
+
-----END RSA PRIVATE KEY-----
|
@@ -0,0 +1,17 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIICqDCCAZACCQDrOEbPOMyFeDANBgkqhkiG9w0BAQsFADAWMRQwEgYDVQQDDAtl
|
3
|
+
eGFtcGxlLm9yZzAeFw0xOTAyMTQwNzQ2MDVaFw0zOTAyMDkwNzQ2MDVaMBYxFDAS
|
4
|
+
BgNVBAMMC2V4YW1wbGUub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
|
5
|
+
AQEAq4dDTvosvN7VKd+qxRV14Ah+Nvyw+K97jXpxeAuMeJzKTAbjqag5nyR0BbOQ
|
6
|
+
1htWbSdLeFkHVDfw5WVSYZh0GUldycyHRZeOaBdnVLWN0eM6661U4NDTmgB+BE4H
|
7
|
+
lwOlt7zFLVCIp7mlOY4ACN6ddBUk/noFte8ynbEG5DVtNT8C7aClqkEFTPLrwlF2
|
8
|
+
2aNqn+orxj23x7meJrvTp7v7nGFfpGkxsfnSBRiokkZwSgqm6xrym/tQxW9ILgyW
|
9
|
+
r+3GXh65DLcJG7vWH5KFdC/cx/sO0axe6tHcgnf0V7zZ8F9IgFWND7KvlxORYDYJ
|
10
|
+
0vlarOSeIPY/DcslskHErGlymQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAhxjtR
|
11
|
+
11H1aUJcZYy2uOMvQ7W0pDzlsv6G/Bb+x8u+lOoirrEHCzqkyA0xD1mjRhnAG3DG
|
12
|
+
4sIFlZvCIDP/fmQzDpY427KXD+TiQ2ry500ZkjYC0ivwdhmoZnGcL92V5ZcYTTJ3
|
13
|
+
Rju2pGFzV+O5vqin4jsTM8LOnrxZkSlGEFv6nDte2OgVZtXWWS1xuBHS7I7CCxlX
|
14
|
+
CgY2XtP7y7403s4Uv89xxAfVk1cSdt0Qp6S2i+ie5YJYWWRlvik9VJ8uacVz8XmV
|
15
|
+
rjqpUCx/9XWVATNw01gwe+gTj2vjU0505I6NmShEkO3EaWIZQUKXncSldrMljXTl
|
16
|
+
BOZS0kfU+R0dnYFG
|
17
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,28 @@
|
|
1
|
+
-----BEGIN PRIVATE KEY-----
|
2
|
+
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCrh0NO+iy83tUp
|
3
|
+
36rFFXXgCH42/LD4r3uNenF4C4x4nMpMBuOpqDmfJHQFs5DWG1ZtJ0t4WQdUN/Dl
|
4
|
+
ZVJhmHQZSV3JzIdFl45oF2dUtY3R4zrrrVTg0NOaAH4ETgeXA6W3vMUtUIinuaU5
|
5
|
+
jgAI3p10FST+egW17zKdsQbkNW01PwLtoKWqQQVM8uvCUXbZo2qf6ivGPbfHuZ4m
|
6
|
+
u9Onu/ucYV+kaTGx+dIFGKiSRnBKCqbrGvKb+1DFb0guDJav7cZeHrkMtwkbu9Yf
|
7
|
+
koV0L9zH+w7RrF7q0dyCd/RXvNnwX0iAVY0Psq+XE5FgNgnS+Vqs5J4g9j8NyyWy
|
8
|
+
QcSsaXKZAgMBAAECggEAVOF/tmJopyIiHDGZwSOIjE/HnZBYRwgXvQA9jGkynzD/
|
9
|
+
jrXODVO5B/6zB2s/niQzFZrfZvOvg8aXB/2m0bLuqOC8b7MtsYt5JhuGv82EG7w1
|
10
|
+
mRDSMtpEDC54LcsrSFi+tfjNHkp/BXkBwUR60ejPw/T+tItPriNrScujnGSv4Su4
|
11
|
+
4PZiGylX0cGBnN/Pdf30ILp0k9brpyZhFw9LZJouX6e6J4lNRDTxxq60pU8HRdiA
|
12
|
+
vUiK7ilexGTfzQvcB1OoQmr3dy6Fqjwhb6sRrltpeb6xx130wDV2DGrnq+nl3/2J
|
13
|
+
+2h4b3kdHQJuWeLF82WUN+lM6Upowk0Vr5CfQsBxjQKBgQDXGbzu5ruWufT+ilRj
|
14
|
+
pN5NXqddZkpYxt0g6vHI69pOz9qnEdJlPLzHqVzJ/GqnzTVcikMOoEMhZ1TJNbXa
|
15
|
+
g69kok2zo3nkIbZ6a2qtmBO4u+9QE3Dz0Uef5D4UiLArc16XT3XRlTZMFTDlbr92
|
16
|
+
djD7eB7WTqH1xbJBNn7JEUU7XwKBgQDMJJmvuec2C/fITgpJUaJHTJd4q7fbVAtu
|
17
|
+
V7TF1K3QTlZJb3Vk55WrvV30q/qsp87iV1xcUyXEA+/SObF68B63MKgwI29jkUwM
|
18
|
+
efeiPBKbR6ZUsOTU5cF5iNmwZJM3HO7ufFuPz6F18Cns0aKHaPlpFc0ztzZAGoMw
|
19
|
+
XkCs4R8NBwKBgEzpzR73rhgFQk9KE0bWCw9LSzkgfHEmGqfMmswnWZZYyGx4+Oxu
|
20
|
+
PWp/ashm05RQ0kXWwoeWUqq9EhoodHBAKhUn2/Th/ZHPZDp98lVETbj+qmHNsdPc
|
21
|
+
/2ly6afaAHRo+mfMZ+qbGiE2apd/dELdnEIu/4fN8ie5mzWqUMeAv2qtAoGBAJuf
|
22
|
+
902AcmPAYefgnnTgd87U89A5UFMy0fgPgq8iAFOBtMQM5TjEV1Rya3L/vHzs/ImO
|
23
|
+
QcncVTkGK0hfVQ68iR3sSPtRuDP2azxDquWR2DlqOMHtjLVEZecpzZJsSdJFC1zh
|
24
|
+
jsemaJdJPBzef4GtJB3ZUfLv47qgu4we/j0M7af3AoGAMscCLCdTsIDpmY5QDCrO
|
25
|
+
eLE+wME6tn/oMJTGHwldf5WEZhVLl/OfsZwrRwtw/8O5okhcXvI2TJVKqg/UU02I
|
26
|
+
IIhz8MH/7p4wN6470of0aBxSloXxV/z2lEAHBYF2jS3fYKbig2JvGKkiR4wGQZMU
|
27
|
+
9NwpfwIXMFncwTcJZzKFoxs=
|
28
|
+
-----END PRIVATE KEY-----
|
@@ -0,0 +1,194 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe OmniAuth::Strategies::Citadele do
|
4
|
+
PRIVATE_KEY = File.read(File.join(RSpec.configuration.cert_folder, 'request.key'))
|
5
|
+
PRIVATE_CRT = File.read(File.join(RSpec.configuration.cert_folder, 'request.crt'))
|
6
|
+
PUBLIC_CRT = File.read(File.join(RSpec.configuration.cert_folder, 'response.crt'))
|
7
|
+
|
8
|
+
let(:app){ Rack::Builder.new do |b|
|
9
|
+
b.use Rack::Session::Cookie, {secret: 'abc123'}
|
10
|
+
b.use(OmniAuth::Strategies::Citadele, PRIVATE_KEY, PRIVATE_CRT, PUBLIC_CRT, 'MY_FROM')
|
11
|
+
b.run lambda{|env| [404, {}, ['Not Found']]}
|
12
|
+
end.to_app }
|
13
|
+
|
14
|
+
let(:last_response_xmldata) { last_response.body.match(/name="xmldata" type="hidden" value="([^"]*)"/)[1] }
|
15
|
+
|
16
|
+
context 'request phase' do
|
17
|
+
let!(:timestamp) { '20170905175959000' }
|
18
|
+
let!(:request_uid) { '7387bf5b-fa27-4fdd-add6-a6bfb2599f77' }
|
19
|
+
|
20
|
+
it 'displays a single form' do
|
21
|
+
get '/auth/citadele'
|
22
|
+
expect(last_response.status).to eq(200)
|
23
|
+
expect(last_response.body.scan('<form').size).to eq(1)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'has JavaScript code to submit the form after it is created' do
|
27
|
+
get '/auth/citadele'
|
28
|
+
expect(last_response.body).to be_include('</form><script type="text/javascript">document.forms[0].submit();</script>')
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'has hidden input field xmldata with required data' do
|
32
|
+
allow_any_instance_of(OmniAuth::Strategies::Citadele).to receive(:timestamp).and_return(timestamp)
|
33
|
+
allow_any_instance_of(OmniAuth::Strategies::Citadele).to receive(:request_uid).and_return(request_uid)
|
34
|
+
get '/auth/citadele'
|
35
|
+
|
36
|
+
priv_key = OpenSSL::PKey::RSA.new(PRIVATE_KEY)
|
37
|
+
priv_crt = OpenSSL::X509::Certificate.new(PRIVATE_CRT)
|
38
|
+
x509_subject_name = priv_crt.subject.to_s
|
39
|
+
x509_certificate = priv_crt.to_s.gsub(/[-]{5}(BEGIN|END).*?[-]{5}/, '').gsub('\n', '')
|
40
|
+
doc = Nokogiri::XML(last_response_xmldata.gsub!('"','"'))
|
41
|
+
doc.remove_namespaces!
|
42
|
+
sent_values = {
|
43
|
+
timestamp: doc.xpath("//Timestamp").text, # Verify
|
44
|
+
from: doc.xpath("//From").text,
|
45
|
+
request: doc.xpath("//Request").text,
|
46
|
+
request_uid: doc.xpath("//RequestUID").text, # Verify
|
47
|
+
version: doc.xpath("//Version").text,
|
48
|
+
language: doc.xpath("//Language").text,
|
49
|
+
return_url: doc.xpath("//ReturnURL").text,
|
50
|
+
x509_subject_name: doc.xpath("//X509SubjectName").text,
|
51
|
+
x509_certificate: doc.xpath("//X509Certificate").text
|
52
|
+
}
|
53
|
+
|
54
|
+
expect(sent_values[:timestamp]).to eq timestamp
|
55
|
+
expect(sent_values[:from]).to eq 'MY_FROM'
|
56
|
+
expect(sent_values[:request]).to eq 'AUTHREQ'
|
57
|
+
expect(sent_values[:request_uid]).to eq request_uid
|
58
|
+
expect(sent_values[:version]).to eq '5.0'
|
59
|
+
expect(sent_values[:language]).to eq 'LV'
|
60
|
+
expect(sent_values[:return_url]).to eq 'http://example.org/auth/citadele/callback'
|
61
|
+
expect(sent_values[:x509_subject_name]).to eq x509_subject_name
|
62
|
+
expect(sent_values[:x509_certificate]).to eq x509_certificate
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'xmldata has a correct signature' do
|
66
|
+
allow_any_instance_of(OmniAuth::Strategies::Citadele).to receive(:timestamp).and_return(timestamp)
|
67
|
+
allow_any_instance_of(OmniAuth::Strategies::Citadele).to receive(:request_uid).and_return(request_uid)
|
68
|
+
get '/auth/citadele'
|
69
|
+
|
70
|
+
signed_xml = <<~XML
|
71
|
+
#{last_response_xmldata.gsub('"','"')}
|
72
|
+
XML
|
73
|
+
pub_crt = OpenSSL::X509::Certificate.new(PRIVATE_CRT).public_key
|
74
|
+
xmldsig = Xmldsig::SignedDocument.new(signed_xml)
|
75
|
+
expect(xmldsig.validate(pub_crt)).to be_truthy
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'with default options' do
|
79
|
+
it 'has the default action tag value' do
|
80
|
+
get '/auth/citadele'
|
81
|
+
expect(last_response.body).to be_include("action='https://online.citadele.lv/amai/start.htm'")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'with custom options' do
|
86
|
+
let(:app){ Rack::Builder.new do |b|
|
87
|
+
b.use Rack::Session::Cookie, {secret: 'abc123'}
|
88
|
+
b.use(OmniAuth::Strategies::Citadele, PRIVATE_KEY, PRIVATE_CRT, PUBLIC_CRT, 'MY_FROM',
|
89
|
+
site: 'https://test.lv/banklink')
|
90
|
+
b.run lambda{|env| [404, {}, ['Not Found']]}
|
91
|
+
end.to_app }
|
92
|
+
|
93
|
+
it 'has the custom action tag value' do
|
94
|
+
get '/auth/citadele'
|
95
|
+
expect(last_response.body).to be_include("action='https://test.lv/banklink'")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'with non-existant private key file' do
|
100
|
+
let(:app){ Rack::Builder.new do |b|
|
101
|
+
b.use Rack::Session::Cookie, {secret: 'abc123'}
|
102
|
+
b.use(OmniAuth::Strategies::Citadele, 'missing-private-key-file.pem', PRIVATE_CRT, PUBLIC_CRT, 'MY_FROM')
|
103
|
+
b.run lambda{|env| [404, {}, ['Not Found']]}
|
104
|
+
end.to_app }
|
105
|
+
|
106
|
+
it 'redirects to /auth/failure with appropriate query params' do
|
107
|
+
get '/auth/citadele'
|
108
|
+
expect(last_response.status).to eq(302)
|
109
|
+
expect(last_response.headers['Location']).to eq('/auth/failure?message=private_key_load_err&strategy=citadele')
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'with non-existant private certificate file' do
|
114
|
+
let(:app){ Rack::Builder.new do |b|
|
115
|
+
b.use Rack::Session::Cookie, {secret: 'abc123'}
|
116
|
+
b.use(OmniAuth::Strategies::Citadele, PRIVATE_KEY, 'missing-private-crt-file.pem', PUBLIC_CRT, 'MY_FROM')
|
117
|
+
b.run lambda{|env| [404, {}, ['Not Found']]}
|
118
|
+
end.to_app }
|
119
|
+
|
120
|
+
it 'redirects to /auth/failure with appropriate query params' do
|
121
|
+
get '/auth/citadele'
|
122
|
+
expect(last_response.status).to eq(302)
|
123
|
+
expect(last_response.headers['Location']).to eq('/auth/failure?message=private_crt_load_err&strategy=citadele')
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context 'callback phase' do
|
129
|
+
let(:auth_hash){ last_request.env['omniauth.auth'] }
|
130
|
+
let(:response_xmldata) do
|
131
|
+
<<~XML
|
132
|
+
<?xml version="1.0" encoding="UTF-8"?><FIDAVISTA xmlns="http://ivis.eps.gov.lv/XMLSchemas/100017/fidavista/v1-2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://ivis.eps.gov.lv/XMLSchemas/100017/fidavista/v1-2 http://ivis.eps.gov.lv/XMLSchemas/100017/fidavista/v1-2/fidavista.xsd"><Header><Timestamp>20170502115836000</Timestamp><From>10000</From><Extension><Amai xmlns="http://online.citadele.lv/XMLSchemas/amai/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://online.citadele.lv/XMLSchemas/amai/ http://online.citadele.lv/XMLSchemas/amai/amai.xsd"><Request>AUTHRESP</Request><RequestUID>9209d453-6486-407f-9a5a-522b00e59ced</RequestUID><Version>5.0</Version><Language>LV</Language><PersonCode>00000000000</PersonCode><Person>TestDP AŠĶŪO</Person><Code>100</Code><SignatureData><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><DigestValue>TXvVCF+1mt4MzkKoPSN4fG5/CpDXG1ME5BABCVs7Izg=</DigestValue></Reference></SignedInfo><SignatureValue>oZlsB8TLPni8w7KYtvsXUHpQySU1S1FbGdKrcKHMHOHLcBdz7bpETmLUjmrX4/JcRpZNvSHcq26xQgR+iacdaHDTxf9WzT3yFj9yLN7+XfKScc0H88dNBc3Hhv1IVCbt1GhkPJH7/w8B9yqfndS9vK2pRAyly/ZWvOvpRVuxst9ak75qFFO3k9XmTLQ2t4T8SCCW3EmgPOkV53utUtYo1SMIu2FF/CY1w5cjlZNFWRk0oCPMLAqXYMkVICuWnZJm9QTkHAblMtWneMO/uXsk6i2EgYkvaFWgtG5yiv3oqzFDaMYujgsgthPVs/DJmlWVFby+sqBtHc99VbDqbtP7+Q==</SignatureValue><KeyInfo><X509Data><X509SubjectName>/CN=DNBTEST/C=LV</X509SubjectName><X509Certificate>MIIDQjCCAiqgAwIBAgIJAJ5auG0KG8WMMA0GCSqGSIb3DQEBCwUAMB8xEDAOBgNVBAMTB0ROQlRFU1QxCzAJBgNVBAYTAkxWMB4XDTE3MDQwMzEwMDQzM1oXDTM3MDMyOTEwMDQzM1owHzEQMA4GA1UEAxMHRE5CVEVTVDELMAkGA1UEBhMCTFYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMRYJ0rKoiMbUDxiiXT0xaf8yOMu59m5DFe1A5I/1X9IZCaVEMXcd7ZJoovupOU340n2Kq5ez8zeS3mLY3WK+78MFIysc9nM7/MrTB2KYVaEnpzgN0c9MkiUq8G7LTtcLCbK/eEYmXf4vQIAXwHr6JnP7+sPd7XZhgTNbeugxyqL9Nj1zzLUBOH2v1/PzFH2KnSe/srCSb/PQs+YPpNvx8nWu4FY9ES09idp59hKnWS1M5SRWKYrc3YhLYDinV3Tjwe0uSGJIC4DNijP/QgkZ6TSIiSOuaTIQofTkFxT9r32SCTjm8oLzK6w8dvPmx2e9Q9urfD99jmiLh7N7hII7TAgMBAAGjgYAwfjAdBgNVHQ4EFgQU3vSU9SHIDGRYCE/bfS9Y27kPKuowTwYDVR0jBEgwRoAU3vSU9SHIDGRYCE/bfS9Y27kPKuqhI6QhMB8xEDAOBgNVBAMTB0ROQlRFU1QxCzAJBgNVBAYTAkxWggkAnlq4bQobxYwwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEApoS7dHifbvMluHL9ypLgJ+SVr/RaAYy8WYE9lfK7CBX0cLzn4pxZm69WpWqp3qB4FxEQS2PNt6TAwexNUeWkKUrMxdnSRRw5gnMM0ELNpWd/xWvu3MHZfR0whfyQyweipttgcaCOMQoRH/DS2HeS3GcRk5ljHzRhavqqgnLY8WZ/YGtnBqFlanMzF2dfWQqld/73S0v9ygwKaC+SwVHIQ8XwgZkwxM3MxyXOuE4sx5p+KaQ7n/aRRsebEZhMUzYXd0+ekN8cNjefBmCJlkV+VxeZwo7s97A4qYMku6Ac3Zji8SUi+Qz9RD0qE8Sjrn8obEY8rDfkGoPZf+ygH4MkOA==</X509Certificate></X509Data></KeyInfo></Signature></SignatureData></Amai></Extension></Header></FIDAVISTA>
|
133
|
+
XML
|
134
|
+
end
|
135
|
+
|
136
|
+
context 'with valid response' do
|
137
|
+
before do
|
138
|
+
post '/auth/citadele/callback', xmldata: response_xmldata
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'sets the correct uid value in the auth hash' do
|
142
|
+
expect(auth_hash.uid).to eq('000000-00000')
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'sets the correct info.full_name value in the auth hash' do
|
146
|
+
expect(auth_hash.info.full_name).to eq('TestDP AŠĶŪO')
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
context 'with non-existant public key file' do
|
151
|
+
let(:app){ Rack::Builder.new do |b|
|
152
|
+
b.use Rack::Session::Cookie, {secret: 'abc123'}
|
153
|
+
b.use(OmniAuth::Strategies::Citadele, PRIVATE_KEY, PRIVATE_CRT, 'missing-public-key-file.pem' )
|
154
|
+
b.run lambda{|env| [404, {}, ['Not Found']]}
|
155
|
+
end.to_app }
|
156
|
+
|
157
|
+
it 'redirects to /auth/failure with appropriate query params' do
|
158
|
+
post '/auth/citadele/callback' # Params are not important, because we're testing public key loading
|
159
|
+
expect(last_response.status).to eq(302)
|
160
|
+
expect(last_response.headers['Location']).to eq('/auth/failure?message=public_crt_load_err&strategy=citadele')
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
context 'with invalid response' do
|
165
|
+
it 'detects code 200' do
|
166
|
+
post '/auth/citadele/callback', xmldata: response_xmldata.gsub('<Code>100</Code', '<Code>200</Code')
|
167
|
+
expect(last_response.status).to eq(302)
|
168
|
+
expect(last_response.headers['Location']).to eq('/auth/failure?message=authentication_cancelled_error&strategy=citadele')
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'detects code 300' do
|
172
|
+
error_msg = 'system_error_300'
|
173
|
+
xmldata = response_xmldata.gsub('<Code>100</Code', "<Code>300</Code><Message>#{error_msg}</Message>")
|
174
|
+
post '/auth/citadele/callback', xmldata: xmldata
|
175
|
+
expect(last_response.status).to eq(302)
|
176
|
+
expect(last_response.headers['Location']).to eq("/auth/failure?message=#{error_msg}&strategy=citadele")
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'detects unsupported response request' do
|
180
|
+
xmldata = response_xmldata.gsub('<Request>AUTHRESP</Request', '<Request>AUTHRESP1</Request')
|
181
|
+
post '/auth/citadele/callback', xmldata: xmldata
|
182
|
+
expect(last_response.status).to eq(302)
|
183
|
+
expect(last_response.headers['Location']).to eq('/auth/failure?message=unsupported_response_request&strategy=citadele')
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'detects invalid response signature err' do
|
187
|
+
xmldata = response_xmldata.gsub(/<SignatureValue>.{6}/, '<SignatureValue>xxyyzz')
|
188
|
+
post '/auth/citadele/callback', xmldata: xmldata
|
189
|
+
expect(last_response.status).to eq(302)
|
190
|
+
expect(last_response.headers['Location']).to eq('/auth/failure?message=invalid_response_signature_err&strategy=citadele')
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
$:.unshift File.expand_path('..', __FILE__)
|
2
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
3
|
+
require 'rspec'
|
4
|
+
require 'rack/test'
|
5
|
+
require 'omniauth'
|
6
|
+
require 'omniauth-citadele'
|
7
|
+
|
8
|
+
RSpec.configure do |config|
|
9
|
+
config.add_setting('cert_folder')
|
10
|
+
config.cert_folder = File.expand_path('../certs', __FILE__)
|
11
|
+
|
12
|
+
config.include Rack::Test::Methods
|
13
|
+
config.extend OmniAuth::Test::StrategyMacros, :type => :strategy
|
14
|
+
config.expect_with :rspec do |c|
|
15
|
+
c.syntax = :expect
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
I18n.enforce_available_locales = false
|
metadata
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: omniauth-citadele
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- MAK IT
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-02-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: omniauth
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: i18n
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rack-test
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: xmldsig
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: nokogiri
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description: OmniAuth strategy for Citadele Banklink
|
126
|
+
email:
|
127
|
+
- admin@makit.lv
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- ".gitignore"
|
133
|
+
- ".travis.yml"
|
134
|
+
- Gemfile
|
135
|
+
- LICENSE.txt
|
136
|
+
- README.md
|
137
|
+
- Rakefile
|
138
|
+
- lib/omniauth-citadele.rb
|
139
|
+
- lib/omniauth/citadele.rb
|
140
|
+
- lib/omniauth/citadele/version.rb
|
141
|
+
- lib/omniauth/locales/omniauth.en.yml
|
142
|
+
- lib/omniauth/locales/omniauth.lv.yml
|
143
|
+
- lib/omniauth/strategies/citadele.rb
|
144
|
+
- omniauth-citadele.gemspec
|
145
|
+
- spec/certs/request.crt
|
146
|
+
- spec/certs/request.key
|
147
|
+
- spec/certs/response.crt
|
148
|
+
- spec/certs/response.key
|
149
|
+
- spec/omniauth/strategies/citadele_spec.rb
|
150
|
+
- spec/spec_helper.rb
|
151
|
+
homepage: https://github.com/mak-it/omniauth-citadele
|
152
|
+
licenses:
|
153
|
+
- MIT
|
154
|
+
metadata: {}
|
155
|
+
post_install_message:
|
156
|
+
rdoc_options: []
|
157
|
+
require_paths:
|
158
|
+
- lib
|
159
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
160
|
+
requirements:
|
161
|
+
- - ">="
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: 2.3.0
|
164
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
165
|
+
requirements:
|
166
|
+
- - ">="
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '0'
|
169
|
+
requirements: []
|
170
|
+
rubygems_version: 3.0.1
|
171
|
+
signing_key:
|
172
|
+
specification_version: 4
|
173
|
+
summary: OmniAuth strategy for Citadele Banklink
|
174
|
+
test_files:
|
175
|
+
- spec/certs/request.crt
|
176
|
+
- spec/certs/request.key
|
177
|
+
- spec/certs/response.crt
|
178
|
+
- spec/certs/response.key
|
179
|
+
- spec/omniauth/strategies/citadele_spec.rb
|
180
|
+
- spec/spec_helper.rb
|