yoti 1.1.0 → 1.2.0

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
  SHA1:
3
- metadata.gz: 687ddf7f2ce726749774b2cbbd5bbe97419d9df5
4
- data.tar.gz: 8f8cdefad48fd070ac6c0dbe7fc5994f4a8878fb
3
+ metadata.gz: db62b520742b6807cac9c0813675327f9dec1bf9
4
+ data.tar.gz: fb2006107a34a2b9eed606ddc63ed61062ec8d96
5
5
  SHA512:
6
- metadata.gz: 603439330c7f7298590d4d3b1f1a8b7bdd6ec6756876729ac5fb9e02522bfe141cbfc12e7dc7afda4ffb5283771036e63127ddb8a9c89ef5324c2394df08ab32
7
- data.tar.gz: 2cd356bf349ae241461f949f3214fe698a84aebfbc871fd7bcb76d0e75c2381bdff7a83ec358c548b1e00dea794fb4bc700bc28f14fb02d162f3850011d5379c
6
+ metadata.gz: af3eebba165eaf25a7ab88a6a07a32de685a2f8ed522a3808519287955100127ef08dbc840856c849c1e25bbf3443a6aad64aa008edc4b29b21230dab5c1ecc2
7
+ data.tar.gz: ba85c6be0f0978ebcb0209835fd0a4564cf9458b54f88173242705df7a3278b3c4c99bb37b858fb306edc49b998af9c89e809535d98c24cab0eabb8ab6306309
data/.gitignore CHANGED
@@ -35,3 +35,5 @@ Gemfile.lock
35
35
 
36
36
  # Ignore Yardstick measurement files
37
37
  /measurement
38
+ examples/rails/public/*.jpeg
39
+ examples/sinatra/public/*.jpeg
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
+ ## 1.2.0 - 2018-02-28
8
+ ### Added
9
+ - AML (Anti Money Laundering) check service
10
+
7
11
  ## 1.1.0 - 2017-10-24
8
12
  ### Changed
9
13
  - `user_profile['selfie']` will return image data instead of an image URI
@@ -4,11 +4,10 @@ After checking out the repo, run `bundle install` to install dependencies. Then,
4
4
 
5
5
  You can use [Guard][] to automatically run the tests every time a file in the `lib` or `spec` folder changes.
6
6
 
7
-
8
7
  Run Guard through Bundler with:
9
8
 
10
9
  ```shell
11
- $ bundle exec guard
10
+ bundle exec guard
12
11
  ```
13
12
 
14
13
  [Guard]: https://github.com/guard/guard
@@ -22,12 +21,13 @@ If you wish to compile `.proto` definitions to Ruby, you will need to install [G
22
21
  ### OSX
23
22
 
24
23
  ```shell
25
- $ brew install protobuf
24
+ brew install protobuf
26
25
  ```
27
26
 
28
27
  ### Ubuntu
28
+
29
29
  ```shell
30
- $ sudo apt-get install -y protobuf
30
+ sudo apt-get install -y protobuf
31
31
  ```
32
32
 
33
33
  This gem relies heavily on the [Ruby Protobuf][] gem. For more information on how Google Protobuf works, please see the [Wiki pages][].
@@ -35,9 +35,9 @@ This gem relies heavily on the [Ruby Protobuf][] gem. For more information on ho
35
35
  Compiling the common and attribute `.proto` definitions can be done with the following commands:
36
36
 
37
37
  ```shell
38
- $ cd lib/yoti/protobuf/v1
39
- $ protoc -I definitions/attribute-public-api/attrpubapi_v1 --ruby_out ./attribute_public_api definitions/attribute-public-api/attrpubapi_v1/*.proto
40
- $ protoc -I definitions/common-public-api/compubapi_v1/ --ruby_out ./common_public_api definitions/common-public-api/compubapi_v1/*.proto
38
+ cd lib/yoti/protobuf/v1
39
+ protoc -I definitions/attribute-public-api/attrpubapi_v1 --ruby_out ./attribute_public_api definitions/attribute-public-api/attrpubapi_v1/*.proto
40
+ protoc -I definitions/common-public-api/compubapi_v1/ --ruby_out ./common_public_api definitions/common-public-api/compubapi_v1/*.proto
41
41
  ```
42
42
 
43
43
  These commands will overwrite the current protobuf Ruby modules, which have been modified. If the protobuf files have to be updated, a good idea would be to change them manually, or generate the files in a new location, and compare the content.
@@ -53,30 +53,33 @@ The 100% code coverage requirement must be met before submitting new code.
53
53
  This can be checked by opening the generated [SimpleCov][] files:
54
54
 
55
55
  ```shell
56
- $ open coverage/index.html
56
+ open coverage/index.html
57
57
  ```
58
58
 
59
59
  ### Style guide
60
+
60
61
  The Ruby style guide is configured in the [rubocop.yml](rubocop.yml) file and can be checked by running:
61
62
 
62
63
  ```shell
63
- $ bundle exec rake rubocop
64
+ bundle exec rake rubocop
64
65
  ```
65
66
 
66
67
  ### Documentation
68
+
67
69
  The documentation uses the [Yard][] format. Please ensure all new classes and methods are fully documented.
68
70
 
69
71
  There are a few Rake tasks to handle documentation:
70
72
 
71
73
  ```shell
72
- $ bundle exec rake measurement
74
+ bundle exec rake measurement
73
75
  ```
74
76
 
75
77
  Verifies the documentation with [Yardstick][] and generates the `measurement/report.txt` file, containing tips on how to improve the documentation coverage.
76
78
 
77
79
  ```shell
78
- $ bundle exec rake yard
80
+ bundle exec rake yard
79
81
  ```
82
+
80
83
  Generates [YARD][] documentation in the doc folder.
81
84
 
82
85
  ### Git
@@ -106,6 +109,7 @@ gem push pkg/yoti-[version].gem
106
109
  ```
107
110
 
108
111
  ## Submitting a pull request
112
+
109
113
  1. [Fork the repository.][fork]
110
114
  2. [Create a topic branch.][branch]
111
115
  3. Add specs for your unimplemented feature or bug fix.
data/README.md CHANGED
@@ -4,42 +4,15 @@ Welcome to the Yoti Ruby SDK. This repository contains the tools you need to qui
4
4
 
5
5
  ## Table of Contents
6
6
 
7
- 1) [An Architectural view](#an-architectural-view) -
8
- High level overview of integration
9
-
10
- 2) [References](#references)-
11
- Guides before you start
12
-
13
- 3) [Requirements](#requirements)-
14
- Everything you need to get started
15
-
16
- 4) [Installing the SDK](#installing-the-sdk)-
17
- How to install our SDK
18
-
19
- 5) [SDK Project import](#sdk-project-import)-
20
- How to install the SDK to your project
21
-
22
- 6) [Configuration](#configuration)-
23
- entry point explanation
24
-
25
- 7) [Profile Retrieval](#profile-retrieval)-
26
- How to retrieve a Yoti profile using the token
27
-
28
- 8) [Handling users](#handling-users)-
29
- How to manage users
30
-
31
- 9) [API Coverage](#api-coverage)-
32
- Attributes defined
33
-
34
- 10) [Running the examples](running-the-examples)-
35
- Attributes defined
36
-
37
- 11) [Support](#support)-
38
- Please feel free to reach out
39
-
40
- 12) [Change Log](#change-log)
41
-
42
- 13) [License](#license)
7
+ 1. [An Architectural view](#an-architectural-view) - High level overview of integration
8
+ 1. [Requirements](#requirements) - Everything you need to get started
9
+ 1. [Installing the SDK](#installing-the-sdk) - How to install our SDK
10
+ 1. [Configuration](#configuration) - Configuring the SDK
11
+ 1. [Profile Retrieval](#profile-retrieval) - How to retrieve a Yoti profile using the token
12
+ 1. [AML Integration](#aml-integration) - How to integrate with Yoti's AML (Anti Money Laundering) service
13
+ 1. [Running the Examples](#running-the-examples) - How to run the example projects provided
14
+ 1. [API Coverage](#api-coverage) - Attributes defined
15
+ 1. [Support](#support) - Please feel free to reach out
43
16
 
44
17
  ## An Architectural view
45
18
 
@@ -51,7 +24,6 @@ Yoti SDK carries out for you steps 6, 7, 8 and the profile decryption in step 9.
51
24
 
52
25
  ![alt text](login_flow.png "Login flow")
53
26
 
54
-
55
27
  Yoti also allows you to enable user details verification from your mobile app by means of the Android (TBA) and iOS (TBA) SDKs. In that scenario, your Yoti-enabled mobile app is playing both the role of the browser and the Yoti app. Your back-end doesn't need to handle these cases in a significantly different way, but you might decide to handle the `User-Agent` header in order to provide different responses for desktop and mobile clients.
56
28
 
57
29
  ## References
@@ -92,21 +64,21 @@ gem 'yoti'
92
64
  And then execute:
93
65
 
94
66
  ```shell
95
- $ bundle install
67
+ bundle install
96
68
  ```
97
69
 
98
70
  Or simply run the following command from your terminal:
99
71
 
100
72
  ```shell
101
- $ [sudo] gem install yoti
73
+ [sudo] gem install yoti
102
74
  ```
103
75
 
104
- ## SDK Project import
76
+ ## SDK Project Import
105
77
 
106
78
  The gem provides a generator for the initialization file:
107
79
 
108
80
  ```shell
109
- $ rails generate yoti:install
81
+ rails generate yoti:install
110
82
  ```
111
83
 
112
84
  The generated initialisation file can be found in `config/initializers/yoti.rb`.
@@ -121,6 +93,7 @@ Yoti.configure do |config|
121
93
  config.key_file_path = ENV['YOTI_KEY_FILE_PATH']
122
94
  end
123
95
  ```
96
+
124
97
  Make sure the following environment variables can be accessed by your app:
125
98
 
126
99
  `YOTI_CLIENT_SDK_ID` - found on the Key settings page on your application dashboard
@@ -129,12 +102,12 @@ Make sure the following environment variables can be accessed by your app:
129
102
 
130
103
  The following options are available:
131
104
 
132
- Config | Required | Default | Note
133
- ---------------------|----------|----------------------|-----
134
- `client_sdk_id` | Yes | | SDK identifier generated by when you publish your app
135
- `key_file_path` | Yes | | Path to the pem file generated when you create your app
136
- `api_url` | No | https://api.yoti.com | Path to Yoti URL used for debugging purposes
137
- `api_port` | No | 443 | Path to Yoti port used for debugging purposes
105
+ Config | Required | Default | Note
106
+ ---------------------|----------|------------------------|-----
107
+ `client_sdk_id` | Yes | | SDK identifier generated by when you publish your app
108
+ `key_file_path` | Yes | | Path to the pem file generated when you create your app
109
+ `api_url` | No | `https://api.yoti.com` | Path to Yoti URL used for debugging purposes
110
+ `api_port` | No | 443 | Path to Yoti port used for debugging purposes
138
111
 
139
112
  Keeping your settings and access keys outside your repository is highly recommended. You can use gems like [dotenv][] to manage environment variables more easily.
140
113
 
@@ -155,11 +128,7 @@ Yoti.configure do |config|
155
128
  end
156
129
  ```
157
130
 
158
- Where `YOTI_KEY` is an environment variable with the following format:
159
-
160
- ```
161
- YOTI_KEY="-----BEGIN RSA PRIVATE KEY-----\nMIIEp..."
162
- ```
131
+ Where `YOTI_KEY` is an environment variable with the following format: `YOTI_KEY="-----BEGIN RSA PRIVATE KEY-----\nMIIEp..."`
163
132
 
164
133
  An easier way of setting this on Heroku would be to use the [Heroku Command Line][]
165
134
 
@@ -169,9 +138,7 @@ heroku config:add YOTI_KEY ="$(cat your-access-security.pem)"
169
138
 
170
139
  [Heroku Command Line]: https://devcenter.heroku.com/articles/heroku-command-line
171
140
 
172
-
173
-
174
- ## Profile retrieval
141
+ ## Profile Retrieval
175
142
 
176
143
  When your application receives a token via the exposed endpoint (it will be assigned to a query string parameter named `token`), you can easily retrieve the user profile:
177
144
 
@@ -189,11 +156,14 @@ else
189
156
  end
190
157
  ```
191
158
 
192
- The `user_profile ` object provides a set of attributes corresponding to user attributes. Whether the attributes are present or not depends on the settings you have applied to your app on Yoti Dashboard.
159
+ The `user_profile` object provides a set of attributes corresponding to user attributes. Whether the attributes are present or not depends on the settings you have applied to your app on Yoti Dashboard.
193
160
 
194
- ### Handling users
161
+ ### Handling Users
195
162
 
196
- When you retrieve the user profile, you receive a user ID generated by Yoti exclusively for your application. This means that if the same individual logs into another app, Yoti will assign them a different id. You can use such id to verify whether the retrieved profile identifies a new or an existing user. Here is an example of how this works:
163
+ When you retrieve the user profile, you receive a user ID generated by Yoti exclusively for your application.
164
+ This means that if the same individual logs into another app, Yoti will assign her/him a different ID.
165
+ You can use this ID to verify whether (for your application) the retrieved profile identifies a new or an existing user.
166
+ Here is an example of how this works:
197
167
 
198
168
  ```ruby
199
169
  if yoti_activity_details.outcome == 'SUCCESS'
@@ -209,9 +179,54 @@ else
209
179
  end
210
180
  ```
211
181
 
212
- Where `your_user_search_function` is a piece of logic in your app that is supposed to find a user, given a user_id. Regardless of wether the user is a new or an existing one, Yoti will always provide their profile, so you don't necessarily need to store it.
182
+ Where `your_user_search_function` is a piece of logic in your app that is supposed to find a user, given a user_id. Regardless of whether the user is a new or an existing one, Yoti will always provide their profile, so you don't necessarily need to store it.
183
+
184
+ ## AML Integration
185
+
186
+ Yoti provides an AML (Anti Money Laundering) check service to allow a deeper KYC process to prevent fraud. This is a chargeable service, so please contact [sdksupport@yoti.com](mailto:sdksupport@yoti.com) for more information.
187
+
188
+ Yoti will provide a boolean result on the following checks:
189
+
190
+ * PEP list - Verify against Politically Exposed Persons list
191
+ * Fraud list - Verify against US Social Security Administration Fraud (SSN Fraud) list
192
+ * Watch list - Verify against watch lists from the Office of Foreign Assets Control
193
+
194
+ To use this functionality you must ensure your application is assigned to your Organisation in the Yoti Dashboard - please see here for further information.
213
195
 
214
- ## Running the examples
196
+ For the AML check you will need to provide the following:
197
+
198
+ * Data provided by Yoti (please ensure you have selected the Given name(s) and Family name attributes from the Data tab in the Yoti Dashboard)
199
+ * Given name(s)
200
+ * Family name
201
+ * Data that must be collected from the user:
202
+ * Country of residence (must be an ISO 3166 3-letter code)
203
+ * Social Security Number (US citizens only)
204
+ * Postcode/Zip code (US citizens only)
205
+
206
+ ### Consent
207
+
208
+ Performing an AML check on a person *requires* their consent.
209
+ **You must ensure you have user consent *before* using this service.**
210
+
211
+ ### Code Example
212
+
213
+ Given a YotiClient initialised with your SDK ID and KeyPair (see [Client Initialisation](#client-initialisation)) performing an AML check is a straightforward case of providing basic profile data.
214
+
215
+ ```ruby
216
+ require 'yoti'
217
+
218
+ Yoti.configure do |config|
219
+ config.client_sdk_id = ENV['YOTI_CLIENT_SDK_ID']
220
+ config.key_file_path = ENV['YOTI_KEY_FILE_PATH']
221
+ end
222
+
223
+ aml_address = Yoti::AmlAddress.new('GBR')
224
+ aml_profile = Yoti::AmlProfile.new('Edward Richard George', 'Heath', aml_address)
225
+
226
+ puts Yoti::Client.aml_check(aml_profile)
227
+ ```
228
+
229
+ ## Running the Examples
215
230
 
216
231
  The examples can be found in the [examples folder](examples).
217
232
  For them to work you will need a working callback URL that your browser can redirect to. The callback URL for both examples will be: `http://your-local-url.domain/profile`.
@@ -230,43 +245,42 @@ Visiting the `http://your-local-url.domain` should show a Yoti Connect button
230
245
 
231
246
  * rename the [.env.default](examples/sinatra/.env.default) file to `.env` and fill in the required configuration values
232
247
  * install the dependencies with `bundle install`
233
- * start the server `dotenv ./app.rb`
248
+ * start the server `ruby ./app.rb`
234
249
 
235
250
  Visiting the `http://your-local-url.domain` should show a Yoti Connect button
236
251
 
237
- ## API coverage
252
+ ### AML Check
253
+
254
+ * rename the [.env.default](examples/aml_check/.env.default) file to `.env` and fill in the required configuration values
255
+ * install the dependencies with `bundle install`
256
+ * run the script with `ruby ./app.rb`
257
+
258
+ ## API Coverage
238
259
 
239
260
  * Activity Details
240
- * [X] User ID `user_id`
241
- * [X] Profile
242
- * [X] Selfie `selfie`
243
- * [X] Given Names `given_names`
244
- * [X] Family Name `family_name`
245
- * [X] Mobile Number `phone_number`
246
- * [X] Email address `email_address`
247
- * [X] Date of Birth `date_of_birth`
248
- * [X] Address `postal_address`
249
- * [X] Gender `gender`
250
- * [X] Nationality `nationality`
251
- * [X] Base64 Selfie URI `base64_selfie_uri`
261
+ * [X] User ID `user_id`
262
+ * [X] Profile
263
+ * [X] Selfie `selfie`
264
+ * [X] Full Name `full_name`
265
+ * [X] Given Names `given_names`
266
+ * [X] Family Name `family_name`
267
+ * [X] Mobile Number `phone_number`
268
+ * [X] Email Address `email_address`
269
+ * [X] Age / Date of Birth `date_of_birth`
270
+ * [X] Age / Verify Condition `age_[over|under]:[1-999]`
271
+ * [X] Address `postal_address`
272
+ * [X] Gender `gender`
273
+ * [X] Nationality `nationality`
274
+ * [X] Base64 Selfie URI `base64_selfie_uri`
252
275
 
253
276
  ## Support
254
277
 
255
278
  For any questions or support please email [sdksupport@yoti.com](mailto:sdksupport@yoti.com).
256
- Please provide the following the get you up and working as quick as possible:
257
-
258
- - Computer Type
259
- - OS Version
260
- - Version of Ruby being used
261
- - Screenshot
262
-
263
-
264
- ## Changelog
265
-
266
- See recent changes in the [release notes][release notes] or the [changelog](CHANGELOG.md).
267
-
268
- [release notes]: https://github.com/getyoti/yoti-ruby-sdk/releases
279
+ Please provide the following to get you up and working as quickly as possible:
269
280
 
270
- ## License
281
+ * Computer type
282
+ * OS version
283
+ * Version of Ruby being used
284
+ * Screenshot
271
285
 
272
- The gem is available under the following [terms](LICENSE.txt).
286
+ Once we have answered your question we may contact you again to discuss Yoti products and services. If you’d prefer us not to do this, please let us know when you e-mail.
@@ -2,7 +2,15 @@ require_relative 'yoti/version'
2
2
  require_relative 'yoti/configuration'
3
3
  require_relative 'yoti/errors'
4
4
  require_relative 'yoti/ssl'
5
- require_relative 'yoti/request'
5
+
6
+ require_relative 'yoti/http/payloads/aml_address'
7
+ require_relative 'yoti/http/payloads/aml_profile'
8
+ require_relative 'yoti/http/aml_check_request'
9
+
10
+ require_relative 'yoti/http/signed_request'
11
+ require_relative 'yoti/http/profile_request'
12
+ require_relative 'yoti/http/request'
13
+
6
14
  require_relative 'yoti/activity_details'
7
15
  require_relative 'yoti/client'
8
16
  require_relative 'yoti/protobuf/v1/protobuf'
@@ -6,7 +6,7 @@ module Yoti
6
6
  # @param encrypted_connect_token [String] token provided as a base 64 string
7
7
  # @return [Object] an ActivityDetails instance encapsulating the user profile
8
8
  def self.get_activity_details(encrypted_connect_token)
9
- receipt = Yoti::Request.new(encrypted_connect_token).receipt
9
+ receipt = Yoti::ProfileRequest.new(encrypted_connect_token).receipt
10
10
  encrypted_data = Protobuf.current_user(receipt)
11
11
 
12
12
  return ActivityDetails.new(receipt) if encrypted_data.nil?
@@ -16,5 +16,9 @@ module Yoti
16
16
  decrypted_profile = Protobuf.attribute_list(decrypted_data)
17
17
  ActivityDetails.new(receipt, decrypted_profile)
18
18
  end
19
+
20
+ def self.aml_check(aml_profile)
21
+ Yoti::AmlCheckRequest.new(aml_profile).response
22
+ end
19
23
  end
20
24
  end
@@ -1,7 +1,7 @@
1
1
  module Yoti
2
2
  class Configuration
3
3
  attr_accessor :client_sdk_id, :key_file_path, :key, :sdk_identifier,
4
- :api_url, :api_port, :api_version, :api_endpoint
4
+ :api_url, :api_port, :api_version
5
5
 
6
6
  # Set config variables by using a configuration block
7
7
  def initialize
@@ -10,4 +10,7 @@ module Yoti
10
10
 
11
11
  # Raises exceptions realted to an incorrect gem configuration value
12
12
  class ConfigurationError < StandardError; end
13
+
14
+ # Raises exceptions related to AML actions
15
+ class AmlError < StandardError; end
13
16
  end
@@ -0,0 +1,25 @@
1
+ module Yoti
2
+ # Manage the API's AML check requests
3
+ class AmlCheckRequest
4
+ def initialize(aml_profile)
5
+ @aml_profile = aml_profile
6
+ @payload = aml_profile.payload
7
+ @request = request
8
+ end
9
+
10
+ # @return [String] a JSON representation of the AML check response
11
+ def response
12
+ JSON.parse(@request.body)
13
+ end
14
+
15
+ private
16
+
17
+ def request
18
+ yoti_request = Yoti::Request.new
19
+ yoti_request.http_method = 'POST'
20
+ yoti_request.endpoint = 'aml-check'
21
+ yoti_request.payload = @payload
22
+ yoti_request
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,17 @@
1
+ module Yoti
2
+ # Manages the AML check Address object
3
+ class AmlAddress
4
+ # @return [String] the country of residence in a ISO 3166 3-letter code format
5
+ attr_accessor :country
6
+
7
+ # @return [String] the postcode required for USA, optional otherwise
8
+ attr_accessor :post_code
9
+
10
+ def initialize(country, post_code = nil)
11
+ raise AmlError, 'AmlAddress requires a country.' if country.to_s.empty?
12
+
13
+ @country = country
14
+ @post_code = post_code
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,41 @@
1
+ module Yoti
2
+ # Manages the AML check Profile object
3
+ class AmlProfile
4
+ def initialize(given_names, family_name, aml_address, ssn = nil)
5
+ @given_names = given_names
6
+ @family_name = family_name
7
+ @ssn = ssn
8
+ @address = aml_address
9
+
10
+ raise AmlError, 'The AML request requires given names, family name and an ISO 3166 3-letter code.' if profile_invalid
11
+ raise AmlError, 'Request for USA require a valid SSN and postcode.' if usa_invalid
12
+ end
13
+
14
+ # @return [Object] the AML check request body
15
+ def payload
16
+ {
17
+ given_names: @given_names,
18
+ family_name: @family_name,
19
+ ssn: @ssn,
20
+ address: {
21
+ country: @address.country,
22
+ post_code: @address.post_code
23
+ }
24
+ }
25
+ end
26
+
27
+ private
28
+
29
+ def profile_invalid
30
+ @given_names.to_s.empty? || @family_name.to_s.empty? || address_invalid
31
+ end
32
+
33
+ def address_invalid
34
+ !@address.is_a?(AmlAddress) || @address.country.to_s.length != 3
35
+ end
36
+
37
+ def usa_invalid
38
+ @address.country == 'USA' && (@ssn.to_s.empty? || @address.post_code.to_s.empty?)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,24 @@
1
+ module Yoti
2
+ # Manage the API's profile requests
3
+ class ProfileRequest
4
+ def initialize(encrypted_connect_token)
5
+ @encrypted_connect_token = encrypted_connect_token
6
+ @request = request
7
+ end
8
+
9
+ # @return [String] a JSON representation of the profile response receipt
10
+ def receipt
11
+ JSON.parse(@request.body)['receipt']
12
+ end
13
+
14
+ private
15
+
16
+ def request
17
+ yoti_request = Yoti::Request.new
18
+ yoti_request.encrypted_connect_token = @encrypted_connect_token
19
+ yoti_request.http_method = 'GET'
20
+ yoti_request.endpoint = 'profile'
21
+ yoti_request
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,81 @@
1
+ module Yoti
2
+ # Manage the API's HTTPS requests
3
+ class Request
4
+ # @return [String] the URL token received from Yoti Connect
5
+ attr_accessor :encrypted_connect_token
6
+
7
+ # @return [String] the HTTP method used for the request
8
+ # The allowed methods are: GET, DELETE, POST, PUT, PATCH
9
+ attr_accessor :http_method
10
+
11
+ # @return [String] the API endpoint for the request
12
+ attr_accessor :endpoint
13
+
14
+ # @return [Hash] the body sent with the request
15
+ attr_accessor :payload
16
+
17
+ # Makes a HTTP request after signing the headers
18
+ # @return [Hash] the body from the HTTP request
19
+ def body
20
+ raise RequestError, 'The request requires a HTTP method.' unless @http_method
21
+ raise RequestError, 'The payload needs to be a hash.' unless @payload.to_s.empty? || @payload.is_a?(Hash)
22
+
23
+ res = Net::HTTP.start(uri.hostname, Yoti.configuration.api_port, use_ssl: https_uri?) do |http|
24
+ signed_request = SignedRequest.new(unsigned_request, path, @payload).sign
25
+ http.request(signed_request)
26
+ end
27
+
28
+ raise RequestError, "Unsuccessful Yoti API call: #{res.message}" unless res.code == '200'
29
+ res.body
30
+ end
31
+
32
+ private
33
+
34
+ def unsigned_request
35
+ case @http_method
36
+ when 'GET'
37
+ http_req = Net::HTTP::Get.new(uri)
38
+ when 'DELETE'
39
+ http_req = Net::HTTP::Delete.new(uri)
40
+ when 'POST'
41
+ http_req = Net::HTTP::Post.new(uri)
42
+ http_req.body = @payload.to_json unless @payload.to_s.empty?
43
+ when 'PUT'
44
+ http_req = Net::HTTP::Put.new(uri)
45
+ http_req.body = @payload.to_json unless @payload.to_s.empty?
46
+ when 'PATCH'
47
+ http_req = Net::HTTP::Patch.new(uri)
48
+ http_req.body = @payload.to_json unless @payload.to_s.empty?
49
+ else
50
+ raise RequestError, "Request method not allowed: #{@http_method}"
51
+ end
52
+
53
+ http_req
54
+ end
55
+
56
+ def uri
57
+ @uri ||= URI(Yoti.configuration.api_endpoint + path)
58
+ end
59
+
60
+ def path
61
+ @path ||= begin
62
+ nonce = SecureRandom.uuid
63
+ timestamp = Time.now.to_i
64
+
65
+ "/#{@endpoint}/#{token}"\
66
+ "?nonce=#{nonce}"\
67
+ "&timestamp=#{timestamp}"\
68
+ "&appId=#{Yoti.configuration.client_sdk_id}"
69
+ end
70
+ end
71
+
72
+ def token
73
+ return '' unless @encrypted_connect_token
74
+ Yoti::SSL.decrypt_token(@encrypted_connect_token)
75
+ end
76
+
77
+ def https_uri?
78
+ uri.scheme == 'https'
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,39 @@
1
+ require 'base64'
2
+
3
+ module Yoti
4
+ # Converts a basic Net::HTTP request into a Yoti Signed Request
5
+ class SignedRequest
6
+ def initialize(unsigned_request, path, payload = {})
7
+ @http_req = unsigned_request
8
+ @path = path
9
+ @payload = payload
10
+ @auth_key = Yoti::SSL.auth_key_from_pem
11
+ end
12
+
13
+ def sign
14
+ @http_req['X-Yoti-Auth-Key'] = @auth_key
15
+ @http_req['X-Yoti-Auth-Digest'] = message_signature
16
+ @http_req['X-Yoti-SDK'] = Yoti.configuration.sdk_identifier
17
+ @http_req['Content-Type'] = 'application/json'
18
+ @http_req['Accept'] = 'application/json'
19
+ @http_req
20
+ end
21
+
22
+ private
23
+
24
+ def message_signature
25
+ @message_signature ||= Yoti::SSL.get_secure_signature("#{http_method}&#{@path}#{payload_string}")
26
+ end
27
+
28
+ def http_method
29
+ @http_req.method
30
+ end
31
+
32
+ # Create the base64 encoded request body
33
+ def payload_string
34
+ return '' unless @payload
35
+
36
+ '&' + Base64.strict_encode64(@payload.to_json)
37
+ end
38
+ end
39
+ end
@@ -26,7 +26,7 @@ module Yoti
26
26
 
27
27
  begin
28
28
  private_key.private_decrypt(Base64.urlsafe_decode64(encrypted_connect_token))
29
- rescue => error
29
+ rescue StandardError => error
30
30
  raise SslError, "Could not decrypt token. #{error}"
31
31
  end
32
32
  end
@@ -63,7 +63,7 @@ module Yoti
63
63
 
64
64
  def private_key
65
65
  @private_key ||= OpenSSL::PKey::RSA.new(pem)
66
- rescue => error
66
+ rescue StandardError => error
67
67
  raise SslError, "The secure key is invalid. #{error}"
68
68
  end
69
69
  end
@@ -1,4 +1,4 @@
1
1
  module Yoti
2
2
  # @return [String] the gem's current version
3
- VERSION = '1.1.0'.freeze
3
+ VERSION = '1.2.0'.freeze
4
4
  end
@@ -1,12 +1,12 @@
1
1
  AllCops:
2
2
  DisplayCopNames: true
3
3
  DisplayStyleGuide: true
4
- TargetRubyVersion: 2.4
4
+ TargetRubyVersion: 2.1
5
5
  Exclude:
6
6
  - 'examples/rails/config/**/*'
7
7
 
8
8
  Metrics/AbcSize:
9
- Max: 15
9
+ Max: 23
10
10
  Exclude:
11
11
  - examples/rails/app/controllers/yoti_controller.rb
12
12
 
@@ -14,14 +14,15 @@ Metrics/BlockLength:
14
14
  Exclude:
15
15
  - spec/**/**/*.rb
16
16
 
17
+ Metrics/CyclomaticComplexity:
18
+ Max: 9
19
+
17
20
  Metrics/LineLength:
18
21
  Enabled: false
19
22
 
20
23
  Metrics/MethodLength:
21
24
  CountComments: false
22
- Max: 15
23
- Exclude:
24
- - examples/rails/app/controllers/yoti_controller.rb
25
+ Max: 19
25
26
 
26
27
  Style/Documentation:
27
28
  Enabled: false
@@ -1,5 +1,3 @@
1
- # coding: utf-8
2
-
3
1
  lib = File.expand_path('../lib', __FILE__)
4
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
3
  require 'yoti/version'
@@ -11,11 +9,11 @@ Gem::Specification.new do |spec|
11
9
  spec.email = ['tech@yoti.com']
12
10
 
13
11
  spec.summary = 'Yoti Ruby SDK for back-end integration.'
14
- spec.description = <<-EOF
12
+ spec.description = <<-DESC
15
13
  This gem contains the tools you need to quickly integrate your Ruby back-end
16
14
  with Yoti, so that your users can share their identity details with your
17
15
  application in a secure and trusted way.
18
- EOF
16
+ DESC
19
17
 
20
18
  spec.homepage = 'https://github.com/getyoti/yoti-ruby-sdk'
21
19
  spec.license = 'MIT'
@@ -33,7 +31,7 @@ Gem::Specification.new do |spec|
33
31
  spec.add_development_dependency 'rake', '~> 12.0'
34
32
  spec.add_development_dependency 'rspec', '~> 3.5'
35
33
  spec.add_development_dependency 'simplecov', '~> 0.13'
36
- spec.add_development_dependency 'webmock', '~> 2.3'
34
+ spec.add_development_dependency 'webmock', '~> 3.3'
37
35
  spec.add_development_dependency 'yard', '~> 0.9'
38
36
  spec.add_development_dependency 'yardstick', '~> 0.9'
39
37
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yoti
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastian Zaremba
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-24 00:00:00.000000000 Z
11
+ date: 2018-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: protobuf
@@ -114,14 +114,14 @@ dependencies:
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '2.3'
117
+ version: '3.3'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '2.3'
124
+ version: '3.3'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: yard
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -175,6 +175,12 @@ files:
175
175
  - lib/yoti/client.rb
176
176
  - lib/yoti/configuration.rb
177
177
  - lib/yoti/errors.rb
178
+ - lib/yoti/http/aml_check_request.rb
179
+ - lib/yoti/http/payloads/aml_address.rb
180
+ - lib/yoti/http/payloads/aml_profile.rb
181
+ - lib/yoti/http/profile_request.rb
182
+ - lib/yoti/http/request.rb
183
+ - lib/yoti/http/signed_request.rb
178
184
  - lib/yoti/protobuf/v1/attribute_public_api/attribute.pb.rb
179
185
  - lib/yoti/protobuf/v1/attribute_public_api/list.pb.rb
180
186
  - lib/yoti/protobuf/v1/attribute_public_api/signing.pb.rb
@@ -184,7 +190,6 @@ files:
184
190
  - lib/yoti/protobuf/v1/definitions/attribute-public-api/attrpubapi_v1/signing.proto
185
191
  - lib/yoti/protobuf/v1/definitions/common-public-api/compubapi_v1/encrypted_data.proto
186
192
  - lib/yoti/protobuf/v1/protobuf.rb
187
- - lib/yoti/request.rb
188
193
  - lib/yoti/ssl.rb
189
194
  - lib/yoti/version.rb
190
195
  - login_flow.png
@@ -1,59 +0,0 @@
1
- module Yoti
2
- # Manage the API's HTTPS requests
3
- class Request
4
- def initialize(encrypted_connect_token)
5
- @encrypted_connect_token = encrypted_connect_token
6
- @auth_key = Yoti::SSL.auth_key_from_pem
7
- end
8
-
9
- # @return [Hash] the receipt key from the request hash response
10
- def receipt
11
- request['receipt']
12
- end
13
-
14
- private
15
-
16
- def request
17
- res = Net::HTTP.start(uri.hostname, Yoti.configuration.api_port, use_ssl: https_uri?) do |http|
18
- http.request(req)
19
- end
20
-
21
- raise RequestError, "Unsuccessful Yoti API call: #{res.message}" unless res.code == '200'
22
- JSON.parse(res.body)
23
- end
24
-
25
- def req
26
- http_req = Net::HTTP::Get.new(uri)
27
- http_req['X-Yoti-Auth-Key'] = @auth_key
28
- http_req['X-Yoti-Auth-Digest'] = message_signature
29
- http_req['X-Yoti-SDK'] = @sdk_identifier
30
- http_req['Content-Type'] = 'application/json'
31
- http_req['Accept'] = 'application/json'
32
- http_req
33
- end
34
-
35
- def message_signature
36
- @message_signature ||= Yoti::SSL.get_secure_signature("GET&#{path}")
37
- end
38
-
39
- def uri
40
- @uri ||= URI(Yoti.configuration.api_endpoint + path)
41
- end
42
-
43
- def path
44
- @path ||= begin
45
- nonce = SecureRandom.uuid
46
- timestamp = Time.now.to_i
47
- "/profile/#{token}?nonce=#{nonce}&timestamp=#{timestamp}&appId=#{Yoti.configuration.client_sdk_id}"
48
- end
49
- end
50
-
51
- def token
52
- @token ||= Yoti::SSL.decrypt_token(@encrypted_connect_token)
53
- end
54
-
55
- def https_uri?
56
- uri.scheme == 'https'
57
- end
58
- end
59
- end