mobile_id 0.0.2 → 0.0.7

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: dd821489ca866a30d97debb4b24438558dc578a94b20e34c1620481c7a0fc54d
4
- data.tar.gz: 8c1f3d4f40d90698c05f8d7112e7507966e480baa6c8c3a37cb8035d2dddf4d1
3
+ metadata.gz: ac13ee4d2a254bb0b64473c0dbbdd8e26a42dc60dcb3dfdbbbcd6c52d35b2826
4
+ data.tar.gz: c01bc3c9e51a8795efe74d14cdb3426645a445cbe8f5cd750fce34795e4f1341
5
5
  SHA512:
6
- metadata.gz: c90fde223c4830be512c78682421fc06848346a9ec81193e8afe8b13379878301c9c1479a04dddc872d2f19a34d72dee986233031c51c9a607601259c6b69cf0
7
- data.tar.gz: 6118400c09a3a34bb687420338be9757f28c7f7273d39a56b352348f0dbcea3908768752998101a28ed7c4d006e39e7020e57b99f7be8fc4859a6dc3cb85711a
6
+ metadata.gz: 9b4f3bfe1608f051a02814ab6299320804ffcbdcb12da9e3aaae232050e6f24af997636668efbf578e80ad80d6a7c76319444695c97b80de30a7b585d05eeace
7
+ data.tar.gz: 96c9db3d18d630e249772b560dfdd8d6d52974bc6bf968efbee15ae3d5eeba86db88b91724bbe2950ed180ac72c781d805f8e94be1b3d1ee4f7a02ec6526c078
@@ -0,0 +1,20 @@
1
+ Release 0.0.7
2
+ * Cert cleanup
3
+
4
+ Release 0.0.6
5
+ * Cert path fix
6
+
7
+ Release 0.0.5
8
+ * Added user certificate validation
9
+
10
+ Release 0.0.4
11
+ * Refactored MobileId to MobileId::Auth
12
+
13
+ Release 0.0.3
14
+ * Gemspec update
15
+
16
+ Release 0.0.2
17
+ * Readme update
18
+
19
+ Release 0.0.1
20
+ * Init
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2019-2020, Priit Tark, priit@gitlab.eu
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,133 @@
1
+ # MobileId::Ruby::Gem
2
+
3
+ Estonia Mobile ID authentication, more info at https://www.id.ee/en/
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'mobile_id'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install mobile_id
20
+
21
+ ## Test usage
22
+
23
+ Execute irb:
24
+
25
+ $ bundle exec irb
26
+ irb(main):001:0> require 'mobile_id'
27
+ => true
28
+ irb(main):002:0> @mid = MobileId::Auth.new(live: false)
29
+ => #<MobileId::Auth:0x000055ac4cb25630 @url="https://tsp.demo.sk.ee/mid-api", @uuid="00000000-0000-0000-0000-000000000000", @name="DEMO", @hash="two+e7UMoFCAXHo8q9AnWqSC58Hhil74RowY8Gg9xQY=">
30
+ irb(main):003:0> auth = @mid.authenticate!(phone: '00000766', personal_code: '60001019906')
31
+ => {"session_id"=>"34e7eff0-691b-4fad-9798-8db680587b18", "phone"=>"00000766", "phone_calling_code"=>"+372"}
32
+ irb(main):004:0> verify = @mid.verify!(auth)
33
+ => {"personal_code"=>"60001019906", "first_name"=>"MARY ÄNN", "last_name"=>"O’CONNEŽ-ŠUSLIK TESTNUMBER", "phone"=>"00000766", "phone_calling_code"=>"+372", "auth_provider"=>"mobileid"}
34
+
35
+ You get verified attributes: personal_code, first_name, last_name, phone, phone_calling_code, auth_provider
36
+
37
+
38
+ ## Live usage
39
+
40
+ For live usage, add your relyingPartyUUID (RPUUID) and relyingPartyName what you get from https://www.sk.ee
41
+
42
+ ```ruby
43
+ @mid = MobileId::Auth.new(live: true, uuid: "39e7eff0-241b-4fad-2798-9db680587b20", name: 'My service name')
44
+ ```
45
+
46
+ Rails with Devise example controller:
47
+
48
+ ```ruby
49
+ class MobileSessionsController < ApplicationController
50
+ include Devise::Controllers::Helpers
51
+ skip_authorization_check only: [:new, :show, :create, :update]
52
+ before_action :init_mobile_id, only: [:create, :update]
53
+
54
+ def new
55
+ @user = User.new
56
+ end
57
+
58
+ # makes Mobile ID authentication
59
+ def create
60
+ session[:auth] = @mid.authenticate!(phone: params[:phone], personal_code: params[:personal_code])
61
+ render :show, locals: { verification_code: @mid.verification_code }
62
+ rescue MobileId::Error => e
63
+ render :error, locals: { message: e }
64
+ end
65
+
66
+ # verifices Mobile ID user
67
+ def update
68
+ session[:auth] = @mid.verify!(session[:auth])
69
+ find_or_create_user_and_redirect(personal_code: @mid.personal_code)
70
+ rescue MobileId::Error => e
71
+ render :error, locals: { message: e }
72
+ end
73
+
74
+ private
75
+
76
+ def init_mobile_id
77
+ @mid = MobileId.new(live: true, uuid: ENV['sk_mid_uuid'], name: ENV['sk_mid_name'])
78
+ end
79
+
80
+ # It's pure your system business logic what to do here with validated user attributes, example code:
81
+ def find_or_create_user_and_redirect(personal_code:)
82
+ @user = User.find_by(personal_code: personal_code)
83
+
84
+ # bind currently present email only account with mobile-id
85
+ if @user.nil? && current_user&.confirmed_email_only_account?
86
+ @user = current_user
87
+ @user.personal_code = personal_code
88
+ @user.save!
89
+ end
90
+
91
+ return redirect_to new_omniuser_url, notice: t(:finish_setup) if @user.nil? || @user.new_record?
92
+ return redirect_to root_url, alert: t(:unlock_info) if @user.access_locked?
93
+
94
+ if @user.valid? && @user.confirmed_at
95
+ # overwrite name changes
96
+ @user.first_name = session[:auth]['first_name'] if session[:auth]['first_name'].present?
97
+ @user.last_name = session[:auth]['last_name'] if session[:auth]['last_name'].present?
98
+ @user.save! if @user.changed?
99
+
100
+ sign_in_and_redirect(@user, notice: t('devise.sessions.signed_in'))
101
+ else
102
+ redirect_to edit_omniuser_url(@user), notice: t('devise.failure.unconfirmed')
103
+ end
104
+ end
105
+ end
106
+ ```
107
+
108
+ ## Development
109
+
110
+ After checking out the repo, run `bundle` to install dependencies. For testing code, run `rspec`
111
+
112
+ ## Contributors
113
+
114
+ * Priit Tark
115
+ * Andri Möll for pointing out user signature issue
116
+
117
+ ## Contributing
118
+
119
+ Bug reports and pull requests are welcome on GitHub at https://github.com/gitlabeu/mobile_id
120
+
121
+ ## Roadmap
122
+
123
+ * Auth signature validation
124
+ * Document sign
125
+ * Rails generators
126
+
127
+ ## License
128
+
129
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
130
+
131
+ ## Sponsors
132
+
133
+ Gem development and testing is sponsored by [GiTLAB](https://gitlab.eu).
@@ -11,151 +11,11 @@ else
11
11
  I18n.load_path << Dir[File.expand_path("lib/mobile_id/locales") + "/*.yml"]
12
12
  end
13
13
 
14
- class MobileId
14
+ module MobileId
15
15
  class Error < StandardError; end
16
16
 
17
- # API documentation https://github.com/SK-EID/MID
18
- LIVE_URL = "https://mid.sk.ee/mid-api"
19
- TEST_URL = "https://tsp.demo.sk.ee/mid-api"
20
-
21
- TEST_UUID = "00000000-0000-0000-0000-000000000000"
22
- TEST_NAME = "DEMO"
23
-
24
- attr_accessor :url, :uuid, :name, :hash, :cert, :cert_subject
25
-
26
- def initialize(live:, uuid: nil, name: nil)
27
- self.url = live == true ? LIVE_URL : TEST_URL
28
- self.uuid = live == true ? uuid : TEST_UUID
29
- self.name = live == true ? name : TEST_NAME
30
- self.hash = Digest::SHA256.base64digest(SecureRandom.uuid)
31
- end
32
-
33
- def authenticate!(phone_calling_code: nil, phone:, personal_code:, language: nil, display_text: nil)
34
- phone_calling_code ||= '+372'
35
- full_phone = "#{phone_calling_code}#{phone}"
36
- language ||=
37
- case I18n.locale
38
- when :et
39
- display_text ||= 'Autentimine'
40
- 'EST'
41
- when :ru
42
- display_text ||= 'Аутентификация'
43
- 'RUS'
44
- else
45
- display_text ||= 'Authentication'
46
- 'ENG'
47
- end
48
-
49
- options = {
50
- headers: {
51
- "Content-Type": "application/json"
52
- },
53
- query: {},
54
- body: {
55
- relyingPartyUUID: uuid,
56
- relyingPartyName: name,
57
- phoneNumber: full_phone.to_s.strip,
58
- nationalIdentityNumber: personal_code.to_s.strip,
59
- hash: hash,
60
- hashType: 'SHA256',
61
- language: language,
62
- displayText: display_text,
63
- displayTextFormat: 'GSM-7' # or "UCS-2”
64
- }.to_json
65
- }
66
-
67
- response = HTTParty.post(url + '/authentication', options)
68
- raise Error, "#{I18n.t('mobile_id.some_error')} #{response}" unless response.code == 200
69
-
70
- ActiveSupport::HashWithIndifferentAccess.new(
71
- session_id: response['sessionID'],
72
- phone: phone,
73
- phone_calling_code: phone_calling_code
74
- )
75
- end
76
-
77
- def verify!(auth)
78
- long_poll!(session_id: auth['session_id'])
79
-
80
- ActiveSupport::HashWithIndifferentAccess.new(
81
- personal_code: personal_code,
82
- first_name: first_name,
83
- last_name: last_name,
84
- phone: auth['phone'],
85
- phone_calling_code: auth['phone_calling_code'],
86
- auth_provider: 'mobileid' # User::MOBILEID
87
- )
88
- end
89
-
90
- def long_poll!(session_id:)
91
- response = HTTParty.get(url + "/authentication/session/#{session_id}")
92
- raise Error, "#{I18n.t('mobile_id.some_error')} #{response.code} #{response}" if response.code != 200
93
-
94
- if response['state'] == 'COMPLETE' && response['result'] != 'OK'
95
- message =
96
- case response['result']
97
- when "TIMEOUT"
98
- I18n.t('mobile_id.timeout')
99
- when "NOT_MID_CLIENT"
100
- I18n.t('mobile_id.user_is_not_mobile_id_client')
101
- when "USER_CANCELLED"
102
- I18n.t('mobile_id.user_cancelled')
103
- when "SIGNATURE_HASH_MISMATCH"
104
- I18n.t('mobile_id.signature_hash_mismatch')
105
- when "PHONE_ABSENT"
106
- I18n.t('mobile_id.phone_absent')
107
- when "DELIVERY_ERROR"
108
- I18n.t('mobile_id.delivery_error')
109
- when "SIM_ERROR"
110
- I18n.t('mobile_id.sim_error')
111
- end
112
- raise Error, message
113
- end
114
-
115
- self.cert = OpenSSL::X509::Certificate.new(Base64.decode64(response['cert']))
116
- self.cert_subject = build_cert_subject
117
- cert
118
- end
119
-
120
- def verification_code
121
- format("%04d", (Digest::SHA2.new(256).digest(Base64.decode64(hash))[-2..-1].unpack1('n') % 10000))
122
- end
123
-
124
- def given_name
125
- cert_subject["GN"].tr(",", " ")
126
- end
127
- alias first_name given_name
128
-
129
- def surname
130
- cert_subject["SN"].tr(",", " ")
131
- end
132
- alias last_name surname
133
-
134
- def country
135
- cert_subject["C"].tr(",", " ")
136
- end
137
-
138
- def common_name
139
- cert_subject["CN"]
140
- end
141
-
142
- def organizational_unit
143
- cert_subject["OU"]
144
- end
145
-
146
- def serial_number
147
- cert_subject["serialNumber"]
148
- end
149
- alias personal_code serial_number
150
-
151
- private
152
-
153
- def build_cert_subject
154
- self.cert_subject = cert.subject.to_utf8.split(/(?<!\\)\,+/).each_with_object({}) do |c, result|
155
- next unless c.include?("=")
156
-
157
- key, val = c.split("=")
158
- result[key] = val
159
- end
160
- end
17
+ LOCALES = [:en, :et, :ru]
161
18
  end
19
+
20
+ require 'mobile_id/cert'
21
+ require 'mobile_id/auth'
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MobileId
4
+ class Auth
5
+ # API documentation https://github.com/SK-EID/MID
6
+ LIVE_URL = "https://mid.sk.ee/mid-api"
7
+ TEST_URL = "https://tsp.demo.sk.ee/mid-api"
8
+
9
+ TEST_UUID = "00000000-0000-0000-0000-000000000000"
10
+ TEST_NAME = "DEMO"
11
+
12
+ attr_accessor :url, :uuid, :name, :doc, :hash, :user_cert, :live
13
+
14
+ def initialize(live:, uuid: nil, name: nil)
15
+ self.url = live == true ? LIVE_URL : TEST_URL
16
+ self.uuid = live == true ? uuid : TEST_UUID
17
+ self.name = live == true ? name : TEST_NAME
18
+ self.live = live
19
+ init_doc(SecureRandom.uuid)
20
+ end
21
+
22
+ def init_doc(doc)
23
+ self.doc = doc
24
+
25
+ self.hash = Digest::SHA256.base64digest(self.doc)
26
+ end
27
+
28
+ def authenticate!(phone_calling_code: nil, phone:, personal_code:, language: nil, display_text: nil)
29
+ phone_calling_code ||= '+372'
30
+ full_phone = "#{phone_calling_code}#{phone}"
31
+ language ||=
32
+ case I18n.locale
33
+ when :et
34
+ display_text ||= 'Autentimine'
35
+ 'EST'
36
+ when :ru
37
+ display_text ||= 'Аутентификация'
38
+ 'RUS'
39
+ else
40
+ display_text ||= 'Authentication'
41
+ 'ENG'
42
+ end
43
+
44
+ options = {
45
+ headers: {
46
+ "Content-Type": "application/json"
47
+ },
48
+ query: {},
49
+ body: {
50
+ relyingPartyUUID: uuid,
51
+ relyingPartyName: name,
52
+ phoneNumber: full_phone.to_s.strip,
53
+ nationalIdentityNumber: personal_code.to_s.strip,
54
+ hash: hash,
55
+ hashType: 'SHA256',
56
+ language: language,
57
+ displayText: display_text,
58
+ displayTextFormat: 'GSM-7' # or "UCS-2”
59
+ }.to_json
60
+ }
61
+
62
+ response = HTTParty.post(url + '/authentication', options)
63
+ raise Error, "#{I18n.t('mobile_id.some_error')} #{response}" unless response.code == 200
64
+
65
+ ActiveSupport::HashWithIndifferentAccess.new(
66
+ session_id: response['sessionID'],
67
+ phone: phone,
68
+ phone_calling_code: phone_calling_code,
69
+ doc: doc
70
+ )
71
+ end
72
+
73
+ def verify!(auth)
74
+ long_poll!(session_id: auth['session_id'], doc: auth['doc'])
75
+
76
+ ActiveSupport::HashWithIndifferentAccess.new(
77
+ personal_code: personal_code,
78
+ first_name: first_name,
79
+ last_name: last_name,
80
+ phone: auth['phone'],
81
+ phone_calling_code: auth['phone_calling_code'],
82
+ auth_provider: 'mobileid' # User::MOBILEID
83
+ )
84
+ end
85
+
86
+ def long_poll!(session_id:, doc:)
87
+ response = HTTParty.get(url + "/authentication/session/#{session_id}")
88
+ raise Error, "#{I18n.t('mobile_id.some_error')} #{response.code} #{response}" if response.code != 200
89
+
90
+ if response['state'] == 'COMPLETE' && response['result'] != 'OK'
91
+ message =
92
+ case response['result']
93
+ when "TIMEOUT"
94
+ I18n.t('mobile_id.timeout')
95
+ when "NOT_MID_CLIENT"
96
+ I18n.t('mobile_id.user_is_not_mobile_id_client')
97
+ when "USER_CANCELLED"
98
+ I18n.t('mobile_id.user_cancelled')
99
+ when "SIGNATURE_HASH_MISMATCH"
100
+ I18n.t('mobile_id.signature_hash_mismatch')
101
+ when "PHONE_ABSENT"
102
+ I18n.t('mobile_id.phone_absent')
103
+ when "DELIVERY_ERROR"
104
+ I18n.t('mobile_id.delivery_error')
105
+ when "SIM_ERROR"
106
+ I18n.t('mobile_id.sim_error')
107
+ end
108
+ raise Error, message
109
+ end
110
+
111
+ @user_cert = MobileId::Cert.new(response['cert'], live: live)
112
+ @user_cert.verify_signature!(response['signature']['value'], doc)
113
+ self.user_cert = @user_cert
114
+ end
115
+
116
+ def verification_code
117
+ format("%04d", (Digest::SHA2.new(256).digest(Base64.decode64(hash))[-2..-1].unpack1('n') % 10000))
118
+ end
119
+
120
+ def given_name
121
+ user_cert.given_name
122
+ end
123
+ alias first_name given_name
124
+
125
+ def surname
126
+ user_cert.surname
127
+ end
128
+ alias last_name surname
129
+
130
+ def country
131
+ user_cert.country
132
+ end
133
+
134
+ def common_name
135
+ user_cert.common_name
136
+ end
137
+
138
+ def organizational_unit
139
+ user_cert.organizational_unit
140
+ end
141
+
142
+ def serial_number
143
+ user_cert.serial_number
144
+ end
145
+ alias personal_code serial_number
146
+ end
147
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MobileId
4
+ class Cert
5
+ class << self
6
+ def root_path
7
+ @root_path ||= File.expand_path('certs', __dir__)
8
+ end
9
+
10
+ def live_store
11
+ @live_store ||=
12
+ build_store([
13
+ File.join(root_path, 'EE_Certification_Centre_Root_CA.pem.crt'),
14
+ File.join(root_path, 'ESTEID-SK_2015.pem.crt')
15
+ ])
16
+ end
17
+
18
+ def test_store
19
+ @test_store ||=
20
+ build_store([
21
+ File.join(root_path, 'TEST_of_EE_Certification_Centre_Root_CA.pem.crt'),
22
+ File.join(root_path, 'TEST_of_ESTEID-SK_2015.pem.crt')
23
+ ])
24
+ end
25
+
26
+ def build_store(paths)
27
+ store = OpenSSL::X509::Store.new
28
+ paths.each { |path| cert = OpenSSL::X509::Certificate.new(File.read(path)); store.add_cert(cert) }
29
+ store
30
+ end
31
+ end
32
+
33
+ attr_accessor :cert, :subject
34
+
35
+ def initialize(base64_cert, live:)
36
+ self.cert = OpenSSL::X509::Certificate.new(Base64.decode64(base64_cert))
37
+ verify!(self.cert, live: live)
38
+ build_cert_subject
39
+ end
40
+
41
+ def verify!(cert, live:)
42
+ store = live == true ? self.class.live_store : self.class.test_store
43
+ raise Error, 'User certificate is not valid' unless store.verify(cert)
44
+ raise Error, 'User certificate is not valid' unless cert.public_key.check_key
45
+ raise Error, 'User certificate is expired' unless (cert.not_before..cert.not_after) === Time.now
46
+
47
+ true
48
+ end
49
+
50
+ def verify_signature!(signature, doc)
51
+ # TODO OpenSSL does not parse signature
52
+ # cert.public_key.verify(OpenSSL::Digest::SHA256.new, signature, doc)
53
+ end
54
+
55
+ def given_name
56
+ subject["GN"].tr(",", " ")
57
+ end
58
+ alias first_name given_name
59
+
60
+ def surname
61
+ subject["SN"].tr(",", " ")
62
+ end
63
+ alias last_name surname
64
+
65
+ def country
66
+ subject["C"].tr(",", " ")
67
+ end
68
+
69
+ def common_name
70
+ subject["CN"]
71
+ end
72
+
73
+ def organizational_unit
74
+ subject["OU"]
75
+ end
76
+
77
+ def serial_number
78
+ subject["serialNumber"]
79
+ end
80
+ alias personal_code serial_number
81
+
82
+ private
83
+
84
+ def build_cert_subject
85
+ self.subject = cert.subject.to_utf8.split(/(?<!\\)\,+/).each_with_object({}) do |c, result|
86
+ next unless c.include?("=")
87
+
88
+ key, val = c.split("=")
89
+ result[key] = val
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,24 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1
3
+ MQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1
4
+ czEoMCYGA1UEAwwfRUUgQ2VydGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYG
5
+ CSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIwMTAxMDMwMTAxMDMwWhgPMjAzMDEy
6
+ MTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNl
7
+ ZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBS
8
+ b290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEB
9
+ AQUAA4IBDwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUy
10
+ euuOF0+W2Ap7kaJjbMeMTC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvO
11
+ bntl8jixwKIy72KyaOBhU8E2lf/slLo2rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIw
12
+ WFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw93X2PaRka9ZP585ArQ/d
13
+ MtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtNP2MbRMNE
14
+ 1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYD
15
+ VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/
16
+ zQas8fElyalL1BSZMEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYB
17
+ BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEF
18
+ BQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+RjxY6hUFaTlrg4wCQiZrxTFGGV
19
+ v9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqMlIpPnTX/dqQG
20
+ E5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u
21
+ uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIW
22
+ iAYLtqZLICjU3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/v
23
+ GVCJYMzpJJUPwssd8m92kMfMdcGWxZ0=
24
+ -----END CERTIFICATE-----
@@ -0,0 +1,37 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIGcDCCBVigAwIBAgIQRUgJC4ec7yFWcqzT3mwbWzANBgkqhkiG9w0BAQwFADB1
3
+ MQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1
4
+ czEoMCYGA1UEAwwfRUUgQ2VydGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYG
5
+ CSqGSIb3DQEJARYJcGtpQHNrLmVlMCAXDTE1MTIxNzEyMzg0M1oYDzIwMzAxMjE3
6
+ MjM1OTU5WjBjMQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVy
7
+ aW1pc2tlc2t1czEXMBUGA1UEYQwOTlRSRUUtMTA3NDcwMTMxFzAVBgNVBAMMDkVT
8
+ VEVJRC1TSyAyMDE1MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0oH6
9
+ 1NDxbdW9k8nLA1qGaL4B7vydod2Ewp/STBZB3wEtIJCLdkpEsS8pXfFiRqwDVsgG
10
+ Gbu+Q99trlb5LI7yi7rIkRov5NftBdSNPSU5rAhYPQhvZZQgOwRaHa5Ey+BaLJHm
11
+ LqYQS9hQvQsCYyws+xVvNFUpK0pGD64iycqdMuBl/nWq3fLuZppwBh0VFltm4nhr
12
+ /1S0R9TRJpqFUGbGr4OK/DwebQ5PjhdS40gCUNwmC7fPQ4vIH+x+TCk2aG+u3MoA
13
+ z0IrpVWqiwzG/vxreuPPAkgXeFCeYf6fXLsGz4WivsZFbph2pMjELu6sltlBXfAG
14
+ 3fGv43t91VXicyzR/eT5dsB+zFsW1sHV+1ONPr+qzgDxCH2cmuqoZNfIIq+buob3
15
+ eA8ee+XpJKJQr+1qGrmhggjvAhc7m6cU4x/QfxwRYhIVNhJf+sKVThkQhbJ9XxuK
16
+ k3c18wymwL1mpDD0PIGJqlssMeiuJ4IzagFbgESGNDUd4icm0hQT8CmQeUm1GbWe
17
+ BYseqPhMQX97QFBLXJLVy2SCyoAz7Bq1qA43++EcibN+yBc1nQs2Zoq8ck9MK0bC
18
+ xDMeUkQUz6VeQGp69ImOQrsw46qTz0mtdQrMSbnkXCuLan5dPm284J9HmaqiYi6j
19
+ 6KLcZ2NkUnDQFesBVlMEm+fHa2iR6lnAFYZ06UECAwEAAaOCAgowggIGMB8GA1Ud
20
+ IwQYMBaAFBLyWj7qVhy/zQas8fElyalL1BSZMB0GA1UdDgQWBBSzq4i8mdVipIUq
21
+ CM20HXI7g3JHUTAOBgNVHQ8BAf8EBAMCAQYwdwYDVR0gBHAwbjAIBgYEAI96AQIw
22
+ CQYHBACL7EABAjAwBgkrBgEEAc4fAQEwIzAhBggrBgEFBQcCARYVaHR0cHM6Ly93
23
+ d3cuc2suZWUvQ1BTMAsGCSsGAQQBzh8BAjALBgkrBgEEAc4fAQMwCwYJKwYBBAHO
24
+ HwEEMBIGA1UdEwEB/wQIMAYBAf8CAQAwQQYDVR0eBDowOKE2MASCAiIiMAqHCAAA
25
+ AAAAAAAAMCKHIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMCcGA1Ud
26
+ JQQgMB4GCCsGAQUFBwMJBggrBgEFBQcDAgYIKwYBBQUHAwQwfAYIKwYBBQUHAQEE
27
+ cDBuMCAGCCsGAQUFBzABhhRodHRwOi8vb2NzcC5zay5lZS9DQTBKBggrBgEFBQcw
28
+ AoY+aHR0cDovL3d3dy5zay5lZS9jZXJ0cy9FRV9DZXJ0aWZpY2F0aW9uX0NlbnRy
29
+ ZV9Sb290X0NBLmRlci5jcnQwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL3d3dy5z
30
+ ay5lZS9yZXBvc2l0b3J5L2NybHMvZWVjY3JjYS5jcmwwDQYJKoZIhvcNAQEMBQAD
31
+ ggEBAHRWDGI3P00r2sOnlvLHKk9eE7X93eT+4e5TeaQsOpE5zQRUTtshxN8Bnx2T
32
+ oQ9rgi18q+MwXm2f0mrGakYYG0bix7ZgDQvCMD/kuRYmwLGdfsTXwh8KuL6uSHF+
33
+ U/ZTss6qG7mxCHG9YvebkN5Yj/rYRvZ9/uJ9rieByxw4wo7b19p22PXkAkXP5y3+
34
+ qK/Oet98lqwI97kJhiS2zxFYRk+dXbazmoVHnozYKmsZaSUvoYNNH19tpS7BLdsg
35
+ i9KpbvQLb5ywIMq9ut3+b2Xvzq8yzmHMFtLIJ6Afu1jJpqD82BUAFcvi5vhnP8M7
36
+ b974R18WCOpgNQvXDI+2/8ZINeU=
37
+ -----END CERTIFICATE-----
@@ -0,0 +1,24 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEEzCCAvugAwIBAgIQc/jtqiMEFERMtVvsSsH7sjANBgkqhkiG9w0BAQUFADB9
3
+ MQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1
4
+ czEwMC4GA1UEAwwnVEVTVCBvZiBFRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBSb290
5
+ IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwIhgPMjAxMDEwMDcxMjM0NTZa
6
+ GA8yMDMwMTIxNzIzNTk1OVowfTELMAkGA1UEBhMCRUUxIjAgBgNVBAoMGUFTIFNl
7
+ cnRpZml0c2VlcmltaXNrZXNrdXMxMDAuBgNVBAMMJ1RFU1Qgb2YgRUUgQ2VydGlm
8
+ aWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVl
9
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1gGpqCtDmNNEHUjC8LXq
10
+ xRdC1kpjDgkzOTxQynzDxw/xCjy5hhyG3xX4RPrW9Z6k5ZNTNS+xzrZgQ9m5U6uM
11
+ ywYpx3F3DVgbdQLd8DsLmuVOz02k/TwoRt1uP6xtV9qG0HsGvN81q3HvPR/zKtA7
12
+ MmNZuwuDFQwsguKgDR2Jfk44eKmLfyzvh+Xe6Cr5+zRnsVYwMA9bgBaOZMv1TwTT
13
+ VNi9H1ltK32Z+IhUX8W5f2qVP33R1wWCKapK1qTX/baXFsBJj++F8I8R6+gSyC3D
14
+ kV5N/pOlWPzZYx+kHRkRe/oddURA9InJwojbnsH+zJOa2VrNKakNv2HnuYCIonzu
15
+ pwIDAQABo4GKMIGHMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
16
+ A1UdDgQWBBS1NAqdpS8QxechDr7EsWVHGwN2/jBFBgNVHSUEPjA8BggrBgEFBQcD
17
+ AgYIKwYBBQUHAwEGCCsGAQUFBwMDBggrBgEFBQcDBAYIKwYBBQUHAwgGCCsGAQUF
18
+ BwMJMA0GCSqGSIb3DQEBBQUAA4IBAQAj72VtxIw6p5lqeNmWoQ48j8HnUBM+6mI0
19
+ I+VkQr0EfQhfmQ5KFaZwnIqxWrEPaxRjYwV0xKa1AixVpFOb1j+XuVmgf7khxXTy
20
+ Bmd8JRLwl7teCkD1SDnU/yHmwY7MV9FbFBd+5XK4teHVvEVRsJ1oFwgcxVhyoviR
21
+ SnbIPaOvk+0nxKClrlS6NW5TWZ+yG55z8OCESHaL6JcimkLFjRjSsQDWIEtDvP4S
22
+ tH3vIMUPPiKdiNkGjVLSdChwkW3z+m0EvAjyD9rnGCmjeEm5diLFu7VMNVqupsbZ
23
+ SfDzzBLc5+6TqgQTOG7GaZk2diMkn03iLdHGFrh8ML+mXG9SjEPI
24
+ -----END CERTIFICATE-----
@@ -0,0 +1,37 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIGgzCCBWugAwIBAgIQEDb9gCZi4PdWc7IoNVIbsTANBgkqhkiG9w0BAQwFADB9
3
+ MQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1
4
+ czEwMC4GA1UEAwwnVEVTVCBvZiBFRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBSb290
5
+ IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwIBcNMTUxMjE4MDcxMzQ0WhgP
6
+ MjAzMDEyMTcyMzU5NTlaMGsxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0
7
+ aWZpdHNlZXJpbWlza2Vza3VzMRcwFQYDVQRhDA5OVFJFRS0xMDc0NzAxMzEfMB0G
8
+ A1UEAwwWVEVTVCBvZiBFU1RFSUQtU0sgMjAxNTCCAiIwDQYJKoZIhvcNAQEBBQAD
9
+ ggIPADCCAgoCggIBAMTeAFvLxmAeaOsRKaf+hlkOhW+CdEilmUIKWs+qCWVq+w8E
10
+ 8PA/TohAZdUcO4KFXothmPDmfOCb0ExXcnOPCr2NndavzB39htlyYKYxkOkZi3pL
11
+ z8bZg/HvpBoy8KIg0sYdbhVPYHf6i7fuJjDac4zN1vKdVQXA6Tv5wS/e90/ZyF95
12
+ 5vycxdNLticdozm5yCDMNgsEji6QNA1zIi3+C2YmnDXx6VyxhuC2R3q0xNkwtJ4e
13
+ zs1RZGxWokTNPzQc3ilGhEJlVsS8vP624hUHwufQnwrKWpc3+D+plMIO0j3E+hmh
14
+ 46gIadDRweFR/dzb+CIBHRaFh0LEBjd/cDFQlBI+E8vpkhqeWp6rp1xwnhCL201M
15
+ 3E1E1Mw+51Xqj7WOfY0TzjOmQJy8WJPEwU2m44KxW1SnpeEBVkgb4XYFeQHAllc7
16
+ J7JDv50BoIPpecgaqn1vKR7l//wDsL0MN1tDlBhl3x7TJ/fwMnwB1E3zVZR74TUZ
17
+ h5J49CAcFrfM4RmP/0hcDW8+4wNWMg2Qgst2qmPZmHCI/OJt5yMt0Ud5yPF8AWxV
18
+ ot3TxOBGjMiM8m6WsksFsQxp5WtA0DANGXIIfydTaTV16Mg+KpYVqFKxkvFBmfVp
19
+ 6xApMaFl3dY/m56O9JHEqFpBDF+uDQIMjFJxJ4Pt7Mdk40zfL4PSw9Qco2T3AgMB
20
+ AAGjggINMIICCTAfBgNVHSMEGDAWgBS1NAqdpS8QxechDr7EsWVHGwN2/jAdBgNV
21
+ HQ4EFgQUScDyRDll1ZtGOw04YIOx1i0ohqYwDgYDVR0PAQH/BAQDAgEGMGYGA1Ud
22
+ IARfMF0wMQYKKwYBBAHOHwMBATAjMCEGCCsGAQUFBwIBFhVodHRwczovL3d3dy5z
23
+ ay5lZS9DUFMwDAYKKwYBBAHOHwMBAjAMBgorBgEEAc4fAwEDMAwGCisGAQQBzh8D
24
+ AQQwEgYDVR0TAQH/BAgwBgEB/wIBADBBBgNVHR4EOjA4oTYwBIICIiIwCocIAAAA
25
+ AAAAAAAwIocgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwJwYDVR0l
26
+ BCAwHgYIKwYBBQUHAwkGCCsGAQUFBwMCBggrBgEFBQcDBDCBiQYIKwYBBQUHAQEE
27
+ fTB7MCUGCCsGAQUFBzABhhlodHRwOi8vZGVtby5zay5lZS9jYV9vY3NwMFIGCCsG
28
+ AQUFBzAChkZodHRwOi8vd3d3LnNrLmVlL2NlcnRzL1RFU1Rfb2ZfRUVfQ2VydGlm
29
+ aWNhdGlvbl9DZW50cmVfUm9vdF9DQS5kZXIuY3J0MEMGA1UdHwQ8MDowOKA2oDSG
30
+ Mmh0dHBzOi8vd3d3LnNrLmVlL3JlcG9zaXRvcnkvY3Jscy90ZXN0X2VlY2NyY2Eu
31
+ Y3JsMA0GCSqGSIb3DQEBDAUAA4IBAQDBOYTpbbQuoJKAmtDPpAomDd9mKZCarIPx
32
+ AH8UXphSndMqOmIUA4oQMrLcZ6a0rMyCFR8x4NX7abc8T81cvgUAWjfNFn8+bi6+
33
+ DgbjhYY+wZ010MHHdUo2xPajfog8cDWJPkmz+9PAdyjzhb1eYoEnm5D6o4hZQCiR
34
+ yPnOKp7LZcpsVz1IFXsqP7M5WgHk0SqY1vs+Yhu7zWPSNYFIzNNXGoUtfKhhkHiR
35
+ WFX/wdzr3fqeaQ3gs/PyD53YuJXRzFrktgJJoJWnHEYIhEwbai9+OeKr4L4kTkxv
36
+ PKTyjjpLKcjUk0Y0cxg7BuzwevonyBtL72b/FVs6XsXJJqCa3W4T
37
+ -----END CERTIFICATE-----
@@ -0,0 +1,10 @@
1
+ en:
2
+ mobile_id:
3
+ some_error: There was some error
4
+ timeout: "Mobile-ID session got timeout"
5
+ user_is_not_mobile_id_client: User is not Mobile-ID client.
6
+ user_cancelled: User cancelled the Mobile ID operation
7
+ signature_hash_mismatch: "Mobile-ID has signiture issue. User needs to contact his/her mobile operator."
8
+ phone_absent: Mobile-ID SIM not available
9
+ delivery_error: Mobile-ID SMS sending error.
10
+ sim_error: Invalid response from Mobile-ID SIM card
@@ -0,0 +1,10 @@
1
+ et:
2
+ mobile_id:
3
+ some_error: Tekkis viga
4
+ timeout: "Mobiil-ID sisselogimine aegus"
5
+ user_is_not_mobile_id_client: Kasutaja ei ole Mobiil-ID klient
6
+ user_cancelled: Kasutaja katkestas Mobiil-ID sisselogimise.
7
+ signature_hash_mismatch: "Mobiil-ID digiallkiri on vigane. Palun pöörduge oma mobiilioperaatori poole."
8
+ phone_absent: Kasutaja telefon ei asu levipiirkonnas või on välja lülitatud.
9
+ delivery_error: Mobiil-ID SMS saatmisel tekkis viga.
10
+ sim_error: Mobiil-ID telefoni SIM viga.
@@ -0,0 +1,10 @@
1
+ ru:
2
+ mobile_id:
3
+ some_error: Была некоторая ошибка
4
+ timeout: "Mobile-ID session got timeout"
5
+ user_is_not_mobile_id_client: User is not Mobile-ID client.
6
+ user_cancelled: User cancelled the Mobile ID operation
7
+ signature_hash_mismatch: "Mobile-ID has signiture issue. User needs to contact his/her mobile operator."
8
+ phone_absent: Mobile-ID SIM not available
9
+ delivery_error: Mobile-ID SMS sending error.
10
+ sim_error: Invalid response from Mobile-ID SIM card
@@ -0,0 +1,13 @@
1
+ require 'rails'
2
+
3
+ module MobileId
4
+ class Railtie < ::Rails::Railtie #:nodoc:
5
+ initializer 'mobile_id' do |app|
6
+ DeviseI18n::Railtie.instance_eval do
7
+ (app.config.i18n.available_locales & MobileId::LOCALES).each do |loc|
8
+ I18n.load_path << File.expand_path("locales/#{loc}.yml", __dir__)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mobile_id
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Priit Tark
@@ -100,7 +100,20 @@ executables: []
100
100
  extensions: []
101
101
  extra_rdoc_files: []
102
102
  files:
103
+ - CHANGELOG.md
104
+ - MIT-LICENSE
105
+ - README.md
103
106
  - lib/mobile_id.rb
107
+ - lib/mobile_id/auth.rb
108
+ - lib/mobile_id/cert.rb
109
+ - lib/mobile_id/certs/EE_Certification_Centre_Root_CA.pem.crt
110
+ - lib/mobile_id/certs/ESTEID-SK_2015.pem.crt
111
+ - lib/mobile_id/certs/TEST_of_EE_Certification_Centre_Root_CA.pem.crt
112
+ - lib/mobile_id/certs/TEST_of_ESTEID-SK_2015.pem.crt
113
+ - lib/mobile_id/locales/en.yml
114
+ - lib/mobile_id/locales/et.yml
115
+ - lib/mobile_id/locales/ru.yml
116
+ - lib/mobile_id/railtie.rb
104
117
  homepage: https://github.com/gitlabeu/mobile_id
105
118
  licenses:
106
119
  - MIT