Class: MobileId::Auth

Inherits:
Object
  • Object
show all
Defined in:
lib/mobile_id/auth.rb

Constant Summary collapse

LIVE_URL =

API documentation github.com/SK-EID/MID

'https://mid.sk.ee/mid-api'
TEST_URL =
'https://tsp.demo.sk.ee/mid-api'
TEST_UUID =
'00000000-0000-0000-0000-000000000000'
TEST_NAME =
'DEMO'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(live:, uuid: nil, name: nil, doc: nil) ⇒ Auth

Returns a new instance of Auth.



14
15
16
17
18
19
20
# File 'lib/mobile_id/auth.rb', line 14

def initialize(live:, uuid: nil, name: nil, doc: nil)
  self.url = live == true ? LIVE_URL : TEST_URL
  self.uuid = live == true ? uuid : TEST_UUID
  self.name = live == true ? name : TEST_NAME
  self.live = live
  init_doc(doc || SecureRandom.hex(40))
end

Instance Attribute Details

#docObject

Returns the value of attribute doc.



12
13
14
# File 'lib/mobile_id/auth.rb', line 12

def doc
  @doc
end

#hashObject

Returns the value of attribute hash.



12
13
14
# File 'lib/mobile_id/auth.rb', line 12

def hash
  @hash
end

#liveObject

Returns the value of attribute live.



12
13
14
# File 'lib/mobile_id/auth.rb', line 12

def live
  @live
end

#nameObject

Returns the value of attribute name.



12
13
14
# File 'lib/mobile_id/auth.rb', line 12

def name
  @name
end

#urlObject

Returns the value of attribute url.



12
13
14
# File 'lib/mobile_id/auth.rb', line 12

def url
  @url
end

#user_certObject

Returns the value of attribute user_cert.



12
13
14
# File 'lib/mobile_id/auth.rb', line 12

def user_cert
  @user_cert
end

#uuidObject

Returns the value of attribute uuid.



12
13
14
# File 'lib/mobile_id/auth.rb', line 12

def uuid
  @uuid
end

Instance Method Details

#authenticate!(phone:, personal_code:, phone_calling_code: nil, language: nil, display_text: nil) ⇒ Object

Raises:



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/mobile_id/auth.rb', line 27

def authenticate!(phone:, personal_code:, phone_calling_code: nil, language: nil, display_text: nil)
  phone_calling_code ||= '+372'
  full_phone = "#{phone_calling_code}#{phone}"
  language ||=
    case I18n.locale
    when :et
      display_text ||= 'Autentimine'
      'EST'
    when :ru
      display_text ||= 'Аутентификация'
      'RUS'
    else
      display_text ||= 'Authentication'
      'ENG'
    end

  options = {
    headers: {
      'Content-Type': 'application/json'
    },
    query: {},
    body: {
      relyingPartyUUID: uuid,
      relyingPartyName: name,
      phoneNumber: full_phone.to_s.strip,
      nationalIdentityNumber: personal_code.to_s.strip,
      hash: Base64.strict_encode64(hash),
      hashType: 'SHA256',
      language: language,
      displayText: display_text,
      displayTextFormat: 'GSM-7' # or "UCS-2”
    }.to_json
  }

  response = HTTParty.post("#{url}/authentication", options)
  raise Error, "#{I18n.t('mobile_id.some_error')} #{response}" unless response.code == 200

  ActiveSupport::HashWithIndifferentAccess.new(
    session_id: response['sessionID'],
    phone: phone,
    phone_calling_code: phone_calling_code,
    doc: doc
  )
end

#common_nameObject



149
150
151
# File 'lib/mobile_id/auth.rb', line 149

def common_name
  user_cert.common_name
end

#countryObject



145
146
147
# File 'lib/mobile_id/auth.rb', line 145

def country
  user_cert.country
end

#given_nameObject Also known as: first_name



135
136
137
# File 'lib/mobile_id/auth.rb', line 135

def given_name
  user_cert.given_name
end

#init_doc(doc) ⇒ Object



22
23
24
25
# File 'lib/mobile_id/auth.rb', line 22

def init_doc(doc)
  self.doc = doc
  self.hash = Digest::SHA256.digest(doc)
end

#long_poll!(session_id:, doc:) ⇒ Object

Raises:



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/mobile_id/auth.rb', line 92

def long_poll!(session_id:, doc:)
  response = nil

  # Retries until RUNNING state turns to COMPLETE
  30.times do |_i|
    response = session_request(session_id)
    break if response['state'] == 'COMPLETE'

    sleep 1
  end
  raise Error, "#{I18n.t('mobile_id.some_error')} #{response.code} #{response}" if response['state'] != 'COMPLETE'

  if response['result'] != 'OK'
    message =
      case response['result']
      when 'TIMEOUT'
        I18n.t('mobile_id.timeout')
      when 'NOT_MID_CLIENT'
        I18n.t('mobile_id.user_is_not_mobile_id_client')
      when 'USER_CANCELLED'
        I18n.t('mobile_id.user_cancelled')
      when 'SIGNATURE_HASH_MISMATCH'
        I18n.t('mobile_id.signature_hash_mismatch')
      when 'PHONE_ABSENT'
        I18n.t('mobile_id.phone_absent')
      when 'DELIVERY_ERROR'
        I18n.t('mobile_id.delivery_error')
      when 'SIM_ERROR'
        I18n.t('mobile_id.sim_error')
      end
    raise Error, message
  end

  @user_cert = MobileId::Cert.new(response['cert'], live: live)
  @user_cert.verify_signature!(response['signature']['value'], doc)
  self.user_cert = @user_cert
end

#organizational_unitObject



153
154
155
# File 'lib/mobile_id/auth.rb', line 153

def organizational_unit
  user_cert.organizational_unit
end

#serial_numberObject Also known as: personal_code



157
158
159
# File 'lib/mobile_id/auth.rb', line 157

def serial_number
  user_cert.serial_number
end

#session_request(session_id) ⇒ Object

Raises:



85
86
87
88
89
90
# File 'lib/mobile_id/auth.rb', line 85

def session_request(session_id)
  response = HTTParty.get(url + "/authentication/session/#{session_id}")
  raise Error, "#{I18n.t('mobile_id.some_error')} #{response.code} #{response}" if response.code != 200

  response
end

#surnameObject Also known as: last_name



140
141
142
# File 'lib/mobile_id/auth.rb', line 140

def surname
  user_cert.surname
end

#verification_codeObject



130
131
132
133
# File 'lib/mobile_id/auth.rb', line 130

def verification_code
  binary = hash.to_s.unpack1('B*')
  '%04d' % (binary[0...6] + binary[-7..]).to_i(2)
end

#verify!(auth) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/mobile_id/auth.rb', line 72

def verify!(auth)
  long_poll!(session_id: auth['session_id'], doc: auth['doc'])

  ActiveSupport::HashWithIndifferentAccess.new(
    personal_code: personal_code,
    first_name: first_name,
    last_name: last_name,
    phone: auth['phone'],
    phone_calling_code: auth['phone_calling_code'],
    auth_provider: 'mobileid' # User::MOBILEID
  )
end