workos 2.4.0 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/README.md +4 -1
- data/lib/workos/audit_trail.rb +0 -1
- data/lib/workos/client.rb +14 -5
- data/lib/workos/configuration.rb +17 -0
- data/lib/workos/directory_sync.rb +0 -1
- data/lib/workos/errors.rb +3 -0
- data/lib/workos/mfa.rb +22 -7
- data/lib/workos/organizations.rb +0 -1
- data/lib/workos/passwordless.rb +0 -1
- data/lib/workos/portal.rb +0 -1
- data/lib/workos/sso.rb +1 -2
- data/lib/workos/types/{verify_factor_struct.rb → verify_challenge_struct.rb} +3 -3
- data/lib/workos/types.rb +1 -1
- data/lib/workos/{verify_factor.rb → verify_challenge.rb} +5 -6
- data/lib/workos/version.rb +1 -1
- data/lib/workos.rb +17 -7
- data/spec/lib/workos/configuration_spec.rb +61 -0
- data/spec/lib/workos/mfa_spec.rb +93 -74
- data/spec/lib/workos/sso_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -2
- data/spec/support/fixtures/vcr_cassettes/mfa/challenge_factor_generic_valid.yml +2 -2
- data/spec/support/fixtures/vcr_cassettes/mfa/challenge_factor_sms_valid.yml +2 -2
- data/spec/support/fixtures/vcr_cassettes/mfa/challenge_factor_totp_valid.yml +2 -2
- data/spec/support/fixtures/vcr_cassettes/mfa/{verify_factor_generic_expired.yml → verify_challenge_generic_expired.yml} +2 -2
- data/spec/support/fixtures/vcr_cassettes/mfa/{verify_factor_generic_invalid.yml → verify_challenge_generic_invalid.yml} +2 -2
- data/spec/support/fixtures/vcr_cassettes/mfa/{verify_factor_generic_valid.yml → verify_challenge_generic_valid.yml} +2 -2
- data/spec/support/fixtures/vcr_cassettes/mfa/{verify_factor_generic_valid_is_false.yml → verify_challenge_generic_valid_is_false.yml} +2 -2
- metadata +15 -15
- data/lib/workos/base.rb +0 -18
- data/spec/lib/workos/base_spec.rb +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 014f85386dcfba661f0a74ae427127257b953a2791b4667c72d9b1961237a93b
|
4
|
+
data.tar.gz: 7290ad0b22df3751f1183f5465d35f56828c4fd1b0e519c29c208138b67db3fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 766ef6dfba39dc072dab56a7fbfbcaa4484e39bbd444dc3c9148894e791b232689e7210a13f178442e595a67ac3c74aed64ee377ddad342f6105b2103513bbec
|
7
|
+
data.tar.gz: 759b73ee9afe91742acb8ee818d03bc397a6760d44f88dbfa3989439e4e396cacc2b71dd866ab90495bb7c1e2b430709987f09335a20b4a08b123aedfa1003d8
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
workos (2.
|
4
|
+
workos (2.5.0)
|
5
5
|
sorbet-runtime (~> 0.5)
|
6
6
|
|
7
7
|
GEM
|
@@ -60,7 +60,7 @@ GEM
|
|
60
60
|
simplecov_json_formatter (0.1.2)
|
61
61
|
sorbet (0.5.6388)
|
62
62
|
sorbet-static (= 0.5.6388)
|
63
|
-
sorbet-runtime (0.5.
|
63
|
+
sorbet-runtime (0.5.10207)
|
64
64
|
sorbet-static (0.5.6388-universal-darwin-14)
|
65
65
|
sorbet-static (0.5.6388-universal-darwin-15)
|
66
66
|
sorbet-static (0.5.6388-universal-darwin-16)
|
data/README.md
CHANGED
@@ -35,7 +35,10 @@ Or, you may set the key yourself, such as in an initializer in your application
|
|
35
35
|
```ruby
|
36
36
|
# /config/initializers/workos.rb
|
37
37
|
|
38
|
-
WorkOS.
|
38
|
+
WorkOS.configure do |config|
|
39
|
+
config.key = '[your api key]'
|
40
|
+
config.timeout = 120
|
41
|
+
end
|
39
42
|
```
|
40
43
|
|
41
44
|
## SDK Versioning
|
data/lib/workos/audit_trail.rb
CHANGED
data/lib/workos/client.rb
CHANGED
@@ -11,6 +11,9 @@ module WorkOS
|
|
11
11
|
def client
|
12
12
|
Net::HTTP.new(WorkOS::API_HOSTNAME, 443).tap do |http_client|
|
13
13
|
http_client.use_ssl = true
|
14
|
+
http_client.open_timeout = WorkOS.config.timeout
|
15
|
+
http_client.read_timeout = WorkOS.config.timeout
|
16
|
+
http_client.write_timeout = WorkOS.config.timeout
|
14
17
|
end
|
15
18
|
end
|
16
19
|
|
@@ -20,7 +23,13 @@ module WorkOS
|
|
20
23
|
).returns(::T.untyped)
|
21
24
|
end
|
22
25
|
def execute_request(request:)
|
23
|
-
|
26
|
+
begin
|
27
|
+
response = client.request(request)
|
28
|
+
rescue Net::OpenTimeout, Net::ReadTimeout, Net::WriteTimeout
|
29
|
+
raise TimeoutError.new(
|
30
|
+
message: 'API Timeout Error',
|
31
|
+
)
|
32
|
+
end
|
24
33
|
|
25
34
|
http_status = response.code.to_i
|
26
35
|
handle_error_response(response: response) if http_status >= 400
|
@@ -45,7 +54,7 @@ module WorkOS
|
|
45
54
|
'Content-Type' => 'application/json',
|
46
55
|
)
|
47
56
|
|
48
|
-
request['Authorization'] = "Bearer #{access_token || WorkOS.key!}" if auth
|
57
|
+
request['Authorization'] = "Bearer #{access_token || WorkOS.config.key!}" if auth
|
49
58
|
request['User-Agent'] = user_agent
|
50
59
|
request
|
51
60
|
end
|
@@ -61,7 +70,7 @@ module WorkOS
|
|
61
70
|
def post_request(path:, auth: false, idempotency_key: nil, body: nil)
|
62
71
|
request = Net::HTTP::Post.new(path, 'Content-Type' => 'application/json')
|
63
72
|
request.body = body.to_json if body
|
64
|
-
request['Authorization'] = "Bearer #{WorkOS.key!}" if auth
|
73
|
+
request['Authorization'] = "Bearer #{WorkOS.config.key!}" if auth
|
65
74
|
request['Idempotency-Key'] = idempotency_key if idempotency_key
|
66
75
|
request['User-Agent'] = user_agent
|
67
76
|
request
|
@@ -83,7 +92,7 @@ module WorkOS
|
|
83
92
|
'Content-Type' => 'application/json',
|
84
93
|
)
|
85
94
|
|
86
|
-
request['Authorization'] = "Bearer #{WorkOS.key!}" if auth
|
95
|
+
request['Authorization'] = "Bearer #{WorkOS.config.key!}" if auth
|
87
96
|
request['User-Agent'] = user_agent
|
88
97
|
request
|
89
98
|
end
|
@@ -99,7 +108,7 @@ module WorkOS
|
|
99
108
|
def put_request(path:, auth: false, idempotency_key: nil, body: nil)
|
100
109
|
request = Net::HTTP::Put.new(path, 'Content-Type' => 'application/json')
|
101
110
|
request.body = body.to_json if body
|
102
|
-
request['Authorization'] = "Bearer #{WorkOS.key!}" if auth
|
111
|
+
request['Authorization'] = "Bearer #{WorkOS.config.key!}" if auth
|
103
112
|
request['Idempotency-Key'] = idempotency_key if idempotency_key
|
104
113
|
request['User-Agent'] = user_agent
|
105
114
|
request
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# typed: true
|
3
|
+
|
4
|
+
module WorkOS
|
5
|
+
# Configuration class sets config initializer
|
6
|
+
class Configuration
|
7
|
+
attr_accessor :timeout, :key
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@timeout = 60
|
11
|
+
end
|
12
|
+
|
13
|
+
def key!
|
14
|
+
key or raise '`WorkOS.config.key` not set'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/workos/errors.rb
CHANGED
@@ -61,4 +61,7 @@ module WorkOS
|
|
61
61
|
# SignatureVerificationError is raised when the signature verification for a
|
62
62
|
# webhook fails
|
63
63
|
class SignatureVerificationError < WorkOSError; end
|
64
|
+
|
65
|
+
# TimeoutError is raised when the HTTP request to the API times out
|
66
|
+
class TimeoutError < WorkOSError; end
|
64
67
|
end
|
data/lib/workos/mfa.rb
CHANGED
@@ -11,7 +11,6 @@ module WorkOS
|
|
11
11
|
module MFA
|
12
12
|
class << self
|
13
13
|
extend T::Sig
|
14
|
-
include Base
|
15
14
|
include Client
|
16
15
|
sig { params(id: String).returns(T::Boolean) }
|
17
16
|
def delete_factor(id:)
|
@@ -122,9 +121,8 @@ module WorkOS
|
|
122
121
|
auth: true,
|
123
122
|
body: {
|
124
123
|
sms_template: sms_template,
|
125
|
-
authentication_factor_id: authentication_factor_id,
|
126
124
|
},
|
127
|
-
path:
|
125
|
+
path: "/auth/factors/#{authentication_factor_id}/challenge",
|
128
126
|
)
|
129
127
|
|
130
128
|
response = execute_request(request: request)
|
@@ -135,30 +133,47 @@ module WorkOS
|
|
135
133
|
params(
|
136
134
|
authentication_challenge_id: T.nilable(String),
|
137
135
|
code: T.nilable(String),
|
138
|
-
).returns(WorkOS::
|
136
|
+
).returns(WorkOS::VerifyChallenge)
|
139
137
|
end
|
140
138
|
def verify_factor(
|
141
139
|
authentication_challenge_id: nil,
|
142
140
|
code: nil
|
143
141
|
)
|
142
|
+
warn '[DEPRECATION] `verify_factor` is deprecated. Please use `verify_challenge` instead.'
|
143
|
+
|
144
|
+
verify_challenge(
|
145
|
+
authentication_challenge_id: authentication_challenge_id,
|
146
|
+
code: code,
|
147
|
+
)
|
148
|
+
end
|
149
|
+
|
150
|
+
sig do
|
151
|
+
params(
|
152
|
+
authentication_challenge_id: T.nilable(String),
|
153
|
+
code: T.nilable(String),
|
154
|
+
).returns(WorkOS::VerifyChallenge)
|
155
|
+
end
|
156
|
+
def verify_challenge(
|
157
|
+
authentication_challenge_id: nil,
|
158
|
+
code: nil
|
159
|
+
)
|
144
160
|
|
145
161
|
if authentication_challenge_id.nil? || code.nil?
|
146
162
|
raise ArgumentError, "Incomplete arguments: 'authentication_challenge_id' and 'code' are required arguments"
|
147
163
|
end
|
148
164
|
|
149
165
|
options = {
|
150
|
-
"authentication_challenge_id": authentication_challenge_id,
|
151
166
|
"code": code,
|
152
167
|
}
|
153
168
|
|
154
169
|
response = execute_request(
|
155
170
|
request: post_request(
|
156
|
-
path:
|
171
|
+
path: "/auth/challenges/#{authentication_challenge_id}/verify",
|
157
172
|
auth: true,
|
158
173
|
body: options,
|
159
174
|
),
|
160
175
|
)
|
161
|
-
WorkOS::
|
176
|
+
WorkOS::VerifyChallenge.new(response.body)
|
162
177
|
end
|
163
178
|
end
|
164
179
|
end
|
data/lib/workos/organizations.rb
CHANGED
data/lib/workos/passwordless.rb
CHANGED
data/lib/workos/portal.rb
CHANGED
data/lib/workos/sso.rb
CHANGED
@@ -13,7 +13,6 @@ module WorkOS
|
|
13
13
|
module SSO
|
14
14
|
class << self
|
15
15
|
extend T::Sig
|
16
|
-
include Base
|
17
16
|
include Client
|
18
17
|
|
19
18
|
PROVIDERS = WorkOS::Types::Provider.values.map(&:serialize).freeze
|
@@ -142,7 +141,7 @@ module WorkOS
|
|
142
141
|
def profile_and_token(code:, client_id: nil)
|
143
142
|
body = {
|
144
143
|
client_id: client_id,
|
145
|
-
client_secret: WorkOS.key!,
|
144
|
+
client_secret: WorkOS.config.key!,
|
146
145
|
grant_type: 'authorization_code',
|
147
146
|
code: code,
|
148
147
|
}
|
@@ -3,9 +3,9 @@
|
|
3
3
|
|
4
4
|
module WorkOS
|
5
5
|
module Types
|
6
|
-
# This
|
7
|
-
# for the
|
8
|
-
class
|
6
|
+
# This VerifyChallengeStruct acts as a typed interface
|
7
|
+
# for the VerifyChallenge class
|
8
|
+
class VerifyChallengeStruct < T::Struct
|
9
9
|
const :challenge, T.nilable(T::Hash[Symbol, Object])
|
10
10
|
const :valid, T::Boolean
|
11
11
|
end
|
data/lib/workos/types.rb
CHANGED
@@ -2,10 +2,9 @@
|
|
2
2
|
# typed: false
|
3
3
|
|
4
4
|
module WorkOS
|
5
|
-
# The
|
6
|
-
# a WorkOS
|
7
|
-
|
8
|
-
class VerifyFactor
|
5
|
+
# The VerifyChallenge class provides a lightweight wrapper around
|
6
|
+
# a WorkOS Authentication Challenge resource.
|
7
|
+
class VerifyChallenge
|
9
8
|
include HashProvider
|
10
9
|
extend T::Sig
|
11
10
|
|
@@ -27,11 +26,11 @@ module WorkOS
|
|
27
26
|
|
28
27
|
private
|
29
28
|
|
30
|
-
sig { params(json_string: String).returns(WorkOS::Types::
|
29
|
+
sig { params(json_string: String).returns(WorkOS::Types::VerifyChallengeStruct) }
|
31
30
|
def parse_json(json_string)
|
32
31
|
hash = JSON.parse(json_string, symbolize_names: true)
|
33
32
|
|
34
|
-
WorkOS::Types::
|
33
|
+
WorkOS::Types::VerifyChallengeStruct.new(
|
35
34
|
challenge: hash[:challenge],
|
36
35
|
valid: hash[:valid],
|
37
36
|
)
|
data/lib/workos/version.rb
CHANGED
data/lib/workos.rb
CHANGED
@@ -5,6 +5,7 @@ require 'workos/version'
|
|
5
5
|
require 'sorbet-runtime'
|
6
6
|
require 'json'
|
7
7
|
require 'workos/hash_provider'
|
8
|
+
require 'workos/configuration'
|
8
9
|
|
9
10
|
# Use the WorkOS module to authenticate your
|
10
11
|
# requests to the WorkOS API. The gem will read
|
@@ -16,20 +17,28 @@ module WorkOS
|
|
16
17
|
API_HOSTNAME = ENV['WORKOS_API_HOSTNAME'] || 'api.workos.com'
|
17
18
|
|
18
19
|
def self.key=(value)
|
19
|
-
|
20
|
+
warn '`WorkOS.key=` is deprecated. Use `WorkOS.configure` instead.'
|
21
|
+
|
22
|
+
config.key = value
|
20
23
|
end
|
21
24
|
|
22
25
|
def self.key
|
23
|
-
|
26
|
+
warn '`WorkOS.key` is deprecated. Use `WorkOS.configure` instead.'
|
27
|
+
|
28
|
+
config.key
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.config
|
32
|
+
@config ||= Configuration.new
|
24
33
|
end
|
25
34
|
|
26
|
-
def self.
|
27
|
-
|
35
|
+
def self.configure
|
36
|
+
yield(config)
|
28
37
|
end
|
29
38
|
|
30
39
|
autoload :Types, 'workos/types'
|
31
|
-
autoload :Base, 'workos/base'
|
32
40
|
autoload :Client, 'workos/client'
|
41
|
+
autoload :Configuration, 'workos/configuration'
|
33
42
|
autoload :AuditTrail, 'workos/audit_trail'
|
34
43
|
autoload :Connection, 'workos/connection'
|
35
44
|
autoload :DirectorySync, 'workos/directory_sync'
|
@@ -48,7 +57,7 @@ module WorkOS
|
|
48
57
|
autoload :MFA, 'workos/mfa'
|
49
58
|
autoload :Factor, 'workos/factor'
|
50
59
|
autoload :Challenge, 'workos/challenge'
|
51
|
-
autoload :
|
60
|
+
autoload :VerifyChallenge, 'workos/verify_challenge'
|
52
61
|
autoload :DeprecatedHashWrapper, 'workos/deprecated_hash_wrapper'
|
53
62
|
|
54
63
|
|
@@ -57,9 +66,10 @@ module WorkOS
|
|
57
66
|
autoload :AuthenticationError, 'workos/errors'
|
58
67
|
autoload :InvalidRequestError, 'workos/errors'
|
59
68
|
autoload :SignatureVerificationError, 'workos/errors'
|
69
|
+
autoload :TimeoutError, 'workos/errors'
|
60
70
|
|
61
71
|
# Remove WORKOS_KEY at some point in the future. Keeping it here now for
|
62
72
|
# backwards compatibility.
|
63
73
|
key = ENV['WORKOS_API_KEY'] || ENV['WORKOS_KEY']
|
64
|
-
|
74
|
+
config.key = key unless key.nil?
|
65
75
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# typed: false
|
3
|
+
|
4
|
+
describe WorkOS do
|
5
|
+
describe '.configure' do
|
6
|
+
context 'with key and no timeout' do
|
7
|
+
before do
|
8
|
+
WorkOS.configure do |config|
|
9
|
+
config.key = 'example_api_key'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'sets the key and default timeout configuration' do
|
14
|
+
expect(WorkOS.config.key).to eq('example_api_key')
|
15
|
+
expect(WorkOS.config.timeout).to eq(60)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'with key and timeout' do
|
20
|
+
before do
|
21
|
+
WorkOS.configure do |config|
|
22
|
+
config.key = 'example_api_key'
|
23
|
+
config.timeout = 120
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'sets the key and timeout configuration' do
|
28
|
+
expect(WorkOS.config.key).to eq('example_api_key')
|
29
|
+
expect(WorkOS.config.timeout).to eq(120)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe WorkOS::Configuration do
|
36
|
+
describe '.key!' do
|
37
|
+
context 'with key set' do
|
38
|
+
before do
|
39
|
+
WorkOS.config.key = 'example_api_key'
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'returns the key' do
|
43
|
+
expect(WorkOS.config.key!).to eq('example_api_key')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'with key not set' do
|
48
|
+
before do
|
49
|
+
WorkOS.config.key = nil
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'throws an error' do
|
53
|
+
expect do
|
54
|
+
WorkOS.config.key!
|
55
|
+
end.to raise_error(
|
56
|
+
'`WorkOS.config.key` not set',
|
57
|
+
)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/spec/lib/workos/mfa_spec.rb
CHANGED
@@ -4,8 +4,8 @@
|
|
4
4
|
describe WorkOS::MFA do
|
5
5
|
it_behaves_like 'client'
|
6
6
|
|
7
|
-
describe 'enroll_factor
|
8
|
-
context '
|
7
|
+
describe '.enroll_factor' do
|
8
|
+
context 'with valid generic argument' do
|
9
9
|
it 'returns a valid factor object' do
|
10
10
|
VCR.use_cassette 'mfa/enroll_factor_generic_valid' do
|
11
11
|
factor = described_class.enroll_factor(
|
@@ -16,7 +16,7 @@ describe WorkOS::MFA do
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
context '
|
19
|
+
context 'with valid totp arguments' do
|
20
20
|
it 'returns a valid factor object' do
|
21
21
|
VCR.use_cassette 'mfa/enroll_factor_totp_valid' do
|
22
22
|
factor = described_class.enroll_factor(
|
@@ -29,7 +29,7 @@ describe WorkOS::MFA do
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
context '
|
32
|
+
context 'with valid sms arguments' do
|
33
33
|
it 'returns a valid factor object' do
|
34
34
|
VCR.use_cassette 'mfa/enroll_factor_sms_valid' do
|
35
35
|
factor = described_class.enroll_factor(
|
@@ -40,10 +40,8 @@ describe WorkOS::MFA do
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
43
|
-
end
|
44
43
|
|
45
|
-
|
46
|
-
context 'enroll factor throws error if type is not sms or totp' do
|
44
|
+
context 'when type is not sms or totp' do
|
47
45
|
it 'returns an error' do
|
48
46
|
expect do
|
49
47
|
described_class.enroll_factor(
|
@@ -57,7 +55,7 @@ describe WorkOS::MFA do
|
|
57
55
|
end
|
58
56
|
end
|
59
57
|
|
60
|
-
context '
|
58
|
+
context 'when type is totp but missing arguments' do
|
61
59
|
it 'returns an error' do
|
62
60
|
expect do
|
63
61
|
described_class.enroll_factor(
|
@@ -70,7 +68,7 @@ describe WorkOS::MFA do
|
|
70
68
|
)
|
71
69
|
end
|
72
70
|
end
|
73
|
-
context '
|
71
|
+
context 'when type is sms and phone number is nil' do
|
74
72
|
it 'returns an error' do
|
75
73
|
expect do
|
76
74
|
described_class.enroll_factor(
|
@@ -84,7 +82,7 @@ describe WorkOS::MFA do
|
|
84
82
|
end
|
85
83
|
end
|
86
84
|
|
87
|
-
describe '
|
85
|
+
describe '.challenge_factor' do
|
88
86
|
context 'challenge with totp' do
|
89
87
|
it 'returns challenge factor object for totp' do
|
90
88
|
VCR.use_cassette 'mfa/challenge_factor_totp_valid' do
|
@@ -118,9 +116,7 @@ describe WorkOS::MFA do
|
|
118
116
|
end
|
119
117
|
end
|
120
118
|
end
|
121
|
-
end
|
122
119
|
|
123
|
-
describe 'challenge factor with invalid arguments' do
|
124
120
|
context 'challenge with totp mssing authentication_factor_id' do
|
125
121
|
it 'returns argument error' do
|
126
122
|
expect do
|
@@ -133,48 +129,58 @@ describe WorkOS::MFA do
|
|
133
129
|
end
|
134
130
|
end
|
135
131
|
|
136
|
-
describe '
|
137
|
-
|
138
|
-
|
139
|
-
VCR.use_cassette 'mfa/
|
140
|
-
|
132
|
+
describe '.verify_factor' do
|
133
|
+
it 'throws a warning' do
|
134
|
+
expect do
|
135
|
+
VCR.use_cassette 'mfa/verify_challenge_generic_valid' do
|
136
|
+
described_class.verify_factor(
|
141
137
|
authentication_challenge_id: 'auth_challenge_01FZ4YVRBMXP5ZM0A7BP4AJ12J',
|
142
138
|
code: '897792',
|
143
139
|
)
|
144
|
-
expect(verify_factor.valid == 'true')
|
145
140
|
end
|
146
|
-
end
|
141
|
+
end.to output("[DEPRECATION] `verify_factor` is deprecated. Please use `verify_challenge` instead.\n").to_stderr
|
147
142
|
end
|
148
143
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
expect(verify_factor.valid == 'false')
|
157
|
-
end
|
144
|
+
it 'calls verify_challenge' do
|
145
|
+
VCR.use_cassette 'mfa/verify_challenge_generic_valid' do
|
146
|
+
verify_factor = described_class.verify_factor(
|
147
|
+
authentication_challenge_id: 'auth_challenge_01FZ4YVRBMXP5ZM0A7BP4AJ12J',
|
148
|
+
code: '897792',
|
149
|
+
)
|
150
|
+
expect(verify_factor.valid == 'true')
|
158
151
|
end
|
159
152
|
end
|
153
|
+
end
|
160
154
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
155
|
+
describe '.verify_challenge' do
|
156
|
+
context 'with generic otp' do
|
157
|
+
context 'and the challenge has not been verified' do
|
158
|
+
it 'returns true if the code is correct' do
|
159
|
+
VCR.use_cassette 'mfa/verify_challenge_generic_valid' do
|
160
|
+
verify_challenge = described_class.verify_challenge(
|
166
161
|
authentication_challenge_id: 'auth_challenge_01FZ4YVRBMXP5ZM0A7BP4AJ12J',
|
167
162
|
code: '897792',
|
168
163
|
)
|
169
|
-
|
164
|
+
expect(verify_challenge.valid == 'true')
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'returns false if the code is incorrect' do
|
169
|
+
VCR.use_cassette 'mfa/verify_challenge_generic_valid_is_false' do
|
170
|
+
verify_challenge = described_class.verify_challenge(
|
171
|
+
authentication_challenge_id: 'auth_challenge_01FZ4YVRBMXP5ZM0A7BP4AJ12J',
|
172
|
+
code: '897792',
|
173
|
+
)
|
174
|
+
expect(verify_challenge.valid == 'false')
|
175
|
+
end
|
170
176
|
end
|
171
177
|
end
|
172
178
|
|
173
|
-
context '
|
174
|
-
it 'returns error
|
175
|
-
VCR.use_cassette 'mfa/
|
179
|
+
context 'and the challenge has already been verified' do
|
180
|
+
it 'returns an error' do
|
181
|
+
VCR.use_cassette 'mfa/verify_challenge_generic_invalid' do
|
176
182
|
expect do
|
177
|
-
described_class.
|
183
|
+
described_class.verify_challenge(
|
178
184
|
authentication_challenge_id: 'auth_challenge_01FZ4YVRBMXP5ZM0A7BP4AJ12J',
|
179
185
|
code: '897792',
|
180
186
|
)
|
@@ -182,51 +188,62 @@ describe WorkOS::MFA do
|
|
182
188
|
end
|
183
189
|
end
|
184
190
|
end
|
185
|
-
end
|
186
|
-
end
|
187
191
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
192
|
+
context 'and the challenge has expired' do
|
193
|
+
it 'returns an error' do
|
194
|
+
VCR.use_cassette 'mfa/verify_challenge_generic_expired' do
|
195
|
+
expect do
|
196
|
+
described_class.verify_challenge(
|
197
|
+
authentication_challenge_id: 'auth_challenge_01FZ4YVRBMXP5ZM0A7BP4AJ12J',
|
198
|
+
code: '897792',
|
199
|
+
)
|
200
|
+
end.to raise_error(WorkOS::InvalidRequestError)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
context 'with missing code argument' do
|
206
|
+
it 'returns an argument error' do
|
207
|
+
expect do
|
208
|
+
described_class.verify_challenge(
|
209
|
+
authentication_challenge_id: 'auth_challenge_01FZ4YVRBMXP5ZM0A7BP4AJ12J',
|
210
|
+
)
|
211
|
+
end.to raise_error(
|
212
|
+
ArgumentError,
|
213
|
+
"Incomplete arguments: 'authentication_challenge_id' and 'code' are required arguments",
|
194
214
|
)
|
195
|
-
end
|
196
|
-
ArgumentError,
|
197
|
-
"Incomplete arguments: 'authentication_challenge_id' and 'code' are required arguments",
|
198
|
-
)
|
215
|
+
end
|
199
216
|
end
|
200
|
-
end
|
201
217
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
218
|
+
context 'with missing authentication_challenge_id argument' do
|
219
|
+
it 'returns an error' do
|
220
|
+
expect do
|
221
|
+
described_class.verify_challenge(
|
222
|
+
code: '897792',
|
223
|
+
)
|
224
|
+
end.to raise_error(
|
225
|
+
ArgumentError,
|
226
|
+
"Incomplete arguments: 'authentication_challenge_id' and 'code' are required arguments",
|
207
227
|
)
|
208
|
-
end
|
209
|
-
ArgumentError,
|
210
|
-
"Incomplete arguments: 'authentication_challenge_id' and 'code' are required arguments",
|
211
|
-
)
|
228
|
+
end
|
212
229
|
end
|
213
|
-
end
|
214
230
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
231
|
+
context 'with missing code and authentication_challenge_id arguments' do
|
232
|
+
it 'returns an argument error' do
|
233
|
+
expect do
|
234
|
+
described_class.verify_challenge
|
235
|
+
end.to raise_error(
|
236
|
+
ArgumentError,
|
237
|
+
"Incomplete arguments: 'authentication_challenge_id' and 'code' are required arguments",
|
238
|
+
)
|
239
|
+
end
|
223
240
|
end
|
224
241
|
end
|
225
242
|
end
|
226
243
|
|
227
|
-
describe '
|
228
|
-
context '
|
229
|
-
it '
|
244
|
+
describe '.get_factor' do
|
245
|
+
context 'with a valid id' do
|
246
|
+
it 'returns a factor' do
|
230
247
|
VCR.use_cassette 'mfa/get_factor_valid' do
|
231
248
|
factor = described_class.get_factor(
|
232
249
|
id: 'auth_factor_01FZ4WMXXA09XF6NK1XMKNWB3M',
|
@@ -236,8 +253,8 @@ describe WorkOS::MFA do
|
|
236
253
|
end
|
237
254
|
end
|
238
255
|
|
239
|
-
context 'invalid
|
240
|
-
it '
|
256
|
+
context 'with an invalid id' do
|
257
|
+
it 'returns an error' do
|
241
258
|
VCR.use_cassette 'mfa/get_factor_invalid' do
|
242
259
|
expect do
|
243
260
|
described_class.get_factor(
|
@@ -247,7 +264,9 @@ describe WorkOS::MFA do
|
|
247
264
|
end
|
248
265
|
end
|
249
266
|
end
|
267
|
+
end
|
250
268
|
|
269
|
+
describe '.delete_factor' do
|
251
270
|
context 'deletes facotr' do
|
252
271
|
it 'uses delete_factor to delete factor' do
|
253
272
|
VCR.use_cassette 'mfa/delete_factor' do
|
data/spec/lib/workos/sso_spec.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -25,7 +25,7 @@ SPEC_ROOT = File.dirname __FILE__
|
|
25
25
|
|
26
26
|
VCR.configure do |config|
|
27
27
|
config.cassette_library_dir = 'spec/support/fixtures/vcr_cassettes'
|
28
|
-
config.filter_sensitive_data('<API_KEY>') { WorkOS.key }
|
28
|
+
config.filter_sensitive_data('<API_KEY>') { WorkOS.config.key }
|
29
29
|
config.hook_into :webmock
|
30
30
|
end
|
31
31
|
|
@@ -51,6 +51,6 @@ RSpec.configure do |config|
|
|
51
51
|
end
|
52
52
|
end)
|
53
53
|
|
54
|
-
config.before(:all) { WorkOS.key ||= '' }
|
54
|
+
config.before(:all) { WorkOS.config.key ||= '' }
|
55
55
|
config.before(:each) { VCR.turn_on! }
|
56
56
|
end
|
@@ -2,10 +2,10 @@
|
|
2
2
|
http_interactions:
|
3
3
|
- request:
|
4
4
|
method: post
|
5
|
-
uri: https://api.workos.com/auth/factors/challenge
|
5
|
+
uri: https://api.workos.com/auth/factors/auth_factor_01FZ4WMXXA09XF6NK1XMKNWB3M/challenge
|
6
6
|
body:
|
7
7
|
encoding: UTF-8
|
8
|
-
string: '{"sms_template":null
|
8
|
+
string: '{"sms_template":null}'
|
9
9
|
headers:
|
10
10
|
Content-Type:
|
11
11
|
- application/json
|
@@ -2,10 +2,10 @@
|
|
2
2
|
http_interactions:
|
3
3
|
- request:
|
4
4
|
method: post
|
5
|
-
uri: https://api.workos.com/auth/factors/challenge
|
5
|
+
uri: https://api.workos.com/auth/factors/auth_factor_01FZ4TS14D1PHFNZ9GF6YD8M1F/challenge
|
6
6
|
body:
|
7
7
|
encoding: UTF-8
|
8
|
-
string: '{"sms_template":"Your code is {{code}}"
|
8
|
+
string: '{"sms_template":"Your code is {{code}}"}'
|
9
9
|
headers:
|
10
10
|
Content-Type:
|
11
11
|
- application/json
|
@@ -2,10 +2,10 @@
|
|
2
2
|
http_interactions:
|
3
3
|
- request:
|
4
4
|
method: post
|
5
|
-
uri: https://api.workos.com/auth/factors/challenge
|
5
|
+
uri: https://api.workos.com/auth/factors/auth_factor_01FZ4TS0MWPZR7GATS7KCXANQZ/challenge
|
6
6
|
body:
|
7
7
|
encoding: UTF-8
|
8
|
-
string: '{"sms_template":null
|
8
|
+
string: '{"sms_template":null}'
|
9
9
|
headers:
|
10
10
|
Content-Type:
|
11
11
|
- application/json
|
@@ -2,10 +2,10 @@
|
|
2
2
|
http_interactions:
|
3
3
|
- request:
|
4
4
|
method: post
|
5
|
-
uri: https://api.workos.com/auth/
|
5
|
+
uri: https://api.workos.com/auth/challenges/auth_challenge_01FZ4YVRBMXP5ZM0A7BP4AJ12J/verify
|
6
6
|
body:
|
7
7
|
encoding: UTF-8
|
8
|
-
string: '{"
|
8
|
+
string: '{"code":"897792"}'
|
9
9
|
headers:
|
10
10
|
Content-Type:
|
11
11
|
- application/json
|
@@ -2,10 +2,10 @@
|
|
2
2
|
http_interactions:
|
3
3
|
- request:
|
4
4
|
method: post
|
5
|
-
uri: https://api.workos.com/auth/
|
5
|
+
uri: https://api.workos.com/auth/challenges/auth_challenge_01FZ4YVRBMXP5ZM0A7BP4AJ12J/verify
|
6
6
|
body:
|
7
7
|
encoding: UTF-8
|
8
|
-
string: '{"
|
8
|
+
string: '{"code":"897792"}'
|
9
9
|
headers:
|
10
10
|
Content-Type:
|
11
11
|
- application/json
|
@@ -2,10 +2,10 @@
|
|
2
2
|
http_interactions:
|
3
3
|
- request:
|
4
4
|
method: post
|
5
|
-
uri: https://api.workos.com/auth/
|
5
|
+
uri: https://api.workos.com/auth/challenges/auth_challenge_01FZ4YVRBMXP5ZM0A7BP4AJ12J/verify
|
6
6
|
body:
|
7
7
|
encoding: UTF-8
|
8
|
-
string: '{"
|
8
|
+
string: '{"code":"897792"}'
|
9
9
|
headers:
|
10
10
|
Content-Type:
|
11
11
|
- application/json
|
@@ -2,10 +2,10 @@
|
|
2
2
|
http_interactions:
|
3
3
|
- request:
|
4
4
|
method: post
|
5
|
-
uri: https://api.workos.com/auth/
|
5
|
+
uri: https://api.workos.com/auth/challenges/auth_challenge_01FZ4YVRBMXP5ZM0A7BP4AJ12J/verify
|
6
6
|
body:
|
7
7
|
encoding: UTF-8
|
8
|
-
string: '{"
|
8
|
+
string: '{"code":"897792"}'
|
9
9
|
headers:
|
10
10
|
Content-Type:
|
11
11
|
- application/json
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: workos
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- WorkOS
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-07-
|
11
|
+
date: 2022-07-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sorbet-runtime
|
@@ -208,9 +208,9 @@ files:
|
|
208
208
|
- docs/top-level-namespace.html
|
209
209
|
- lib/workos.rb
|
210
210
|
- lib/workos/audit_trail.rb
|
211
|
-
- lib/workos/base.rb
|
212
211
|
- lib/workos/challenge.rb
|
213
212
|
- lib/workos/client.rb
|
213
|
+
- lib/workos/configuration.rb
|
214
214
|
- lib/workos/connection.rb
|
215
215
|
- lib/workos/deprecated_hash_wrapper.rb
|
216
216
|
- lib/workos/directory.rb
|
@@ -241,9 +241,9 @@ files:
|
|
241
241
|
- lib/workos/types/passwordless_session_struct.rb
|
242
242
|
- lib/workos/types/profile_struct.rb
|
243
243
|
- lib/workos/types/provider_enum.rb
|
244
|
-
- lib/workos/types/
|
244
|
+
- lib/workos/types/verify_challenge_struct.rb
|
245
245
|
- lib/workos/types/webhook_struct.rb
|
246
|
-
- lib/workos/
|
246
|
+
- lib/workos/verify_challenge.rb
|
247
247
|
- lib/workos/version.rb
|
248
248
|
- lib/workos/webhook.rb
|
249
249
|
- lib/workos/webhooks.rb
|
@@ -282,7 +282,7 @@ files:
|
|
282
282
|
- sorbet/rbi/sorbet-typed/lib/yard/all/yard.rbi
|
283
283
|
- sorbet/rbi/todo.rbi
|
284
284
|
- spec/lib/workos/audit_trail_spec.rb
|
285
|
-
- spec/lib/workos/
|
285
|
+
- spec/lib/workos/configuration_spec.rb
|
286
286
|
- spec/lib/workos/directory_sync_spec.rb
|
287
287
|
- spec/lib/workos/directory_user_spec.rb
|
288
288
|
- spec/lib/workos/mfa_spec.rb
|
@@ -333,10 +333,10 @@ files:
|
|
333
333
|
- spec/support/fixtures/vcr_cassettes/mfa/enroll_factor_totp_valid.yml
|
334
334
|
- spec/support/fixtures/vcr_cassettes/mfa/get_factor_invalid.yml
|
335
335
|
- spec/support/fixtures/vcr_cassettes/mfa/get_factor_valid.yml
|
336
|
-
- spec/support/fixtures/vcr_cassettes/mfa/
|
337
|
-
- spec/support/fixtures/vcr_cassettes/mfa/
|
338
|
-
- spec/support/fixtures/vcr_cassettes/mfa/
|
339
|
-
- spec/support/fixtures/vcr_cassettes/mfa/
|
336
|
+
- spec/support/fixtures/vcr_cassettes/mfa/verify_challenge_generic_expired.yml
|
337
|
+
- spec/support/fixtures/vcr_cassettes/mfa/verify_challenge_generic_invalid.yml
|
338
|
+
- spec/support/fixtures/vcr_cassettes/mfa/verify_challenge_generic_valid.yml
|
339
|
+
- spec/support/fixtures/vcr_cassettes/mfa/verify_challenge_generic_valid_is_false.yml
|
340
340
|
- spec/support/fixtures/vcr_cassettes/organization/create.yml
|
341
341
|
- spec/support/fixtures/vcr_cassettes/organization/create_invalid.yml
|
342
342
|
- spec/support/fixtures/vcr_cassettes/organization/delete.yml
|
@@ -394,7 +394,7 @@ specification_version: 4
|
|
394
394
|
summary: API client for WorkOS
|
395
395
|
test_files:
|
396
396
|
- spec/lib/workos/audit_trail_spec.rb
|
397
|
-
- spec/lib/workos/
|
397
|
+
- spec/lib/workos/configuration_spec.rb
|
398
398
|
- spec/lib/workos/directory_sync_spec.rb
|
399
399
|
- spec/lib/workos/directory_user_spec.rb
|
400
400
|
- spec/lib/workos/mfa_spec.rb
|
@@ -445,10 +445,10 @@ test_files:
|
|
445
445
|
- spec/support/fixtures/vcr_cassettes/mfa/enroll_factor_totp_valid.yml
|
446
446
|
- spec/support/fixtures/vcr_cassettes/mfa/get_factor_invalid.yml
|
447
447
|
- spec/support/fixtures/vcr_cassettes/mfa/get_factor_valid.yml
|
448
|
-
- spec/support/fixtures/vcr_cassettes/mfa/
|
449
|
-
- spec/support/fixtures/vcr_cassettes/mfa/
|
450
|
-
- spec/support/fixtures/vcr_cassettes/mfa/
|
451
|
-
- spec/support/fixtures/vcr_cassettes/mfa/
|
448
|
+
- spec/support/fixtures/vcr_cassettes/mfa/verify_challenge_generic_expired.yml
|
449
|
+
- spec/support/fixtures/vcr_cassettes/mfa/verify_challenge_generic_invalid.yml
|
450
|
+
- spec/support/fixtures/vcr_cassettes/mfa/verify_challenge_generic_valid.yml
|
451
|
+
- spec/support/fixtures/vcr_cassettes/mfa/verify_challenge_generic_valid_is_false.yml
|
452
452
|
- spec/support/fixtures/vcr_cassettes/organization/create.yml
|
453
453
|
- spec/support/fixtures/vcr_cassettes/organization/create_invalid.yml
|
454
454
|
- spec/support/fixtures/vcr_cassettes/organization/delete.yml
|
data/lib/workos/base.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
# typed: true
|
3
|
-
|
4
|
-
|
5
|
-
module WorkOS
|
6
|
-
## The Base class handles setting and reading the WorkOS
|
7
|
-
## API Key for authentication
|
8
|
-
module Base
|
9
|
-
attr_accessor :key
|
10
|
-
|
11
|
-
class << self
|
12
|
-
extend T::Sig
|
13
|
-
|
14
|
-
attr_writer :key
|
15
|
-
attr_reader :key
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
# typed: false
|
3
|
-
|
4
|
-
module WorkOS
|
5
|
-
module Test
|
6
|
-
class << self
|
7
|
-
include Base
|
8
|
-
include Client
|
9
|
-
|
10
|
-
def request
|
11
|
-
execute_request(request: post_request(path: '/events', body: {}))
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
describe WorkOS::Base do
|
18
|
-
describe '.execute_request' do
|
19
|
-
context 'when unauthenticated' do
|
20
|
-
it 'raises an error' do
|
21
|
-
VCR.use_cassette('base/execute_request_unauthenticated') do
|
22
|
-
expect { WorkOS::Test.request }.to raise_error(
|
23
|
-
WorkOS::AuthenticationError,
|
24
|
-
/Status 401, Unauthorized/,
|
25
|
-
)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|