workos 2.4.0 → 2.5.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/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
|