workos 7.1.0 → 7.1.2
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/.oagen-manifest.json +1 -1
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +16 -0
- data/Gemfile.lock +2 -2
- data/lib/workos/api_keys.rb +1 -1
- data/lib/workos/audit_logs.rb +2 -2
- data/lib/workos/authorization.rb +128 -116
- data/lib/workos/base_client.rb +6 -1
- data/lib/workos/encryptors/aes_gcm.rb +35 -3
- data/lib/workos/groups.rb +1 -1
- data/lib/workos/multi_factor_auth.rb +1 -1
- data/lib/workos/organization_domains.rb +1 -1
- data/lib/workos/radar.rb +2 -2
- data/lib/workos/session.rb +16 -5
- data/lib/workos/sso.rb +2 -2
- data/lib/workos/user_management.rb +74 -65
- data/lib/workos/version.rb +1 -1
- data/lib/workos/webhooks.rb +1 -1
- data/rbi/workos/authorization.rbi +100 -26
- data/rbi/workos/user_management.rbi +60 -14
- data/test/workos/test_audit_logs.rb +2 -2
- data/test/workos/test_authorization.rb +86 -20
- data/test/workos/test_encryptors_aes_gcm.rb +21 -0
- data/test/workos/test_session.rb +193 -0
- data/test/workos/test_user_management.rb +44 -8
- data/test/workos/test_webhooks.rb +2 -2
- metadata +2 -2
|
@@ -6,6 +6,58 @@
|
|
|
6
6
|
|
|
7
7
|
module WorkOS
|
|
8
8
|
class UserManagement
|
|
9
|
+
class PasswordPlaintext
|
|
10
|
+
sig { returns(String) }
|
|
11
|
+
def password; end
|
|
12
|
+
|
|
13
|
+
sig do
|
|
14
|
+
params(
|
|
15
|
+
password: String
|
|
16
|
+
).returns(WorkOS::UserManagement::PasswordPlaintext)
|
|
17
|
+
end
|
|
18
|
+
def self.new(password:); end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class PasswordHashed
|
|
22
|
+
sig { returns(String) }
|
|
23
|
+
def password_hash; end
|
|
24
|
+
|
|
25
|
+
sig { returns(String) }
|
|
26
|
+
def password_hash_type; end
|
|
27
|
+
|
|
28
|
+
sig do
|
|
29
|
+
params(
|
|
30
|
+
password_hash: String,
|
|
31
|
+
password_hash_type: String
|
|
32
|
+
).returns(WorkOS::UserManagement::PasswordHashed)
|
|
33
|
+
end
|
|
34
|
+
def self.new(password_hash:, password_hash_type:); end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class RoleSingle
|
|
38
|
+
sig { returns(String) }
|
|
39
|
+
def role_slug; end
|
|
40
|
+
|
|
41
|
+
sig do
|
|
42
|
+
params(
|
|
43
|
+
role_slug: String
|
|
44
|
+
).returns(WorkOS::UserManagement::RoleSingle)
|
|
45
|
+
end
|
|
46
|
+
def self.new(role_slug:); end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
class RoleMultiple
|
|
50
|
+
sig { returns(T::Array[String]) }
|
|
51
|
+
def role_slugs; end
|
|
52
|
+
|
|
53
|
+
sig do
|
|
54
|
+
params(
|
|
55
|
+
role_slugs: T::Array[String]
|
|
56
|
+
).returns(WorkOS::UserManagement::RoleMultiple)
|
|
57
|
+
end
|
|
58
|
+
def self.new(role_slugs:); end
|
|
59
|
+
end
|
|
60
|
+
|
|
9
61
|
sig { params(client: WorkOS::BaseClient).void }
|
|
10
62
|
def initialize(client); end
|
|
11
63
|
|
|
@@ -113,13 +165,11 @@ module WorkOS
|
|
|
113
165
|
email_verified: T.nilable(T::Boolean),
|
|
114
166
|
metadata: T.nilable(T::Hash[String, String]),
|
|
115
167
|
external_id: T.nilable(String),
|
|
116
|
-
password: T.nilable(
|
|
117
|
-
password_hash: T.nilable(String),
|
|
118
|
-
password_hash_type: T.nilable(String),
|
|
168
|
+
password: T.nilable(T.any(WorkOS::UserManagement::PasswordPlaintext, WorkOS::UserManagement::PasswordHashed)),
|
|
119
169
|
request_options: T::Hash[Symbol, T.untyped]
|
|
120
170
|
).returns(WorkOS::User)
|
|
121
171
|
end
|
|
122
|
-
def create_user(email:, first_name:, last_name:, email_verified:, metadata:, external_id:, password:,
|
|
172
|
+
def create_user(email:, first_name:, last_name:, email_verified:, metadata:, external_id:, password:, request_options:); end
|
|
123
173
|
|
|
124
174
|
sig do
|
|
125
175
|
params(
|
|
@@ -147,13 +197,11 @@ module WorkOS
|
|
|
147
197
|
metadata: T.nilable(T::Hash[String, String]),
|
|
148
198
|
external_id: T.nilable(String),
|
|
149
199
|
locale: T.nilable(String),
|
|
150
|
-
password: T.nilable(
|
|
151
|
-
password_hash: T.nilable(String),
|
|
152
|
-
password_hash_type: T.nilable(String),
|
|
200
|
+
password: T.nilable(T.any(WorkOS::UserManagement::PasswordPlaintext, WorkOS::UserManagement::PasswordHashed)),
|
|
153
201
|
request_options: T::Hash[Symbol, T.untyped]
|
|
154
202
|
).returns(WorkOS::User)
|
|
155
203
|
end
|
|
156
|
-
def update_user(id:, email:, first_name:, last_name:, email_verified:, metadata:, external_id:, locale:, password:,
|
|
204
|
+
def update_user(id:, email:, first_name:, last_name:, email_verified:, metadata:, external_id:, locale:, password:, request_options:); end
|
|
157
205
|
|
|
158
206
|
sig do
|
|
159
207
|
params(
|
|
@@ -328,12 +376,11 @@ module WorkOS
|
|
|
328
376
|
params(
|
|
329
377
|
user_id: String,
|
|
330
378
|
organization_id: String,
|
|
331
|
-
|
|
332
|
-
role_slugs: T.nilable(T::Array[String]),
|
|
379
|
+
role: T.nilable(T.any(WorkOS::UserManagement::RoleSingle, WorkOS::UserManagement::RoleMultiple)),
|
|
333
380
|
request_options: T::Hash[Symbol, T.untyped]
|
|
334
381
|
).returns(WorkOS::OrganizationMembership)
|
|
335
382
|
end
|
|
336
|
-
def create_organization_membership(user_id:, organization_id:,
|
|
383
|
+
def create_organization_membership(user_id:, organization_id:, role:, request_options:); end
|
|
337
384
|
|
|
338
385
|
sig do
|
|
339
386
|
params(
|
|
@@ -346,12 +393,11 @@ module WorkOS
|
|
|
346
393
|
sig do
|
|
347
394
|
params(
|
|
348
395
|
id: String,
|
|
349
|
-
|
|
350
|
-
role_slugs: T.nilable(T::Array[String]),
|
|
396
|
+
role: T.nilable(T.any(WorkOS::UserManagement::RoleSingle, WorkOS::UserManagement::RoleMultiple)),
|
|
351
397
|
request_options: T::Hash[Symbol, T.untyped]
|
|
352
398
|
).returns(WorkOS::UserOrganizationMembership)
|
|
353
399
|
end
|
|
354
|
-
def update_organization_membership(id:,
|
|
400
|
+
def update_organization_membership(id:, role:, request_options:); end
|
|
355
401
|
|
|
356
402
|
sig do
|
|
357
403
|
params(
|
|
@@ -42,7 +42,7 @@ class AuditLogsTest < Minitest::Test
|
|
|
42
42
|
def test_create_schema_returns_expected_result
|
|
43
43
|
stub_request(:post, %r{\Ahttps://api\.workos\.com/audit_logs/actions/stub/schemas(\?|\z)})
|
|
44
44
|
.to_return(body: "{}", status: 200)
|
|
45
|
-
result = @client.audit_logs.create_schema(action_name: "stub", targets: [])
|
|
45
|
+
result = @client.audit_logs.create_schema(action_name: "stub", targets: [{}])
|
|
46
46
|
refute_nil result
|
|
47
47
|
end
|
|
48
48
|
|
|
@@ -73,7 +73,7 @@ class AuditLogsTest < Minitest::Test
|
|
|
73
73
|
{name: :update_organization_audit_logs_retention, verb: :put, url: %r{\Ahttps://api\.workos\.com/organizations/stub/audit_logs_retention(\?|\z)}, args: {id: "stub", retention_period_in_days: 1}},
|
|
74
74
|
{name: :list_actions, verb: :get, url: %r{\Ahttps://api\.workos\.com/audit_logs/actions(\?|\z)}},
|
|
75
75
|
{name: :list_action_schemas, verb: :get, url: %r{\Ahttps://api\.workos\.com/audit_logs/actions/stub/schemas(\?|\z)}, args: {action_name: "stub"}},
|
|
76
|
-
{name: :create_schema, verb: :post, url: %r{\Ahttps://api\.workos\.com/audit_logs/actions/stub/schemas(\?|\z)}, args: {action_name: "stub", targets: []}},
|
|
76
|
+
{name: :create_schema, verb: :post, url: %r{\Ahttps://api\.workos\.com/audit_logs/actions/stub/schemas(\?|\z)}, args: {action_name: "stub", targets: [{}]}},
|
|
77
77
|
{name: :create_event, verb: :post, url: %r{\Ahttps://api\.workos\.com/audit_logs/events(\?|\z)}, args: {organization_id: "stub", event: {}}},
|
|
78
78
|
{name: :create_export, verb: :post, url: %r{\Ahttps://api\.workos\.com/audit_logs/exports(\?|\z)}, args: {organization_id: "stub", range_start: "stub", range_end: "stub"}},
|
|
79
79
|
{name: :get_export, verb: :get, url: %r{\Ahttps://api\.workos\.com/audit_logs/exports/stub(\?|\z)}, args: {audit_log_export_id: "stub"}}
|
|
@@ -13,15 +13,31 @@ class AuthorizationTest < Minitest::Test
|
|
|
13
13
|
|
|
14
14
|
def test_check_returns_expected_result
|
|
15
15
|
stub_request(:post, %r{\Ahttps://api\.workos\.com/authorization/organization_memberships/stub/check(\?|\z)})
|
|
16
|
+
.with(body: hash_including("permission_slug" => "stub", "resource_id" => "stub"))
|
|
16
17
|
.to_return(body: "{}", status: 200)
|
|
17
|
-
result = @client.authorization.check(organization_membership_id: "stub", permission_slug: "stub", resource_target:
|
|
18
|
+
result = @client.authorization.check(organization_membership_id: "stub", permission_slug: "stub", resource_target: WorkOS::Authorization::ResourceTargetById.new(resource_id: "stub"))
|
|
19
|
+
refute_nil result
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def test_check_with_resource_target_by_external_id_returns_expected_result
|
|
23
|
+
stub_request(:post, %r{\Ahttps://api\.workos\.com/authorization/organization_memberships/stub/check(\?|\z)})
|
|
24
|
+
.with(body: hash_including("permission_slug" => "stub", "resource_external_id" => "stub", "resource_type_slug" => "stub"))
|
|
25
|
+
.to_return(body: "{}", status: 200)
|
|
26
|
+
result = @client.authorization.check(organization_membership_id: "stub", permission_slug: "stub", resource_target: WorkOS::Authorization::ResourceTargetByExternalId.new(resource_external_id: "stub", resource_type_slug: "stub"))
|
|
18
27
|
refute_nil result
|
|
19
28
|
end
|
|
20
29
|
|
|
21
30
|
def test_list_resources_for_membership_returns_expected_result
|
|
22
31
|
stub_request(:get, %r{\Ahttps://api\.workos\.com/authorization/organization_memberships/stub/resources(\?|\z)})
|
|
23
32
|
.to_return(body: '{"data": [], "list_metadata": {}}', status: 200)
|
|
24
|
-
result = @client.authorization.list_resources_for_membership(organization_membership_id: "stub", permission_slug: "stub", parent_resource:
|
|
33
|
+
result = @client.authorization.list_resources_for_membership(organization_membership_id: "stub", permission_slug: "stub", parent_resource: WorkOS::Authorization::ParentResourceById.new(parent_resource_id: "stub"))
|
|
34
|
+
assert_kind_of WorkOS::Types::ListStruct, result
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def test_list_resources_for_membership_with_parent_resource_by_external_id_returns_expected_result
|
|
38
|
+
stub_request(:get, %r{\Ahttps://api\.workos\.com/authorization/organization_memberships/stub/resources(\?|\z)})
|
|
39
|
+
.to_return(body: '{"data": [], "list_metadata": {}}', status: 200)
|
|
40
|
+
result = @client.authorization.list_resources_for_membership(organization_membership_id: "stub", permission_slug: "stub", parent_resource: WorkOS::Authorization::ParentResourceByExternalId.new(parent_resource_type_slug: "stub", parent_resource_external_id: "stub"))
|
|
25
41
|
assert_kind_of WorkOS::Types::ListStruct, result
|
|
26
42
|
end
|
|
27
43
|
|
|
@@ -48,15 +64,31 @@ class AuthorizationTest < Minitest::Test
|
|
|
48
64
|
|
|
49
65
|
def test_assign_role_returns_expected_result
|
|
50
66
|
stub_request(:post, %r{\Ahttps://api\.workos\.com/authorization/organization_memberships/stub/role_assignments(\?|\z)})
|
|
67
|
+
.with(body: hash_including("role_slug" => "stub", "resource_id" => "stub"))
|
|
51
68
|
.to_return(body: "{}", status: 200)
|
|
52
|
-
result = @client.authorization.assign_role(organization_membership_id: "stub", role_slug: "stub", resource_target:
|
|
69
|
+
result = @client.authorization.assign_role(organization_membership_id: "stub", role_slug: "stub", resource_target: WorkOS::Authorization::ResourceTargetById.new(resource_id: "stub"))
|
|
70
|
+
refute_nil result
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def test_assign_role_with_resource_target_by_external_id_returns_expected_result
|
|
74
|
+
stub_request(:post, %r{\Ahttps://api\.workos\.com/authorization/organization_memberships/stub/role_assignments(\?|\z)})
|
|
75
|
+
.with(body: hash_including("role_slug" => "stub", "resource_external_id" => "stub", "resource_type_slug" => "stub"))
|
|
76
|
+
.to_return(body: "{}", status: 200)
|
|
77
|
+
result = @client.authorization.assign_role(organization_membership_id: "stub", role_slug: "stub", resource_target: WorkOS::Authorization::ResourceTargetByExternalId.new(resource_external_id: "stub", resource_type_slug: "stub"))
|
|
53
78
|
refute_nil result
|
|
54
79
|
end
|
|
55
80
|
|
|
56
81
|
def test_remove_role_returns_expected_result
|
|
57
82
|
stub_request(:delete, %r{\Ahttps://api\.workos\.com/authorization/organization_memberships/stub/role_assignments(\?|\z)})
|
|
58
83
|
.to_return(body: "{}", status: 200)
|
|
59
|
-
result = @client.authorization.remove_role(organization_membership_id: "stub", role_slug: "stub", resource_target:
|
|
84
|
+
result = @client.authorization.remove_role(organization_membership_id: "stub", role_slug: "stub", resource_target: WorkOS::Authorization::ResourceTargetById.new(resource_id: "stub"))
|
|
85
|
+
assert_nil result
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def test_remove_role_with_resource_target_by_external_id_returns_expected_result
|
|
89
|
+
stub_request(:delete, %r{\Ahttps://api\.workos\.com/authorization/organization_memberships/stub/role_assignments(\?|\z)})
|
|
90
|
+
.to_return(body: "{}", status: 200)
|
|
91
|
+
result = @client.authorization.remove_role(organization_membership_id: "stub", role_slug: "stub", resource_target: WorkOS::Authorization::ResourceTargetByExternalId.new(resource_external_id: "stub", resource_type_slug: "stub"))
|
|
60
92
|
assert_nil result
|
|
61
93
|
end
|
|
62
94
|
|
|
@@ -112,7 +144,7 @@ class AuthorizationTest < Minitest::Test
|
|
|
112
144
|
def test_set_organization_role_permissions_returns_expected_result
|
|
113
145
|
stub_request(:put, %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/roles/stub/permissions(\?|\z)})
|
|
114
146
|
.to_return(body: "{}", status: 200)
|
|
115
|
-
result = @client.authorization.set_organization_role_permissions(organization_id: "stub", slug: "stub", permissions: [])
|
|
147
|
+
result = @client.authorization.set_organization_role_permissions(organization_id: "stub", slug: "stub", permissions: ["stub"])
|
|
116
148
|
refute_nil result
|
|
117
149
|
end
|
|
118
150
|
|
|
@@ -132,8 +164,17 @@ class AuthorizationTest < Minitest::Test
|
|
|
132
164
|
|
|
133
165
|
def test_update_resource_by_external_id_returns_expected_result
|
|
134
166
|
stub_request(:patch, %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/resources/stub/stub(\?|\z)})
|
|
167
|
+
.with(body: hash_including("parent_resource_id" => "stub"))
|
|
135
168
|
.to_return(body: "{}", status: 200)
|
|
136
|
-
result = @client.authorization.update_resource_by_external_id(organization_id: "stub", resource_type_slug: "stub", external_id: "stub")
|
|
169
|
+
result = @client.authorization.update_resource_by_external_id(organization_id: "stub", resource_type_slug: "stub", external_id: "stub", parent_resource: WorkOS::Authorization::ParentResourceById.new(parent_resource_id: "stub"))
|
|
170
|
+
refute_nil result
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def test_update_resource_by_external_id_with_parent_resource_by_external_id_returns_expected_result
|
|
174
|
+
stub_request(:patch, %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/resources/stub/stub(\?|\z)})
|
|
175
|
+
.with(body: hash_including("parent_resource_external_id" => "stub", "parent_resource_type_slug" => "stub"))
|
|
176
|
+
.to_return(body: "{}", status: 200)
|
|
177
|
+
result = @client.authorization.update_resource_by_external_id(organization_id: "stub", resource_type_slug: "stub", external_id: "stub", parent_resource: WorkOS::Authorization::ParentResourceByExternalId.new(parent_resource_external_id: "stub", parent_resource_type_slug: "stub"))
|
|
137
178
|
refute_nil result
|
|
138
179
|
end
|
|
139
180
|
|
|
@@ -154,14 +195,30 @@ class AuthorizationTest < Minitest::Test
|
|
|
154
195
|
def test_list_resources_returns_expected_result
|
|
155
196
|
stub_request(:get, %r{\Ahttps://api\.workos\.com/authorization/resources(\?|\z)})
|
|
156
197
|
.to_return(body: '{"data": [], "list_metadata": {}}', status: 200)
|
|
157
|
-
result = @client.authorization.list_resources
|
|
198
|
+
result = @client.authorization.list_resources(parent: WorkOS::Authorization::ParentById.new(parent_resource_id: "stub"))
|
|
199
|
+
assert_kind_of WorkOS::Types::ListStruct, result
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def test_list_resources_with_parent_by_external_id_returns_expected_result
|
|
203
|
+
stub_request(:get, %r{\Ahttps://api\.workos\.com/authorization/resources(\?|\z)})
|
|
204
|
+
.to_return(body: '{"data": [], "list_metadata": {}}', status: 200)
|
|
205
|
+
result = @client.authorization.list_resources(parent: WorkOS::Authorization::ParentByExternalId.new(parent_resource_type_slug: "stub", parent_external_id: "stub"))
|
|
158
206
|
assert_kind_of WorkOS::Types::ListStruct, result
|
|
159
207
|
end
|
|
160
208
|
|
|
161
209
|
def test_create_resource_returns_expected_result
|
|
162
210
|
stub_request(:post, %r{\Ahttps://api\.workos\.com/authorization/resources(\?|\z)})
|
|
211
|
+
.with(body: hash_including("external_id" => "stub", "name" => "stub", "resource_type_slug" => "stub", "organization_id" => "stub", "parent_resource_id" => "stub"))
|
|
163
212
|
.to_return(body: "{}", status: 200)
|
|
164
|
-
result = @client.authorization.create_resource(external_id: "stub", name: "stub", resource_type_slug: "stub", organization_id: "stub")
|
|
213
|
+
result = @client.authorization.create_resource(external_id: "stub", name: "stub", resource_type_slug: "stub", organization_id: "stub", parent_resource: WorkOS::Authorization::ParentResourceById.new(parent_resource_id: "stub"))
|
|
214
|
+
refute_nil result
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def test_create_resource_with_parent_resource_by_external_id_returns_expected_result
|
|
218
|
+
stub_request(:post, %r{\Ahttps://api\.workos\.com/authorization/resources(\?|\z)})
|
|
219
|
+
.with(body: hash_including("external_id" => "stub", "name" => "stub", "resource_type_slug" => "stub", "organization_id" => "stub", "parent_resource_external_id" => "stub", "parent_resource_type_slug" => "stub"))
|
|
220
|
+
.to_return(body: "{}", status: 200)
|
|
221
|
+
result = @client.authorization.create_resource(external_id: "stub", name: "stub", resource_type_slug: "stub", organization_id: "stub", parent_resource: WorkOS::Authorization::ParentResourceByExternalId.new(parent_resource_external_id: "stub", parent_resource_type_slug: "stub"))
|
|
165
222
|
refute_nil result
|
|
166
223
|
end
|
|
167
224
|
|
|
@@ -174,8 +231,17 @@ class AuthorizationTest < Minitest::Test
|
|
|
174
231
|
|
|
175
232
|
def test_update_resource_returns_expected_result
|
|
176
233
|
stub_request(:patch, %r{\Ahttps://api\.workos\.com/authorization/resources/stub(\?|\z)})
|
|
234
|
+
.with(body: hash_including("parent_resource_id" => "stub"))
|
|
235
|
+
.to_return(body: "{}", status: 200)
|
|
236
|
+
result = @client.authorization.update_resource(resource_id: "stub", parent_resource: WorkOS::Authorization::ParentResourceById.new(parent_resource_id: "stub"))
|
|
237
|
+
refute_nil result
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def test_update_resource_with_parent_resource_by_external_id_returns_expected_result
|
|
241
|
+
stub_request(:patch, %r{\Ahttps://api\.workos\.com/authorization/resources/stub(\?|\z)})
|
|
242
|
+
.with(body: hash_including("parent_resource_external_id" => "stub", "parent_resource_type_slug" => "stub"))
|
|
177
243
|
.to_return(body: "{}", status: 200)
|
|
178
|
-
result = @client.authorization.update_resource(resource_id: "stub")
|
|
244
|
+
result = @client.authorization.update_resource(resource_id: "stub", parent_resource: WorkOS::Authorization::ParentResourceByExternalId.new(parent_resource_external_id: "stub", parent_resource_type_slug: "stub"))
|
|
179
245
|
refute_nil result
|
|
180
246
|
end
|
|
181
247
|
|
|
@@ -231,7 +297,7 @@ class AuthorizationTest < Minitest::Test
|
|
|
231
297
|
def test_set_environment_role_permissions_returns_expected_result
|
|
232
298
|
stub_request(:put, %r{\Ahttps://api\.workos\.com/authorization/roles/stub/permissions(\?|\z)})
|
|
233
299
|
.to_return(body: "{}", status: 200)
|
|
234
|
-
result = @client.authorization.set_environment_role_permissions(slug: "stub", permissions: [])
|
|
300
|
+
result = @client.authorization.set_environment_role_permissions(slug: "stub", permissions: ["stub"])
|
|
235
301
|
refute_nil result
|
|
236
302
|
end
|
|
237
303
|
|
|
@@ -272,13 +338,13 @@ class AuthorizationTest < Minitest::Test
|
|
|
272
338
|
|
|
273
339
|
# Parameterized authentication error tests (one per endpoint).
|
|
274
340
|
[
|
|
275
|
-
{name: :check, verb: :post, url: %r{\Ahttps://api\.workos\.com/authorization/organization_memberships/stub/check(\?|\z)}, args: {organization_membership_id: "stub", permission_slug: "stub", resource_target:
|
|
276
|
-
{name: :list_resources_for_membership, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/organization_memberships/stub/resources(\?|\z)}, args: {organization_membership_id: "stub", permission_slug: "stub", parent_resource:
|
|
341
|
+
{name: :check, verb: :post, url: %r{\Ahttps://api\.workos\.com/authorization/organization_memberships/stub/check(\?|\z)}, args: {organization_membership_id: "stub", permission_slug: "stub", resource_target: WorkOS::Authorization::ResourceTargetById.new(resource_id: "stub")}},
|
|
342
|
+
{name: :list_resources_for_membership, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/organization_memberships/stub/resources(\?|\z)}, args: {organization_membership_id: "stub", permission_slug: "stub", parent_resource: WorkOS::Authorization::ParentResourceById.new(parent_resource_id: "stub")}},
|
|
277
343
|
{name: :list_effective_permissions, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/organization_memberships/stub/resources/stub/permissions(\?|\z)}, args: {organization_membership_id: "stub", resource_id: "stub"}},
|
|
278
344
|
{name: :list_effective_permissions_by_external_id, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/organization_memberships/stub/resources/stub/stub/permissions(\?|\z)}, args: {organization_membership_id: "stub", resource_type_slug: "stub", external_id: "stub"}},
|
|
279
345
|
{name: :list_role_assignments, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/organization_memberships/stub/role_assignments(\?|\z)}, args: {organization_membership_id: "stub"}},
|
|
280
|
-
{name: :assign_role, verb: :post, url: %r{\Ahttps://api\.workos\.com/authorization/organization_memberships/stub/role_assignments(\?|\z)}, args: {organization_membership_id: "stub", role_slug: "stub", resource_target:
|
|
281
|
-
{name: :remove_role, verb: :delete, url: %r{\Ahttps://api\.workos\.com/authorization/organization_memberships/stub/role_assignments(\?|\z)}, args: {organization_membership_id: "stub", role_slug: "stub", resource_target:
|
|
346
|
+
{name: :assign_role, verb: :post, url: %r{\Ahttps://api\.workos\.com/authorization/organization_memberships/stub/role_assignments(\?|\z)}, args: {organization_membership_id: "stub", role_slug: "stub", resource_target: WorkOS::Authorization::ResourceTargetById.new(resource_id: "stub")}},
|
|
347
|
+
{name: :remove_role, verb: :delete, url: %r{\Ahttps://api\.workos\.com/authorization/organization_memberships/stub/role_assignments(\?|\z)}, args: {organization_membership_id: "stub", role_slug: "stub", resource_target: WorkOS::Authorization::ResourceTargetById.new(resource_id: "stub")}},
|
|
282
348
|
{name: :remove_role_assignment, verb: :delete, url: %r{\Ahttps://api\.workos\.com/authorization/organization_memberships/stub/role_assignments/stub(\?|\z)}, args: {organization_membership_id: "stub", role_assignment_id: "stub"}},
|
|
283
349
|
{name: :list_organization_roles, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/roles(\?|\z)}, args: {organization_id: "stub"}},
|
|
284
350
|
{name: :create_organization_role, verb: :post, url: %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/roles(\?|\z)}, args: {organization_id: "stub", name: "stub"}},
|
|
@@ -286,16 +352,16 @@ class AuthorizationTest < Minitest::Test
|
|
|
286
352
|
{name: :update_organization_role, verb: :patch, url: %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/roles/stub(\?|\z)}, args: {organization_id: "stub", slug: "stub"}},
|
|
287
353
|
{name: :delete_organization_role, verb: :delete, url: %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/roles/stub(\?|\z)}, args: {organization_id: "stub", slug: "stub"}},
|
|
288
354
|
{name: :add_organization_role_permission, verb: :post, url: %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/roles/stub/permissions(\?|\z)}, args: {organization_id: "stub", slug: "stub", body_slug: "stub"}},
|
|
289
|
-
{name: :set_organization_role_permissions, verb: :put, url: %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/roles/stub/permissions(\?|\z)}, args: {organization_id: "stub", slug: "stub", permissions: []}},
|
|
355
|
+
{name: :set_organization_role_permissions, verb: :put, url: %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/roles/stub/permissions(\?|\z)}, args: {organization_id: "stub", slug: "stub", permissions: ["stub"]}},
|
|
290
356
|
{name: :remove_organization_role_permission, verb: :delete, url: %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/roles/stub/permissions/stub(\?|\z)}, args: {organization_id: "stub", slug: "stub", permission_slug: "stub"}},
|
|
291
357
|
{name: :get_resource_by_external_id, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/resources/stub/stub(\?|\z)}, args: {organization_id: "stub", resource_type_slug: "stub", external_id: "stub"}},
|
|
292
|
-
{name: :update_resource_by_external_id, verb: :patch, url: %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/resources/stub/stub(\?|\z)}, args: {organization_id: "stub", resource_type_slug: "stub", external_id: "stub"}},
|
|
358
|
+
{name: :update_resource_by_external_id, verb: :patch, url: %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/resources/stub/stub(\?|\z)}, args: {organization_id: "stub", resource_type_slug: "stub", external_id: "stub", parent_resource: WorkOS::Authorization::ParentResourceById.new(parent_resource_id: "stub")}},
|
|
293
359
|
{name: :delete_resource_by_external_id, verb: :delete, url: %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/resources/stub/stub(\?|\z)}, args: {organization_id: "stub", resource_type_slug: "stub", external_id: "stub"}},
|
|
294
360
|
{name: :list_memberships_for_resource_by_external_id, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/resources/stub/stub/organization_memberships(\?|\z)}, args: {organization_id: "stub", resource_type_slug: "stub", external_id: "stub", permission_slug: "stub"}},
|
|
295
|
-
{name: :list_resources, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/resources(\?|\z)}},
|
|
296
|
-
{name: :create_resource, verb: :post, url: %r{\Ahttps://api\.workos\.com/authorization/resources(\?|\z)}, args: {external_id: "stub", name: "stub", resource_type_slug: "stub", organization_id: "stub"}},
|
|
361
|
+
{name: :list_resources, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/resources(\?|\z)}, args: {parent: WorkOS::Authorization::ParentById.new(parent_resource_id: "stub")}},
|
|
362
|
+
{name: :create_resource, verb: :post, url: %r{\Ahttps://api\.workos\.com/authorization/resources(\?|\z)}, args: {external_id: "stub", name: "stub", resource_type_slug: "stub", organization_id: "stub", parent_resource: WorkOS::Authorization::ParentResourceById.new(parent_resource_id: "stub")}},
|
|
297
363
|
{name: :get_resource, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/resources/stub(\?|\z)}, args: {resource_id: "stub"}},
|
|
298
|
-
{name: :update_resource, verb: :patch, url: %r{\Ahttps://api\.workos\.com/authorization/resources/stub(\?|\z)}, args: {resource_id: "stub"}},
|
|
364
|
+
{name: :update_resource, verb: :patch, url: %r{\Ahttps://api\.workos\.com/authorization/resources/stub(\?|\z)}, args: {resource_id: "stub", parent_resource: WorkOS::Authorization::ParentResourceById.new(parent_resource_id: "stub")}},
|
|
299
365
|
{name: :delete_resource, verb: :delete, url: %r{\Ahttps://api\.workos\.com/authorization/resources/stub(\?|\z)}, args: {resource_id: "stub"}},
|
|
300
366
|
{name: :list_memberships_for_resource, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/resources/stub/organization_memberships(\?|\z)}, args: {resource_id: "stub", permission_slug: "stub"}},
|
|
301
367
|
{name: :list_environment_roles, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/roles(\?|\z)}},
|
|
@@ -303,7 +369,7 @@ class AuthorizationTest < Minitest::Test
|
|
|
303
369
|
{name: :get_environment_role, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/roles/stub(\?|\z)}, args: {slug: "stub"}},
|
|
304
370
|
{name: :update_environment_role, verb: :patch, url: %r{\Ahttps://api\.workos\.com/authorization/roles/stub(\?|\z)}, args: {slug: "stub"}},
|
|
305
371
|
{name: :add_environment_role_permission, verb: :post, url: %r{\Ahttps://api\.workos\.com/authorization/roles/stub/permissions(\?|\z)}, args: {slug: "stub", body_slug: "stub"}},
|
|
306
|
-
{name: :set_environment_role_permissions, verb: :put, url: %r{\Ahttps://api\.workos\.com/authorization/roles/stub/permissions(\?|\z)}, args: {slug: "stub", permissions: []}},
|
|
372
|
+
{name: :set_environment_role_permissions, verb: :put, url: %r{\Ahttps://api\.workos\.com/authorization/roles/stub/permissions(\?|\z)}, args: {slug: "stub", permissions: ["stub"]}},
|
|
307
373
|
{name: :list_permissions, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/permissions(\?|\z)}},
|
|
308
374
|
{name: :create_permission, verb: :post, url: %r{\Ahttps://api\.workos\.com/authorization/permissions(\?|\z)}, args: {slug: "stub", name: "stub"}},
|
|
309
375
|
{name: :get_permission, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/permissions/stub(\?|\z)}, args: {slug: "stub"}},
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
# @oagen-ignore-file
|
|
4
4
|
require "test_helper"
|
|
5
5
|
require "base64"
|
|
6
|
+
require "json"
|
|
7
|
+
require "openssl"
|
|
8
|
+
require "securerandom"
|
|
6
9
|
|
|
7
10
|
class EncryptorsAesGcmTest < Minitest::Test
|
|
8
11
|
PASSWORD = "test-cookie-password-at-least-32"
|
|
@@ -51,4 +54,22 @@ class EncryptorsAesGcmTest < Minitest::Test
|
|
|
51
54
|
sealed2 = @enc.seal(data, PASSWORD)
|
|
52
55
|
refute_equal sealed1, sealed2
|
|
53
56
|
end
|
|
57
|
+
|
|
58
|
+
def test_unseal_reads_legacy_v6_payload
|
|
59
|
+
data = {"access_token" => "tok_abc", "refresh_token" => "ref_xyz"}
|
|
60
|
+
sealed = legacy_v6_seal(data, PASSWORD)
|
|
61
|
+
assert_equal data, @enc.unseal(sealed, PASSWORD)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
def legacy_v6_seal(data, key)
|
|
67
|
+
cipher = OpenSSL::Cipher.new("aes-256-gcm").encrypt
|
|
68
|
+
iv = SecureRandom.random_bytes(12)
|
|
69
|
+
cipher.key = key
|
|
70
|
+
cipher.iv = iv
|
|
71
|
+
ciphertext = cipher.update(JSON.generate(data)) + cipher.final
|
|
72
|
+
|
|
73
|
+
Base64.encode64(iv + ciphertext + cipher.auth_tag)
|
|
74
|
+
end
|
|
54
75
|
end
|
data/test/workos/test_session.rb
CHANGED
|
@@ -6,6 +6,7 @@ require "json"
|
|
|
6
6
|
require "openssl"
|
|
7
7
|
require "jwt"
|
|
8
8
|
require "base64"
|
|
9
|
+
require "securerandom"
|
|
9
10
|
|
|
10
11
|
class SessionTest < Minitest::Test
|
|
11
12
|
PASSWORD = "very-long-cookie-password-secret"
|
|
@@ -84,6 +85,22 @@ class SessionTest < Minitest::Test
|
|
|
84
85
|
assert_equal "u_1", result.user["id"]
|
|
85
86
|
end
|
|
86
87
|
|
|
88
|
+
def test_authenticate_reads_legacy_v6_sealed_session
|
|
89
|
+
rsa, pub = signing_key_pair
|
|
90
|
+
access_token = make_jwt({"sid" => "session_v6", "org_id" => "org_legacy", "exp" => Time.now.to_i + 60}, rsa)
|
|
91
|
+
sealed = legacy_v6_seal({"access_token" => access_token, "user" => {"id" => "u_legacy"}}, PASSWORD)
|
|
92
|
+
|
|
93
|
+
stub_request(:get, "https://api.workos.com/sso/jwks/client_001")
|
|
94
|
+
.to_return(status: 200, body: jwks_payload(pub).to_json)
|
|
95
|
+
|
|
96
|
+
result = @sm.authenticate(seal_data: sealed, cookie_password: PASSWORD)
|
|
97
|
+
assert_kind_of WorkOS::SessionManager::AuthSuccess, result
|
|
98
|
+
assert result.authenticated
|
|
99
|
+
assert_equal "session_v6", result.session_id
|
|
100
|
+
assert_equal "org_legacy", result.organization_id
|
|
101
|
+
assert_equal "u_legacy", result.user["id"]
|
|
102
|
+
end
|
|
103
|
+
|
|
87
104
|
def test_authenticate_merges_custom_claims_from_block
|
|
88
105
|
rsa, pub = signing_key_pair
|
|
89
106
|
access_token = make_jwt(
|
|
@@ -206,6 +223,170 @@ class SessionTest < Minitest::Test
|
|
|
206
223
|
assert_equal "https://app/cb", params["return_to"]
|
|
207
224
|
end
|
|
208
225
|
|
|
226
|
+
# --- Session#refresh -------------------------------------------------------
|
|
227
|
+
|
|
228
|
+
def test_refresh_seals_session_client_side_and_returns_refresh_success
|
|
229
|
+
rsa, pub = signing_key_pair
|
|
230
|
+
old_access = make_jwt({"sid" => "session_old", "exp" => Time.now.to_i - 60}, rsa)
|
|
231
|
+
sealed = @sm.seal_data({"access_token" => old_access, "refresh_token" => "rt_old", "user" => {"id" => "u_1"}}, PASSWORD)
|
|
232
|
+
|
|
233
|
+
new_access = make_jwt({"sid" => "session_new", "org_id" => "org_1", "role" => "admin", "exp" => Time.now.to_i + 300}, rsa)
|
|
234
|
+
api_response = {
|
|
235
|
+
"access_token" => new_access,
|
|
236
|
+
"refresh_token" => "rt_new",
|
|
237
|
+
"user" => {"id" => "u_1", "email" => "a@b.com"},
|
|
238
|
+
"impersonator" => nil
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
stub_request(:post, "https://api.workos.com/user_management/authenticate")
|
|
242
|
+
.with(body: hash_including("grant_type" => "refresh_token", "refresh_token" => "rt_old"))
|
|
243
|
+
.to_return(status: 200, body: api_response.to_json)
|
|
244
|
+
stub_request(:get, "https://api.workos.com/sso/jwks/client_001")
|
|
245
|
+
.to_return(status: 200, body: jwks_payload(pub).to_json)
|
|
246
|
+
|
|
247
|
+
session = @sm.load(seal_data: sealed, cookie_password: PASSWORD)
|
|
248
|
+
result = session.refresh
|
|
249
|
+
|
|
250
|
+
assert_kind_of WorkOS::SessionManager::RefreshSuccess, result
|
|
251
|
+
assert result.authenticated
|
|
252
|
+
assert_equal "session_new", result.session_id
|
|
253
|
+
assert_equal "org_1", result.organization_id
|
|
254
|
+
assert_equal "admin", result.role
|
|
255
|
+
assert_equal "u_1", result.user["id"]
|
|
256
|
+
|
|
257
|
+
# sealed_session should be a non-empty string that round-trips
|
|
258
|
+
refute_empty result.sealed_session
|
|
259
|
+
unsealed = @sm.unseal_data(result.sealed_session, PASSWORD)
|
|
260
|
+
assert_equal new_access, unsealed["access_token"]
|
|
261
|
+
assert_equal "rt_new", unsealed["refresh_token"]
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def test_refresh_reads_legacy_v6_sealed_session
|
|
265
|
+
rsa, pub = signing_key_pair
|
|
266
|
+
old_access = make_jwt({"sid" => "session_old_v6", "exp" => Time.now.to_i - 60}, rsa)
|
|
267
|
+
sealed = legacy_v6_seal(
|
|
268
|
+
{"access_token" => old_access, "refresh_token" => "rt_old_v6", "user" => {"id" => "u_v6"}},
|
|
269
|
+
PASSWORD
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
new_access = make_jwt({"sid" => "session_new_v6", "org_id" => "org_v6", "role" => "member", "exp" => Time.now.to_i + 300}, rsa)
|
|
273
|
+
api_response = {
|
|
274
|
+
"access_token" => new_access,
|
|
275
|
+
"refresh_token" => "rt_new_v6",
|
|
276
|
+
"user" => {"id" => "u_v6", "email" => "legacy@example.com"},
|
|
277
|
+
"impersonator" => nil
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
stub_request(:post, "https://api.workos.com/user_management/authenticate")
|
|
281
|
+
.with(body: hash_including("grant_type" => "refresh_token", "refresh_token" => "rt_old_v6"))
|
|
282
|
+
.to_return(status: 200, body: api_response.to_json)
|
|
283
|
+
stub_request(:get, "https://api.workos.com/sso/jwks/client_001")
|
|
284
|
+
.to_return(status: 200, body: jwks_payload(pub).to_json)
|
|
285
|
+
|
|
286
|
+
session = @sm.load(seal_data: sealed, cookie_password: PASSWORD)
|
|
287
|
+
result = session.refresh
|
|
288
|
+
|
|
289
|
+
assert_kind_of WorkOS::SessionManager::RefreshSuccess, result
|
|
290
|
+
assert result.authenticated
|
|
291
|
+
assert_equal "session_new_v6", result.session_id
|
|
292
|
+
assert_equal "org_v6", result.organization_id
|
|
293
|
+
assert_equal "member", result.role
|
|
294
|
+
assert_equal "u_v6", result.user["id"]
|
|
295
|
+
|
|
296
|
+
refute_empty result.sealed_session
|
|
297
|
+
unsealed = @sm.unseal_data(result.sealed_session, PASSWORD)
|
|
298
|
+
assert_equal new_access, unsealed["access_token"]
|
|
299
|
+
assert_equal "rt_new_v6", unsealed["refresh_token"]
|
|
300
|
+
assert_equal "u_v6", unsealed["user"]["id"]
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
def test_refresh_updates_internal_seal_data_for_subsequent_authenticate
|
|
304
|
+
rsa, pub = signing_key_pair
|
|
305
|
+
old_access = make_jwt({"sid" => "session_old", "exp" => Time.now.to_i - 60}, rsa)
|
|
306
|
+
sealed = @sm.seal_data({"access_token" => old_access, "refresh_token" => "rt_old", "user" => {"id" => "u_1"}}, PASSWORD)
|
|
307
|
+
|
|
308
|
+
new_access = make_jwt({"sid" => "session_refreshed", "org_id" => "org_2", "exp" => Time.now.to_i + 300}, rsa)
|
|
309
|
+
api_response = {
|
|
310
|
+
"access_token" => new_access,
|
|
311
|
+
"refresh_token" => "rt_new",
|
|
312
|
+
"user" => {"id" => "u_1"}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
stub_request(:post, "https://api.workos.com/user_management/authenticate")
|
|
316
|
+
.to_return(status: 200, body: api_response.to_json)
|
|
317
|
+
stub_request(:get, "https://api.workos.com/sso/jwks/client_001")
|
|
318
|
+
.to_return(status: 200, body: jwks_payload(pub).to_json)
|
|
319
|
+
|
|
320
|
+
session = @sm.load(seal_data: sealed, cookie_password: PASSWORD)
|
|
321
|
+
session.refresh
|
|
322
|
+
|
|
323
|
+
# A subsequent authenticate should use the refreshed token
|
|
324
|
+
auth = session.authenticate
|
|
325
|
+
assert_kind_of WorkOS::SessionManager::AuthSuccess, auth
|
|
326
|
+
assert auth.authenticated
|
|
327
|
+
assert_equal "session_refreshed", auth.session_id
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def test_refresh_returns_error_on_invalid_cookie
|
|
331
|
+
result = @sm.refresh(seal_data: "garbage", cookie_password: PASSWORD)
|
|
332
|
+
assert_kind_of WorkOS::SessionManager::RefreshError, result
|
|
333
|
+
refute result.authenticated
|
|
334
|
+
assert_equal WorkOS::SessionManager::INVALID_SESSION_COOKIE, result.reason
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
def test_refresh_returns_error_when_no_refresh_token
|
|
338
|
+
sealed = @sm.seal_data({"access_token" => "at_only"}, PASSWORD)
|
|
339
|
+
result = @sm.refresh(seal_data: sealed, cookie_password: PASSWORD)
|
|
340
|
+
assert_kind_of WorkOS::SessionManager::RefreshError, result
|
|
341
|
+
assert_equal WorkOS::SessionManager::INVALID_SESSION_COOKIE, result.reason
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
def test_refresh_does_not_send_session_param_to_api
|
|
345
|
+
rsa, pub = signing_key_pair
|
|
346
|
+
old_access = make_jwt({"sid" => "s", "exp" => Time.now.to_i - 60}, rsa)
|
|
347
|
+
sealed = @sm.seal_data({"access_token" => old_access, "refresh_token" => "rt_x", "user" => {"id" => "u"}}, PASSWORD)
|
|
348
|
+
|
|
349
|
+
new_access = make_jwt({"sid" => "s2", "exp" => Time.now.to_i + 300}, rsa)
|
|
350
|
+
api_response = {"access_token" => new_access, "refresh_token" => "rt_y", "user" => {"id" => "u"}}
|
|
351
|
+
|
|
352
|
+
stub = stub_request(:post, "https://api.workos.com/user_management/authenticate")
|
|
353
|
+
.with { |req| !req.body.include?("seal_session") }
|
|
354
|
+
.to_return(status: 200, body: api_response.to_json)
|
|
355
|
+
stub_request(:get, "https://api.workos.com/sso/jwks/client_001")
|
|
356
|
+
.to_return(status: 200, body: jwks_payload(pub).to_json)
|
|
357
|
+
|
|
358
|
+
session = @sm.load(seal_data: sealed, cookie_password: PASSWORD)
|
|
359
|
+
session.refresh
|
|
360
|
+
|
|
361
|
+
assert_requested(stub)
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
def test_refresh_returns_error_on_malformed_access_token_without_mutating_state
|
|
365
|
+
rsa, pub = signing_key_pair
|
|
366
|
+
old_access = make_jwt({"sid" => "session_old", "exp" => Time.now.to_i - 60}, rsa)
|
|
367
|
+
sealed = @sm.seal_data({"access_token" => old_access, "refresh_token" => "rt_old", "user" => {"id" => "u_1"}}, PASSWORD)
|
|
368
|
+
|
|
369
|
+
api_response = {
|
|
370
|
+
"access_token" => "not-a-valid-jwt",
|
|
371
|
+
"refresh_token" => "rt_new",
|
|
372
|
+
"user" => {"id" => "u_1"}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
stub_request(:post, "https://api.workos.com/user_management/authenticate")
|
|
376
|
+
.to_return(status: 200, body: api_response.to_json)
|
|
377
|
+
stub_request(:get, "https://api.workos.com/sso/jwks/client_001")
|
|
378
|
+
.to_return(status: 200, body: jwks_payload(pub).to_json)
|
|
379
|
+
|
|
380
|
+
session = @sm.load(seal_data: sealed, cookie_password: PASSWORD)
|
|
381
|
+
result = session.refresh
|
|
382
|
+
|
|
383
|
+
assert_kind_of WorkOS::SessionManager::RefreshError, result
|
|
384
|
+
refute result.authenticated
|
|
385
|
+
|
|
386
|
+
# Session state should not have been mutated
|
|
387
|
+
assert_equal sealed, session.seal_data
|
|
388
|
+
end
|
|
389
|
+
|
|
209
390
|
# --- Session constructor validation ---------------------------------------
|
|
210
391
|
|
|
211
392
|
def test_session_load_requires_cookie_password
|
|
@@ -258,4 +439,16 @@ class SessionTest < Minitest::Test
|
|
|
258
439
|
assert_kind_of WorkOS::SessionManager::AuthSuccess, result
|
|
259
440
|
assert_equal "s_custom", result.session_id
|
|
260
441
|
end
|
|
442
|
+
|
|
443
|
+
private
|
|
444
|
+
|
|
445
|
+
def legacy_v6_seal(data, key)
|
|
446
|
+
cipher = OpenSSL::Cipher.new("aes-256-gcm").encrypt
|
|
447
|
+
iv = SecureRandom.random_bytes(12)
|
|
448
|
+
cipher.key = key
|
|
449
|
+
cipher.iv = iv
|
|
450
|
+
ciphertext = cipher.update(JSON.generate(data)) + cipher.final
|
|
451
|
+
|
|
452
|
+
Base64.encode64(iv + ciphertext + cipher.auth_tag)
|
|
453
|
+
end
|
|
261
454
|
end
|