passageidentity 0.1.2 → 0.2.1
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/passageidentity/auth.rb +16 -11
- data/lib/passageidentity/client.rb +24 -29
- data/lib/passageidentity/error.rb +20 -0
- data/lib/passageidentity/user_api.rb +100 -39
- data/passageidentity.gemspec +1 -1
- data/tests/errors_test.rb +30 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 04e31805b3eb522f8677f9c249abc99f8daf02f807fbe8855702b97656e0371b
|
4
|
+
data.tar.gz: 1d3e7b0d52b180bf880c0e988e035e6d393aaa856a3ff01b8c04b76567266950
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ea2498dd8f07d7a7f8bd5434635ef43e643611656bce4e71afa0a63d1eb4b29df1ed58b1bcd78e4dc348c8826b0ca16ba55f4ce37085b746685c0252be285195
|
7
|
+
data.tar.gz: f67a7631241795a30209c65caff48b624175bb5c181a0ac67b0c8cbba38e202c26d2c143d2d94a6e2436fcaae38cd0581a5d5323d4800aa613dddb3a75d33ce1
|
data/lib/passageidentity/auth.rb
CHANGED
@@ -19,8 +19,11 @@ module Passage
|
|
19
19
|
response = @connection.get("/v1/apps/#{@app_id}")
|
20
20
|
return response.body["app"]
|
21
21
|
rescue Faraday::Error => e
|
22
|
-
raise PassageError
|
23
|
-
|
22
|
+
raise PassageError.new(
|
23
|
+
message: "failed to fetch passage app",
|
24
|
+
status_code: e.response[:status],
|
25
|
+
body: e.response[:body]
|
26
|
+
)
|
24
27
|
end
|
25
28
|
end
|
26
29
|
|
@@ -52,14 +55,16 @@ module Passage
|
|
52
55
|
# Get the token based on the strategy
|
53
56
|
if @auth_strategy === Passage::COOKIE_STRATEGY
|
54
57
|
unless request.cookies["psg_auth_token"].present?
|
55
|
-
raise PassageError
|
56
|
-
|
58
|
+
raise PassageError.new(
|
59
|
+
message:
|
60
|
+
`missing authentication token: expected "psg_auth_token" cookie`
|
61
|
+
)
|
57
62
|
end
|
58
63
|
@token = request.cookies["psg_auth_token"]
|
59
64
|
else
|
60
65
|
headers = request.headers
|
61
66
|
unless headers["Authorization"].present?
|
62
|
-
raise PassageError
|
67
|
+
raise PassageError.new(message: "no authentication token in header")
|
63
68
|
end
|
64
69
|
@token = headers["Authorization"].split(" ").last
|
65
70
|
end
|
@@ -68,7 +73,7 @@ module Passage
|
|
68
73
|
if @token
|
69
74
|
return authenticate_token(@token)
|
70
75
|
else
|
71
|
-
raise PassageError
|
76
|
+
raise PassageError.new(message: "no authentication token")
|
72
77
|
end
|
73
78
|
nil
|
74
79
|
end
|
@@ -98,15 +103,15 @@ module Passage
|
|
98
103
|
)
|
99
104
|
return claims[0]["sub"]
|
100
105
|
rescue JWT::InvalidIssuerError => e
|
101
|
-
raise
|
106
|
+
raise PassageError.new(message: e.message)
|
102
107
|
rescue JWT::InvalidAudError => e
|
103
|
-
raise
|
108
|
+
raise PassageError.new(e.message)
|
104
109
|
rescue JWT::ExpiredSignature => e
|
105
|
-
raise
|
110
|
+
raise PassageError.new(e.message)
|
106
111
|
rescue JWT::IncorrectAlgorithm => e
|
107
|
-
raise
|
112
|
+
raise PassageError.new(e.message)
|
108
113
|
rescue JWT::DecodeError => e
|
109
|
-
raise
|
114
|
+
raise PassageError.new(e.message)
|
110
115
|
end
|
111
116
|
end
|
112
117
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require_relative "auth"
|
4
4
|
require_relative "user_api"
|
5
5
|
require_relative "error"
|
6
|
+
require "rubygems"
|
6
7
|
|
7
8
|
module Passage
|
8
9
|
App =
|
@@ -77,7 +78,7 @@ module Passage
|
|
77
78
|
|
78
79
|
# check for valid auth strategy
|
79
80
|
unless [COOKIE_STRATEGY, HEADER_STRATEGY].include? auth_strategy
|
80
|
-
raise PassageError
|
81
|
+
raise PassageError.new(message: "invalid auth strategy.")
|
81
82
|
end
|
82
83
|
@auth_strategy = auth_strategy
|
83
84
|
|
@@ -92,30 +93,19 @@ module Passage
|
|
92
93
|
end
|
93
94
|
|
94
95
|
def get_connection
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
headers: {
|
109
|
-
"Authorization" => "Bearer #{@api_key}"
|
110
|
-
}
|
111
|
-
) do |f|
|
112
|
-
f.request :json
|
113
|
-
f.request :retry
|
114
|
-
f.response :raise_error
|
115
|
-
f.response :json
|
116
|
-
f.adapter :net_http
|
117
|
-
end
|
118
|
-
end
|
96
|
+
gemspec = File.join(__dir__, "../../passageidentity.gemspec")
|
97
|
+
spec = Gem::Specification.load(gemspec)
|
98
|
+
headers = { "Passage-Version" => "passage-ruby #{spec.version}" }
|
99
|
+
headers["Authorization"] = "Bearer #{@api_key}" if @api_key != ""
|
100
|
+
|
101
|
+
@connection =
|
102
|
+
Faraday.new(url: @api_url, headers: headers) do |f|
|
103
|
+
f.request :json
|
104
|
+
f.request :retry
|
105
|
+
f.response :raise_error
|
106
|
+
f.response :json
|
107
|
+
f.adapter :net_http
|
108
|
+
end
|
119
109
|
end
|
120
110
|
|
121
111
|
def get_app()
|
@@ -165,8 +155,10 @@ module Passage
|
|
165
155
|
|
166
156
|
# check to see if the channel specified is valid before sending it off to the server
|
167
157
|
unless [PHONE_CHANNEL, EMAIL_CHANNEL].include? channel
|
168
|
-
raise PassageError
|
169
|
-
|
158
|
+
raise PassageError.new(
|
159
|
+
message:
|
160
|
+
"channel: must be either Passage::EMAIL_CHANNEL or Passage::PHONE_CHANNEL"
|
161
|
+
)
|
170
162
|
end
|
171
163
|
magic_link_req["channel"] = channel unless channel.empty?
|
172
164
|
magic_link_req["send"] = send
|
@@ -195,8 +187,11 @@ module Passage
|
|
195
187
|
)
|
196
188
|
)
|
197
189
|
rescue Faraday::Error => e
|
198
|
-
raise PassageError
|
199
|
-
|
190
|
+
raise PassageError.new(
|
191
|
+
message: "failed to create Passage Magic Link",
|
192
|
+
status_code: e.response[:status],
|
193
|
+
body: e.response[:body]
|
194
|
+
)
|
200
195
|
end
|
201
196
|
end
|
202
197
|
end
|
@@ -1,4 +1,24 @@
|
|
1
|
+
require "net/http"
|
2
|
+
|
1
3
|
module Passage
|
2
4
|
class PassageError < StandardError
|
5
|
+
attr_reader :status_code
|
6
|
+
attr_reader :status_text
|
7
|
+
attr_reader :message
|
8
|
+
attr_reader :error
|
9
|
+
|
10
|
+
def initialize(message:, status_code: nil, body: nil)
|
11
|
+
@message = message
|
12
|
+
@status_code = status_code
|
13
|
+
@status_text =
|
14
|
+
(
|
15
|
+
if status_code.nil?
|
16
|
+
nil
|
17
|
+
else
|
18
|
+
Net::HTTPResponse::CODE_TO_OBJ[status_code.to_s]
|
19
|
+
end
|
20
|
+
)
|
21
|
+
@error = body.nil? ? nil : body["error"]
|
22
|
+
end
|
3
23
|
end
|
4
24
|
end
|
@@ -10,7 +10,8 @@ module Passage
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def get(user_id:)
|
13
|
-
|
13
|
+
user_exists?(user_id)
|
14
|
+
|
14
15
|
begin
|
15
16
|
response = @connection.get("/v1/apps/#{@app_id}/users/#{user_id}")
|
16
17
|
user = response.body["user"]
|
@@ -35,17 +36,24 @@ module Passage
|
|
35
36
|
)
|
36
37
|
rescue Faraday::Error => e
|
37
38
|
if e.is_a? Faraday::ResourceNotFound
|
38
|
-
raise PassageError
|
39
|
-
|
39
|
+
raise PassageError.new(
|
40
|
+
message: "Passage User with ID \"#{user_id}\" does not exist",
|
41
|
+
status_code: e.response[:status],
|
42
|
+
body: e.response[:body]
|
43
|
+
)
|
40
44
|
else
|
41
|
-
raise PassageError
|
42
|
-
|
45
|
+
raise PassageError.new(
|
46
|
+
message: "failed to get Passage User.",
|
47
|
+
status_code: e.response[:status],
|
48
|
+
body: e.response[:body]
|
49
|
+
)
|
43
50
|
end
|
44
51
|
end
|
45
52
|
end
|
46
53
|
|
47
54
|
def activate(user_id:)
|
48
|
-
|
55
|
+
user_exists?(user_id)
|
56
|
+
|
49
57
|
begin
|
50
58
|
response =
|
51
59
|
@connection.patch("/v1/apps/#{@app_id}/users/#{user_id}/activate")
|
@@ -70,17 +78,24 @@ module Passage
|
|
70
78
|
)
|
71
79
|
rescue Faraday::Error => e
|
72
80
|
if e.is_a? Faraday::ResourceNotFound
|
73
|
-
raise PassageError
|
74
|
-
|
81
|
+
raise PassageError.new(
|
82
|
+
message: "Passage User with ID \"#{user_id}\" does not exist",
|
83
|
+
status_code: e.response[:status],
|
84
|
+
body: e.response[:body]
|
85
|
+
)
|
75
86
|
else
|
76
|
-
raise PassageError
|
77
|
-
|
87
|
+
raise PassageError.new(
|
88
|
+
message: "failed to activate Passage User.",
|
89
|
+
status_code: e.response[:status],
|
90
|
+
body: e.response[:body]
|
91
|
+
)
|
78
92
|
end
|
79
93
|
end
|
80
94
|
end
|
81
95
|
|
82
96
|
def deactivate(user_id:)
|
83
|
-
|
97
|
+
user_exists?(user_id)
|
98
|
+
|
84
99
|
begin
|
85
100
|
response =
|
86
101
|
@connection.patch("/v1/apps/#{@app_id}/users/#{user_id}/deactivate")
|
@@ -105,17 +120,24 @@ module Passage
|
|
105
120
|
)
|
106
121
|
rescue Faraday::Error => e
|
107
122
|
if e.is_a? Faraday::ResourceNotFound
|
108
|
-
raise PassageError
|
109
|
-
|
123
|
+
raise PassageError.new(
|
124
|
+
message: "Passage User with ID \"#{user_id}\" does not exist",
|
125
|
+
status_code: e.response[:status],
|
126
|
+
body: e.response[:body]
|
127
|
+
)
|
110
128
|
else
|
111
|
-
raise PassageError
|
112
|
-
|
129
|
+
raise PassageError.new(
|
130
|
+
message: "failed to deactivate Passage User.",
|
131
|
+
status_code: e.response[:status],
|
132
|
+
body: e.response[:body]
|
133
|
+
)
|
113
134
|
end
|
114
135
|
end
|
115
136
|
end
|
116
137
|
|
117
138
|
def update(user_id:, email: "", phone: "", user_metadata: {})
|
118
|
-
|
139
|
+
user_exists?(user_id)
|
140
|
+
|
119
141
|
updates = {}
|
120
142
|
updates["email"] = email unless email.empty?
|
121
143
|
updates["phone"] = phone unless phone.empty?
|
@@ -144,11 +166,17 @@ module Passage
|
|
144
166
|
)
|
145
167
|
rescue Faraday::Error => e
|
146
168
|
if e.is_a? Faraday::ResourceNotFound
|
147
|
-
raise PassageError
|
148
|
-
|
169
|
+
raise PassageError.new(
|
170
|
+
message: "Passage User with ID \"#{user_id}\" does not exist",
|
171
|
+
status_code: e.response[:status],
|
172
|
+
body: e.response[:body]
|
173
|
+
)
|
149
174
|
else
|
150
|
-
raise PassageError
|
151
|
-
|
175
|
+
raise PassageError.new(
|
176
|
+
"failed to update Passage User",
|
177
|
+
status_code: e.response[:status],
|
178
|
+
body: e.response[:body]
|
179
|
+
)
|
152
180
|
end
|
153
181
|
end
|
154
182
|
end
|
@@ -180,32 +208,41 @@ module Passage
|
|
180
208
|
)
|
181
209
|
)
|
182
210
|
rescue Faraday::Error => e
|
183
|
-
raise PassageError
|
184
|
-
|
211
|
+
raise PassageError.new(
|
212
|
+
"failed to create Passage User",
|
213
|
+
status_code: e.response[:status],
|
214
|
+
body: e.response[:body]
|
215
|
+
)
|
185
216
|
end
|
186
217
|
end
|
187
218
|
|
188
219
|
def delete(user_id:)
|
189
|
-
|
220
|
+
user_exists?(user_id)
|
221
|
+
|
190
222
|
begin
|
191
223
|
response = @connection.delete("/v1/apps/#{@app_id}/users/#{user_id}")
|
192
224
|
return true
|
193
225
|
rescue Faraday::Error => e
|
194
226
|
if e.is_a? Faraday::ResourceNotFound
|
195
|
-
raise PassageError
|
196
|
-
|
227
|
+
raise PassageError.new(
|
228
|
+
"passage User with ID \"#{user_id}\" does not exist",
|
229
|
+
status_code: e.response[:status],
|
230
|
+
body: e.response[:body]
|
231
|
+
)
|
197
232
|
else
|
198
|
-
raise PassageError
|
199
|
-
|
233
|
+
raise PassageError.new(
|
234
|
+
"failed to delete Passage User",
|
235
|
+
status_code: e.response[:status],
|
236
|
+
body: e.response[:body]
|
237
|
+
)
|
200
238
|
end
|
201
239
|
end
|
202
240
|
end
|
203
241
|
|
204
242
|
def delete_device(user_id:, device_id:)
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
end
|
243
|
+
user_exists?(user_id)
|
244
|
+
device_exists?(device_id)
|
245
|
+
|
209
246
|
begin
|
210
247
|
response =
|
211
248
|
@connection.delete(
|
@@ -213,13 +250,17 @@ module Passage
|
|
213
250
|
)
|
214
251
|
return true
|
215
252
|
rescue Faraday::Error => e
|
216
|
-
raise PassageError
|
217
|
-
|
253
|
+
raise PassageError.new(
|
254
|
+
"failed to delete Passage User Device",
|
255
|
+
status_code: e.response[:status],
|
256
|
+
body: e.response[:body]
|
257
|
+
)
|
218
258
|
end
|
219
259
|
end
|
220
260
|
|
221
261
|
def list_devices(user_id:)
|
222
|
-
|
262
|
+
user_exists?(user_id)
|
263
|
+
|
223
264
|
begin
|
224
265
|
response =
|
225
266
|
@connection.get("/v1/apps/#{@app_id}/users/#{user_id}/devices")
|
@@ -240,20 +281,40 @@ module Passage
|
|
240
281
|
end
|
241
282
|
return devices
|
242
283
|
rescue Faraday::Error => e
|
243
|
-
raise PassageError
|
244
|
-
|
284
|
+
raise PassageError.new(
|
285
|
+
"failed to delete Passage User Device",
|
286
|
+
status_code: e.response[:status],
|
287
|
+
body: e.response[:body]
|
288
|
+
)
|
245
289
|
end
|
246
290
|
end
|
247
291
|
|
248
292
|
def signout(user_id:)
|
249
|
-
|
293
|
+
user_exists?(user_id)
|
250
294
|
begin
|
251
295
|
response =
|
252
296
|
@connection.delete("/v1/apps/#{@app_id}/users/#{user_id}/tokens/")
|
253
297
|
return true
|
254
298
|
rescue Faraday::Error => e
|
255
|
-
raise PassageError
|
256
|
-
|
299
|
+
raise PassageError.new(
|
300
|
+
"failed to revoke user's refresh tokens",
|
301
|
+
status_code: e.response[:status],
|
302
|
+
body: e.response[:body]
|
303
|
+
)
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
private
|
308
|
+
|
309
|
+
def user_exists?(user_id)
|
310
|
+
if user_id.to_s.empty?
|
311
|
+
raise PassageError.new(message: "must supply a valid user_id")
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
def device_exists?(device_id)
|
316
|
+
if device_id.to_s.empty?
|
317
|
+
raise PassageError.new(message: "must supply a valid device_id")
|
257
318
|
end
|
258
319
|
end
|
259
320
|
end
|
data/passageidentity.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'passageidentity'
|
3
|
-
s.version = '0.1
|
3
|
+
s.version = '0.2.1'
|
4
4
|
s.summary = 'Passage SDK for biometric authentication'
|
5
5
|
s.description =
|
6
6
|
'Enables verification of server-side authentication and user management for applications using Passage'
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative "../lib/passageidentity/error"
|
2
|
+
require "test/unit"
|
3
|
+
require "net/http"
|
4
|
+
|
5
|
+
class ErrorTest < Test::Unit::TestCase
|
6
|
+
def test_initialize
|
7
|
+
body = { "error" => "some error" }
|
8
|
+
|
9
|
+
error =
|
10
|
+
Passage::PassageError.new(
|
11
|
+
message: "some message",
|
12
|
+
status_code: 400,
|
13
|
+
body: body
|
14
|
+
)
|
15
|
+
|
16
|
+
assert_equal error.message, "some message"
|
17
|
+
assert_equal error.error, "some error"
|
18
|
+
assert_equal error.status_code, 400
|
19
|
+
assert_equal error.status_text, Net::HTTPBadRequest
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_initialize_message_only
|
23
|
+
error = Passage::PassageError.new(message: "some message")
|
24
|
+
|
25
|
+
assert_equal error.message, "some message"
|
26
|
+
assert_equal error.error, nil
|
27
|
+
assert_equal error.status_code, nil
|
28
|
+
assert_equal error.status_text, nil
|
29
|
+
end
|
30
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: passageidentity
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Passage Identity
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-10-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -94,6 +94,7 @@ files:
|
|
94
94
|
- tests/all.rb
|
95
95
|
- tests/app_test.rb
|
96
96
|
- tests/auth_test.rb
|
97
|
+
- tests/errors_test.rb
|
97
98
|
- tests/magic_link_test.rb
|
98
99
|
- tests/user_api_test.rb
|
99
100
|
homepage: https://rubygems.org/gems/passageidentity
|