mobile_id 0.0.1 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4fe6d1fd810346d147526247e6caff4a425668840b1926efaae177151ffac96d
4
- data.tar.gz: d3030278e561fa6959e92cf1fb4b928d3381a4a604e79e5e4b3ac0d95ed98525
3
+ metadata.gz: 7b5200abc2bfce7f9f1e41ecb8e5ac4f7e75767e97b755faf3d5293270e03b29
4
+ data.tar.gz: bb97dfa048f527f417159dbca7222973d56404f632fcffc2090369ed99002390
5
5
  SHA512:
6
- metadata.gz: 1ab4acaef19ceaea34fd9c28e55984a9b07bc220304dc1b92ba8c7f647a73f283256f0d4c7a30128ba1894fd56d8ed435a1c22cd92022a3add06995ac243be82
7
- data.tar.gz: 60acfeb6677a3da2534ec390b2b991b1826ce0780c3d6334774619a2dd3b63b441eeed436d465f558b2f064151953a707ec0ec26a7285572d05fb0293029db55
6
+ metadata.gz: 4f79d3dc6c37f22273b6fe502fe5d6898042455dac704c04f7de0463b69cf8485dfca344898b444d14003f922d7023ff5ce7ea2617e52563b6c917aaeca718f9
7
+ data.tar.gz: f499e7ebb0a3962038186c511305264d34926a733efac2c21706dc9b113215cfdbc4bfbb54f1a9c21ae5f45540cde23d7aa49097ca50d2c6b9b6f9654247e240
@@ -0,0 +1,17 @@
1
+ Release 0.0.6
2
+ * Cert path fix
3
+
4
+ Release 0.0.5
5
+ * Added user certificate validation
6
+
7
+ Release 0.0.4
8
+ * Refactored MobileId to MobileId::Auth
9
+
10
+ Release 0.0.3
11
+ * Gemspec update
12
+
13
+ Release 0.0.2
14
+ * Readme update
15
+
16
+ Release 0.0.1
17
+ * 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,94 @@
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
+ binding.pry
20
+ @test_store ||=
21
+ build_store([
22
+ File.join(root_path, 'TEST_of_EE_Certification_Centre_Root_CA.pem.crt'),
23
+ File.join(root_path, 'TEST_of_ESTEID-SK_2015.pem.crt')
24
+ ])
25
+ end
26
+
27
+ def build_store(paths)
28
+ store = OpenSSL::X509::Store.new
29
+ paths.each { |path| cert = OpenSSL::X509::Certificate.new(File.read(path)); store.add_cert(cert) }
30
+ store
31
+ end
32
+ end
33
+
34
+ attr_accessor :cert, :subject
35
+
36
+ def initialize(base64_cert, live:)
37
+ self.cert = OpenSSL::X509::Certificate.new(Base64.decode64(base64_cert))
38
+ verify!(self.cert, live: live)
39
+ build_cert_subject
40
+ end
41
+
42
+ def verify!(cert, live:)
43
+ store = live == true ? self.class.live_store : self.class.test_store
44
+ raise Error, 'User certificate is not valid' unless store.verify(cert)
45
+ raise Error, 'User certificate is not valid' unless cert.public_key.check_key
46
+ raise Error, 'User certificate is expired' unless (cert.not_before..cert.not_after) === Time.now
47
+
48
+ true
49
+ end
50
+
51
+ def verify_signature!(signature, doc)
52
+ # TODO OpenSSL does not parse signature
53
+ # cert.public_key.verify(OpenSSL::Digest::SHA256.new, signature, doc)
54
+ end
55
+
56
+ def given_name
57
+ subject["GN"].tr(",", " ")
58
+ end
59
+ alias first_name given_name
60
+
61
+ def surname
62
+ subject["SN"].tr(",", " ")
63
+ end
64
+ alias last_name surname
65
+
66
+ def country
67
+ subject["C"].tr(",", " ")
68
+ end
69
+
70
+ def common_name
71
+ subject["CN"]
72
+ end
73
+
74
+ def organizational_unit
75
+ subject["OU"]
76
+ end
77
+
78
+ def serial_number
79
+ subject["serialNumber"]
80
+ end
81
+ alias personal_code serial_number
82
+
83
+ private
84
+
85
+ def build_cert_subject
86
+ self.subject = cert.subject.to_utf8.split(/(?<!\\)\,+/).each_with_object({}) do |c, result|
87
+ next unless c.include?("=")
88
+
89
+ key, val = c.split("=")
90
+ result[key] = val
91
+ end
92
+ end
93
+ end
94
+ 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.1
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Priit Tark
@@ -94,13 +94,26 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
- description: Estonia Mobile ID authentication, more info at https://www.id.ee/en/
97
+ description: Estonia Mobile ID authentication
98
98
  email: priit@gitlab.eu
99
99
  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