mobile_id 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/mobile_id.rb +161 -0
  3. metadata +127 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4fe6d1fd810346d147526247e6caff4a425668840b1926efaae177151ffac96d
4
+ data.tar.gz: d3030278e561fa6959e92cf1fb4b928d3381a4a604e79e5e4b3ac0d95ed98525
5
+ SHA512:
6
+ metadata.gz: 1ab4acaef19ceaea34fd9c28e55984a9b07bc220304dc1b92ba8c7f647a73f283256f0d4c7a30128ba1894fd56d8ed435a1c22cd92022a3add06995ac243be82
7
+ data.tar.gz: 60acfeb6677a3da2534ec390b2b991b1826ce0780c3d6334774619a2dd3b63b441eeed436d465f558b2f064151953a707ec0ec26a7285572d05fb0293029db55
@@ -0,0 +1,161 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+ require 'digest'
5
+ require 'httparty'
6
+ require 'active_support/core_ext/hash/indifferent_access'
7
+ require 'i18n'
8
+ if defined?(Rails)
9
+ require 'mobile_id/railtie'
10
+ else
11
+ I18n.load_path << Dir[File.expand_path("lib/mobile_id/locales") + "/*.yml"]
12
+ end
13
+
14
+ class MobileId
15
+ class Error < StandardError; end
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
161
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mobile_id
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Priit Tark
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-09-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httparty
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: openssl
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 2.2.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 2.2.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: i18n
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
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: activesupport
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
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: rspec
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: pry
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
+ description: Estonia Mobile ID authentication, more info at https://www.id.ee/en/
98
+ email: priit@gitlab.eu
99
+ executables: []
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - lib/mobile_id.rb
104
+ homepage: https://github.com/gitlabeu/mobile_id
105
+ licenses:
106
+ - MIT
107
+ metadata: {}
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubygems_version: 3.1.4
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: Estonia Mobile ID authentication
127
+ test_files: []