simplicity_client 0.1.2 → 0.2.0
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 +4 -4
- data/lib/simplicity_client.rb +147 -33
- metadata +25 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 35ccb4c05970e3765687119f1761b0c1ff47965ab6311f5e86e5fb321b8e87fd
|
4
|
+
data.tar.gz: dfc4d51cf8d179a2901c62aaa576828193ddf6ef87a9aba6793da75da6825737
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ef0ea4b00d2ae9ae5deaaf317759fe595e7221fbfe46175c48747355e388ab4faaf4f0b272ccd6c57ec7c11fc7f06037dd35b6f9e76998c8258d36a6c406dfb
|
7
|
+
data.tar.gz: 6c7618d98c48fc47adfa19931cb68a1fe67d612cc17e1e51c0a6cfdd7d708cffedf7dffd3ff96e425a890990c2b56d629541184edb033de49e2634d49f1e5be4
|
data/lib/simplicity_client.rb
CHANGED
@@ -9,29 +9,45 @@ require "faraday"
|
|
9
9
|
require "faraday-cookie_jar"
|
10
10
|
require "faraday/follow_redirects"
|
11
11
|
require "aws-sdk-cognitoidentityprovider"
|
12
|
-
require "aws-cognito-srp"
|
13
12
|
require "aws-sdk-cognitoidentity"
|
14
13
|
require "aws-sigv4"
|
14
|
+
require_relative "fido2_client"
|
15
15
|
|
16
16
|
module SimplicityClient
|
17
|
+
Params = Struct.new(:email, :credentialId, :keyAlgorithm, :keyCurve, :keyValue, :userHandle, keyword_init: true)
|
18
|
+
ParamDefinition = Struct.new(:name, :label, :primary_id)
|
19
|
+
|
17
20
|
class Error < StandardError; end
|
18
21
|
|
22
|
+
# For the user interface
|
23
|
+
PARAMS_INFO = [
|
24
|
+
ParamDefinition.new(name: "email", label: "Email address", primary_id: true),
|
25
|
+
ParamDefinition.new(name: "credentialId", label: "Passkey credential ID"),
|
26
|
+
ParamDefinition.new(name: "keyAlgorithm", label: "Passkey key algorithm"),
|
27
|
+
ParamDefinition.new(name: "keyCurve", label: "Passkey key curve"),
|
28
|
+
ParamDefinition.new(name: "keyValue", label: "Passkey value"),
|
29
|
+
ParamDefinition.new(name: "userHandle", label: "Passkey user handle")
|
30
|
+
].freeze
|
31
|
+
|
19
32
|
class Session
|
20
33
|
def initialize
|
21
34
|
@logger = Logger.new $stderr
|
22
|
-
@logger.level = Logger::
|
35
|
+
@logger.level = Logger::DEBUG
|
23
36
|
|
24
37
|
@user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"
|
25
38
|
|
26
39
|
@client = Faraday.new(
|
27
40
|
headers: { "User-Agent" => @user_agent },
|
28
|
-
|
29
|
-
|
30
|
-
|
41
|
+
# proxy: "http://Thinkbook.local:8080",
|
42
|
+
# :ssl => {:verify => false}
|
43
|
+
) do |builder|
|
31
44
|
builder.response :follow_redirects
|
32
|
-
|
45
|
+
builder.response :logger
|
33
46
|
builder.adapter Faraday.default_adapter
|
34
47
|
end
|
48
|
+
|
49
|
+
@authsignal_base = "https://au.api.authsignal.com/v1"
|
50
|
+
@authsignal_tenant_id = "e768822f-b1a1-404c-a685-0e37905ca5f5"
|
35
51
|
end
|
36
52
|
|
37
53
|
# Write the session data out to a string so that the session can be restored later
|
@@ -47,49 +63,76 @@ module SimplicityClient
|
|
47
63
|
@auth_data = json["auth_data"]
|
48
64
|
end
|
49
65
|
|
50
|
-
def login(
|
51
|
-
client = Aws::CognitoIdentityProvider::Client.new(region:
|
66
|
+
def login(params)
|
67
|
+
client = Aws::CognitoIdentityProvider::Client.new(region: "ap-southeast-2")
|
52
68
|
|
53
69
|
user_pool_id = "ap-southeast-2_abAklW6ap"
|
54
70
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
71
|
+
device_id = SecureRandom.uuid
|
72
|
+
passkey = Fido2Client::Passkey.new(params.credentialId, params.keyAlgorithm, params.keyCurve, params.keyValue, params.userHandle)
|
73
|
+
challenge_id = fetch_challenge_id
|
74
|
+
authentication_options = fetch_authentication_options(challenge_id)
|
75
|
+
challenge = authentication_options["options"]["challenge"]
|
76
|
+
assertion = Fido2Client::Client.new.get_assertion(passkey, challenge)
|
77
|
+
passkey_result = present_passkey(challenge_id, assertion, device_id)
|
78
|
+
|
79
|
+
resp = client.initiate_auth(
|
80
|
+
{
|
81
|
+
auth_flow: "CUSTOM_AUTH",
|
82
|
+
auth_parameters: {
|
83
|
+
USERNAME: params.email,
|
84
|
+
},
|
85
|
+
client_metadata: {
|
86
|
+
anonymousId: device_id,
|
87
|
+
},
|
88
|
+
client_id: "kvoiu7unft0c8hqqsa6hkmeu5",
|
89
|
+
},
|
61
90
|
)
|
62
91
|
|
63
|
-
resp =
|
92
|
+
resp = client.respond_to_auth_challenge(
|
93
|
+
{
|
94
|
+
challenge_name: "CUSTOM_CHALLENGE",
|
95
|
+
challenge_responses: {
|
96
|
+
USERNAME: params.email,
|
97
|
+
ANSWER: passkey_result["accessToken"],
|
98
|
+
},
|
99
|
+
client_id: "kvoiu7unft0c8hqqsa6hkmeu5",
|
100
|
+
session: resp.session,
|
101
|
+
},
|
102
|
+
)
|
64
103
|
|
65
|
-
cognito_identity_client = Aws::CognitoIdentity::Client.new(region:
|
104
|
+
cognito_identity_client = Aws::CognitoIdentity::Client.new(region: "ap-southeast-2")
|
66
105
|
|
67
106
|
# Assuming you have the Identity Pool ID and the ID token
|
68
|
-
identity_pool_id =
|
69
|
-
id_token = resp.id_token
|
107
|
+
identity_pool_id = "ap-southeast-2:0ed33fc6-4cef-4f2e-b634-31c616e108e2"
|
108
|
+
id_token = resp.authentication_result.id_token
|
70
109
|
|
71
110
|
# Get ID from the identity pool
|
72
|
-
id_response = cognito_identity_client.get_id(
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
111
|
+
id_response = cognito_identity_client.get_id(
|
112
|
+
{
|
113
|
+
identity_pool_id: identity_pool_id,
|
114
|
+
logins: {
|
115
|
+
"cognito-idp.ap-southeast-2.amazonaws.com/#{user_pool_id}" => id_token,
|
116
|
+
},
|
117
|
+
},
|
118
|
+
)
|
78
119
|
|
79
120
|
# Get credentials for the ID
|
80
|
-
credentials_response = cognito_identity_client.get_credentials_for_identity(
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
121
|
+
credentials_response = cognito_identity_client.get_credentials_for_identity(
|
122
|
+
{
|
123
|
+
identity_id: id_response.identity_id,
|
124
|
+
logins: {
|
125
|
+
"cognito-idp.ap-southeast-2.amazonaws.com/#{user_pool_id}" => id_token,
|
126
|
+
},
|
127
|
+
},
|
128
|
+
)
|
86
129
|
|
87
130
|
access_key_id = credentials_response.credentials.access_key_id
|
88
131
|
secret_key = credentials_response.credentials.secret_key
|
89
132
|
session_token = credentials_response.credentials.session_token
|
90
133
|
|
91
134
|
@auth_data = {
|
92
|
-
email:
|
135
|
+
email: params.email,
|
93
136
|
access_key_id: access_key_id,
|
94
137
|
secret_key: secret_key,
|
95
138
|
region: "ap-southeast-2",
|
@@ -126,12 +169,12 @@ module SimplicityClient
|
|
126
169
|
signature = signer.sign_request(
|
127
170
|
http_method: http_method,
|
128
171
|
url: url,
|
129
|
-
body: body
|
172
|
+
body: body,
|
130
173
|
)
|
131
174
|
|
132
175
|
response = @client.post(url) do |req|
|
133
176
|
req.headers = signature.headers.merge({
|
134
|
-
|
177
|
+
"Content-Type" => "application/json",
|
135
178
|
})
|
136
179
|
req.body = body
|
137
180
|
end
|
@@ -154,5 +197,76 @@ module SimplicityClient
|
|
154
197
|
raise Error, "Failed to list accounts: #{response.status}, #{response.body}"
|
155
198
|
end
|
156
199
|
end
|
200
|
+
|
201
|
+
private
|
202
|
+
|
203
|
+
def fetch_challenge_id
|
204
|
+
response = @client.post("#{@authsignal_base}/client/challenge") do |req|
|
205
|
+
req.headers = {
|
206
|
+
"Authorization" => "Basic #{Base64.encode64(@authsignal_tenant_id)}",
|
207
|
+
"Content-Type" => "application/json",
|
208
|
+
}
|
209
|
+
req.body = {
|
210
|
+
action: "cognitoAuth",
|
211
|
+
}.to_json
|
212
|
+
end
|
213
|
+
|
214
|
+
if response.success?
|
215
|
+
obj = JSON.parse(response.body)
|
216
|
+
obj["challengeId"]
|
217
|
+
else
|
218
|
+
raise Error, "Failed to get challenge ID: #{response.status}, #{response.body}"
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def fetch_authentication_options(challenge_id)
|
223
|
+
response = @client.post("#{@authsignal_base}/client/user-authenticators/passkey/authentication-options") do |req|
|
224
|
+
req.headers = {
|
225
|
+
"Authorization" => "Basic #{Base64.encode64(@authsignal_tenant_id)}",
|
226
|
+
"Content-Type" => "application/json",
|
227
|
+
}
|
228
|
+
req.body = {
|
229
|
+
challengeId: challenge_id,
|
230
|
+
}.to_json
|
231
|
+
end
|
232
|
+
|
233
|
+
if response.success?
|
234
|
+
JSON.parse(response.body)
|
235
|
+
else
|
236
|
+
raise Error, "Failed to get authentication options: #{response.status}, #{response.body}"
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def present_passkey(challenge_id, assertion, device_id)
|
241
|
+
response = @client.post("#{@authsignal_base}/client/verify/passkey") do |req|
|
242
|
+
req.headers = {
|
243
|
+
"Authorization" => "Basic #{Base64.encode64(@authsignal_tenant_id)}",
|
244
|
+
"Content-Type" => "application/json",
|
245
|
+
}
|
246
|
+
req.body = {
|
247
|
+
challengeId: challenge_id,
|
248
|
+
authenticationCredential: {
|
249
|
+
id: assertion.credential_id,
|
250
|
+
rawId: assertion.credential_id,
|
251
|
+
response: {
|
252
|
+
authenticatorData: assertion.authenticator_data,
|
253
|
+
clientDataJSON: assertion.client_data_json,
|
254
|
+
signature: assertion.signature,
|
255
|
+
userHandle: assertion.user_handle,
|
256
|
+
},
|
257
|
+
type: "public-key",
|
258
|
+
clientExtensionResults: {},
|
259
|
+
authenticatorAttachment: "platform",
|
260
|
+
},
|
261
|
+
deviceId: device_id,
|
262
|
+
}.to_json
|
263
|
+
end
|
264
|
+
|
265
|
+
if response.success?
|
266
|
+
JSON.parse(response.body)
|
267
|
+
else
|
268
|
+
raise Error, "Failed to get JWT: #{response.status}, #{response.body}"
|
269
|
+
end
|
270
|
+
end
|
157
271
|
end
|
158
272
|
end
|
metadata
CHANGED
@@ -1,113 +1,99 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simplicity_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- George Dewar
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '2.7'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '2.7'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: faraday-cookie_jar
|
14
|
+
name: aws-sdk-cognitoidentity
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
30
16
|
requirements:
|
31
17
|
- - "~>"
|
32
18
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
19
|
+
version: 1.52.0
|
34
20
|
type: :runtime
|
35
21
|
prerelease: false
|
36
22
|
version_requirements: !ruby/object:Gem::Requirement
|
37
23
|
requirements:
|
38
24
|
- - "~>"
|
39
25
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
26
|
+
version: 1.52.0
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
28
|
+
name: aws-sdk-cognitoidentityprovider
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
44
30
|
requirements:
|
45
31
|
- - "~>"
|
46
32
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
33
|
+
version: '1.87'
|
48
34
|
type: :runtime
|
49
35
|
prerelease: false
|
50
36
|
version_requirements: !ruby/object:Gem::Requirement
|
51
37
|
requirements:
|
52
38
|
- - "~>"
|
53
39
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
40
|
+
version: '1.87'
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
|
-
name: aws-
|
42
|
+
name: aws-sigv4
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
58
44
|
requirements:
|
59
45
|
- - "~>"
|
60
46
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
47
|
+
version: 1.8.0
|
62
48
|
type: :runtime
|
63
49
|
prerelease: false
|
64
50
|
version_requirements: !ruby/object:Gem::Requirement
|
65
51
|
requirements:
|
66
52
|
- - "~>"
|
67
53
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
54
|
+
version: 1.8.0
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
56
|
+
name: faraday
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
72
58
|
requirements:
|
73
59
|
- - "~>"
|
74
60
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
61
|
+
version: '2.7'
|
76
62
|
type: :runtime
|
77
63
|
prerelease: false
|
78
64
|
version_requirements: !ruby/object:Gem::Requirement
|
79
65
|
requirements:
|
80
66
|
- - "~>"
|
81
67
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
68
|
+
version: '2.7'
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
70
|
+
name: faraday-cookie_jar
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
86
72
|
requirements:
|
87
73
|
- - "~>"
|
88
74
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
75
|
+
version: 0.0.7
|
90
76
|
type: :runtime
|
91
77
|
prerelease: false
|
92
78
|
version_requirements: !ruby/object:Gem::Requirement
|
93
79
|
requirements:
|
94
80
|
- - "~>"
|
95
81
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
82
|
+
version: 0.0.7
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
84
|
+
name: faraday-follow_redirects
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
100
86
|
requirements:
|
101
87
|
- - "~>"
|
102
88
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
89
|
+
version: 0.3.0
|
104
90
|
type: :runtime
|
105
91
|
prerelease: false
|
106
92
|
version_requirements: !ruby/object:Gem::Requirement
|
107
93
|
requirements:
|
108
94
|
- - "~>"
|
109
95
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
96
|
+
version: 0.3.0
|
111
97
|
description: This gem can log into Simplicity and fetch fund balances
|
112
98
|
email:
|
113
99
|
- george@dewar.co.nz
|
@@ -116,11 +102,11 @@ extensions: []
|
|
116
102
|
extra_rdoc_files: []
|
117
103
|
files:
|
118
104
|
- lib/simplicity_client.rb
|
119
|
-
homepage: https://
|
105
|
+
homepage: https://github.com/GeorgeDewar/simplicity_client
|
120
106
|
licenses:
|
121
107
|
- MIT
|
122
108
|
metadata: {}
|
123
|
-
post_install_message:
|
109
|
+
post_install_message:
|
124
110
|
rdoc_options: []
|
125
111
|
require_paths:
|
126
112
|
- lib
|
@@ -135,8 +121,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
135
121
|
- !ruby/object:Gem::Version
|
136
122
|
version: '0'
|
137
123
|
requirements: []
|
138
|
-
rubygems_version: 3.
|
139
|
-
signing_key:
|
124
|
+
rubygems_version: 3.5.16
|
125
|
+
signing_key:
|
140
126
|
specification_version: 4
|
141
127
|
summary: Fetch KiwiSaver and investment fund balances from Simplicity
|
142
128
|
test_files: []
|