workos 5.19.0 → 5.21.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b64aa946db63d75ad0e7b560a904f441d2acfe4f320138c90884c5382a8da26e
4
- data.tar.gz: 9038133e40d856eee210c2298739995e3aa8cceae91b1415542955c6bea16226
3
+ metadata.gz: 44c2f0a70f0a653685d6e7a8ca2601b64c4a1ff43276680ff52d0fcd2c80f5b3
4
+ data.tar.gz: 1d3aa7e958196efbe79018014e2ffd5be229dc93812a60725d05a958afcd1c20
5
5
  SHA512:
6
- metadata.gz: c16ee35f4494b5acd119ae6a354d0ba3fa7d9e892310d8388133ff54c0e0930f3d19a20c96d3ebe5b99d7fccd8acf213eb78e6d679967c972c4c4abc15ad3cfd
7
- data.tar.gz: 88a97b1723b6dd505b19e8911c6eccef2b2adda01e996959cffa73ec82d71bf85d1011e517f660085d5c388f6474dad2eb7f0b78352e5f5b458671510b936813
6
+ metadata.gz: f51ad812297b13109f943a23d15592991b14f2d1c18ba91505c4227fffc64c2ac7912c32df163e974eb95a1f8069b3289f33b1bf783c18e757ba56e7869717d7
7
+ data.tar.gz: 5a5428749ac62c22f4fa33db0ad5a491e262c01e445a8318210d09e654e6123a17dec582e9d8b54f09913f123679f1ebe8bc57a2fec7d032f690acf28d77b8a4
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- workos (5.19.0)
4
+ workos (5.21.0)
5
5
  encryptor (~> 3.0)
6
6
  jwt (~> 2.8)
7
7
 
@@ -12,7 +12,8 @@ module WorkOS
12
12
  :access_token,
13
13
  :refresh_token,
14
14
  :authentication_method,
15
- :sealed_session
15
+ :sealed_session,
16
+ :oauth_tokens
16
17
 
17
18
  # rubocop:disable Metrics/AbcSize
18
19
  def initialize(authentication_response_json, session = nil)
@@ -27,6 +28,7 @@ module WorkOS
27
28
  reason: impersonator_json[:reason],)
28
29
  end
29
30
  @authentication_method = json[:authentication_method]
31
+ @oauth_tokens = json[:oauth_tokens] ? WorkOS::OAuthTokens.new(json[:oauth_tokens].to_json) : nil
30
32
  @sealed_session =
31
33
  if session && session[:seal_session]
32
34
  WorkOS::Session.seal_data({
@@ -49,6 +51,7 @@ module WorkOS
49
51
  refresh_token: refresh_token,
50
52
  authentication_method: authentication_method,
51
53
  sealed_session: sealed_session,
54
+ oauth_tokens: oauth_tokens&.to_json,
52
55
  }
53
56
  end
54
57
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WorkOS
4
+ # The OAuthTokens class represents the third party provider OAuth tokens returned in the authentication response.
5
+ # This class is not meant to be instantiated in user space, and is instantiated internally but exposed.
6
+ class OAuthTokens
7
+ include HashProvider
8
+
9
+ attr_accessor :access_token, :refresh_token, :scopes, :expires_at
10
+
11
+ def initialize(json)
12
+ hash = JSON.parse(json, symbolize_names: true)
13
+
14
+ @access_token = hash[:access_token]
15
+ @refresh_token = hash[:refresh_token]
16
+ @scopes = hash[:scopes]
17
+ @expires_at = hash[:expires_at]
18
+ end
19
+
20
+ def to_json(*)
21
+ {
22
+ access_token: access_token,
23
+ refresh_token: refresh_token,
24
+ scopes: scopes,
25
+ expires_at: expires_at,
26
+ }
27
+ end
28
+ end
29
+ end
@@ -185,7 +185,14 @@ module WorkOS
185
185
 
186
186
  # Retrieve a list of roles for the given organization.
187
187
  #
188
- # @param [String] organizationId The ID of the organization to fetch roles for.
188
+ # @param [String] organization_id The ID of the organization to fetch roles for.
189
+ #
190
+ # @example
191
+ # WorkOS::Organizations.list_organization_roles(organization_id: 'org_01EHZNVPK3SFK441A1RGBFSHRT')
192
+ # => #<WorkOS::Types::ListStruct data=[#<WorkOS::Role id="role_123" name="Admin" slug="admin"
193
+ # permissions=["admin:all"] ...>] ...>
194
+ #
195
+ # @return [WorkOS::Types::ListStruct] - Collection of Role objects, each including permissions array
189
196
  def list_organization_roles(organization_id:)
190
197
  response = execute_request(
191
198
  request: get_request(
data/lib/workos/role.rb CHANGED
@@ -7,7 +7,7 @@ module WorkOS
7
7
  class Role
8
8
  include HashProvider
9
9
 
10
- attr_accessor :id, :name, :slug, :description, :type, :created_at, :updated_at
10
+ attr_accessor :id, :name, :slug, :description, :permissions, :type, :created_at, :updated_at
11
11
 
12
12
  def initialize(json)
13
13
  hash = JSON.parse(json, symbolize_names: true)
@@ -16,6 +16,7 @@ module WorkOS
16
16
  @name = hash[:name]
17
17
  @slug = hash[:slug]
18
18
  @description = hash[:description]
19
+ @permissions = hash[:permissions] || []
19
20
  @type = hash[:type]
20
21
  @created_at = hash[:created_at]
21
22
  @updated_at = hash[:updated_at]
@@ -27,6 +28,7 @@ module WorkOS
27
28
  name: name,
28
29
  slug: slug,
29
30
  description: description,
31
+ permissions: permissions,
30
32
  type: type,
31
33
  created_at: created_at,
32
34
  updated_at: updated_at,
data/lib/workos/user.rb CHANGED
@@ -8,7 +8,7 @@ module WorkOS
8
8
  include HashProvider
9
9
 
10
10
  attr_accessor :id, :email, :first_name, :last_name, :email_verified,
11
- :profile_picture_url, :last_sign_in_at, :created_at, :updated_at
11
+ :profile_picture_url, :external_id, :last_sign_in_at, :created_at, :updated_at
12
12
 
13
13
  def initialize(json)
14
14
  hash = JSON.parse(json, symbolize_names: true)
@@ -19,6 +19,7 @@ module WorkOS
19
19
  @last_name = hash[:last_name]
20
20
  @email_verified = hash[:email_verified]
21
21
  @profile_picture_url = hash[:profile_picture_url]
22
+ @external_id = hash[:external_id]
22
23
  @last_sign_in_at = hash[:last_sign_in_at]
23
24
  @created_at = hash[:created_at]
24
25
  @updated_at = hash[:updated_at]
@@ -32,6 +33,7 @@ module WorkOS
32
33
  last_name: last_name,
33
34
  email_verified: email_verified,
34
35
  profile_picture_url: profile_picture_url,
36
+ external_id: external_id,
35
37
  last_sign_in_at: last_sign_in_at,
36
38
  created_at: created_at,
37
39
  updated_at: updated_at,
@@ -71,6 +71,7 @@ module WorkOS
71
71
  # field of the IdP sign-in page for the user, if you know their username ahead of time.
72
72
  # @param [String] domain_hint Can be used to pre-fill the domain field when
73
73
  # initiating authentication with Microsoft OAuth, or with a GoogleSAML connection type.
74
+ # @param [Array<String>] provider_scopes An array of additional OAuth scopes to request from the provider.
74
75
  # @example
75
76
  # WorkOS::UserManagement.authorization_url(
76
77
  # connection_id: 'conn_123',
@@ -96,7 +97,8 @@ module WorkOS
96
97
  provider: nil,
97
98
  connection_id: nil,
98
99
  organization_id: nil,
99
- state: ''
100
+ state: '',
101
+ provider_scopes: nil
100
102
  )
101
103
 
102
104
  validate_authorization_url_arguments(
@@ -115,6 +117,7 @@ module WorkOS
115
117
  provider: provider,
116
118
  connection_id: connection_id,
117
119
  organization_id: organization_id,
120
+ provider_scopes: provider_scopes,
118
121
  }.compact)
119
122
 
120
123
  "https://#{WorkOS.config.api_hostname}/user_management/authorize?#{query}"
@@ -219,6 +222,7 @@ module WorkOS
219
222
  # @param [String] first_name The user's first name.
220
223
  # @param [String] last_name The user's last name.
221
224
  # @param [Boolean] email_verified Whether the user's email address was previously verified.
225
+ # @param [String] external_id The users's external ID
222
226
  # @param [String] password The user's password.
223
227
  # @param [String] password_hash The user's hashed password.
224
228
  # @option [String] password_hash_type The algorithm originally used to hash the password.
@@ -231,6 +235,7 @@ module WorkOS
231
235
  first_name: nil,
232
236
  last_name: nil,
233
237
  email_verified: nil,
238
+ external_id: nil,
234
239
  password: nil,
235
240
  password_hash: nil,
236
241
  password_hash_type: nil
@@ -242,6 +247,7 @@ module WorkOS
242
247
  first_name: first_name,
243
248
  last_name: last_name,
244
249
  email_verified: email_verified,
250
+ external_id: external_id,
245
251
  password: password,
246
252
  password_hash: password_hash,
247
253
  password_hash_type: password_hash_type,
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WorkOS
4
- VERSION = '5.19.0'
4
+ VERSION = '5.21.0'
5
5
  end
data/lib/workos.rb CHANGED
@@ -63,6 +63,7 @@ module WorkOS
63
63
  autoload :Invitation, 'workos/invitation'
64
64
  autoload :MagicAuth, 'workos/magic_auth'
65
65
  autoload :MFA, 'workos/mfa'
66
+ autoload :OAuthTokens, 'workos/oauth_tokens'
66
67
  autoload :Organization, 'workos/organization'
67
68
  autoload :Organizations, 'workos/organizations'
68
69
  autoload :OrganizationMembership, 'workos/organization_membership'
@@ -354,6 +354,48 @@ describe WorkOS::Organizations do
354
354
  expect(roles.list_metadata).to eq(expected_metadata)
355
355
  end
356
356
  end
357
+
358
+ it 'returns properly initialized Role objects with all attributes' do
359
+ VCR.use_cassette 'organization/list_organization_roles' do
360
+ roles = described_class.list_organization_roles(organization_id: 'org_01JEXP6Z3X7HE4CB6WQSH9ZAFE')
361
+
362
+ first_role = roles.data.first
363
+ expect(first_role).to be_a(WorkOS::Role)
364
+ expect(first_role.id).to eq('role_01HS1C7GRJE08PBR3M6Y0ZYGDZ')
365
+ expect(first_role.name).to eq('Admin')
366
+ expect(first_role.slug).to eq('admin')
367
+ expect(first_role.description).to eq('Write access to every resource available')
368
+ expect(first_role.permissions).to eq(['admin:all', 'read:users', 'write:users', 'manage:roles'])
369
+ expect(first_role.type).to eq('EnvironmentRole')
370
+ expect(first_role.created_at).to eq('2024-03-15T15:38:29.521Z')
371
+ expect(first_role.updated_at).to eq('2024-11-14T17:08:00.556Z')
372
+ end
373
+ end
374
+
375
+ it 'handles roles with empty permissions arrays' do
376
+ VCR.use_cassette 'organization/list_organization_roles' do
377
+ roles = described_class.list_organization_roles(organization_id: 'org_01JEXP6Z3X7HE4CB6WQSH9ZAFE')
378
+
379
+ platform_manager_role = roles.data.find { |role| role.slug == 'org-platform-manager' }
380
+ expect(platform_manager_role).to be_a(WorkOS::Role)
381
+ expect(platform_manager_role.permissions).to eq([])
382
+ end
383
+ end
384
+
385
+ it 'properly serializes Role objects including permissions' do
386
+ VCR.use_cassette 'organization/list_organization_roles' do
387
+ roles = described_class.list_organization_roles(organization_id: 'org_01JEXP6Z3X7HE4CB6WQSH9ZAFE')
388
+
389
+ billing_role = roles.data.find { |role| role.slug == 'billing' }
390
+ serialized = billing_role.to_json
391
+
392
+ expect(serialized[:id]).to eq('role_01JA8GJZRDSZEB9289DQXJ3N9Z')
393
+ expect(serialized[:name]).to eq('Billing Manager')
394
+ expect(serialized[:slug]).to eq('billing')
395
+ expect(serialized[:permissions]).to eq(['read:billing', 'write:billing'])
396
+ expect(serialized[:type]).to eq('EnvironmentRole')
397
+ end
398
+ end
357
399
  end
358
400
  end
359
401
  end
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe WorkOS::Role do
4
+ describe '.initialize' do
5
+ context 'with full role data including permissions' do
6
+ it 'initializes all attributes correctly' do
7
+ role_json = {
8
+ id: 'role_01FAEAJCJ3P1Z6WP5Y9VQPN2XY',
9
+ name: 'Admin',
10
+ slug: 'admin',
11
+ description: 'Administrator role with full access',
12
+ permissions: ['read:users', 'write:users', 'admin:all'],
13
+ type: 'system',
14
+ created_at: '2022-05-13T17:45:31.732Z',
15
+ updated_at: '2022-07-13T17:45:42.618Z',
16
+ }.to_json
17
+
18
+ role = described_class.new(role_json)
19
+
20
+ expect(role.id).to eq('role_01FAEAJCJ3P1Z6WP5Y9VQPN2XY')
21
+ expect(role.name).to eq('Admin')
22
+ expect(role.slug).to eq('admin')
23
+ expect(role.description).to eq('Administrator role with full access')
24
+ expect(role.permissions).to eq(['read:users', 'write:users', 'admin:all'])
25
+ expect(role.type).to eq('system')
26
+ expect(role.created_at).to eq('2022-05-13T17:45:31.732Z')
27
+ expect(role.updated_at).to eq('2022-07-13T17:45:42.618Z')
28
+ end
29
+ end
30
+
31
+ context 'with role data without permissions' do
32
+ it 'initializes permissions as empty array' do
33
+ role_json = {
34
+ id: 'role_01FAEAJCJ3P1Z6WP5Y9VQPN2XY',
35
+ name: 'User',
36
+ slug: 'user',
37
+ description: 'Basic user role',
38
+ type: 'custom',
39
+ created_at: '2022-05-13T17:45:31.732Z',
40
+ updated_at: '2022-07-13T17:45:42.618Z',
41
+ }.to_json
42
+
43
+ role = described_class.new(role_json)
44
+
45
+ expect(role.id).to eq('role_01FAEAJCJ3P1Z6WP5Y9VQPN2XY')
46
+ expect(role.name).to eq('User')
47
+ expect(role.slug).to eq('user')
48
+ expect(role.description).to eq('Basic user role')
49
+ expect(role.permissions).to eq([])
50
+ expect(role.type).to eq('custom')
51
+ expect(role.created_at).to eq('2022-05-13T17:45:31.732Z')
52
+ expect(role.updated_at).to eq('2022-07-13T17:45:42.618Z')
53
+ end
54
+ end
55
+
56
+ context 'with role data with null permissions' do
57
+ it 'initializes permissions as empty array' do
58
+ role_json = {
59
+ id: 'role_01FAEAJCJ3P1Z6WP5Y9VQPN2XY',
60
+ name: 'User',
61
+ slug: 'user',
62
+ description: 'Basic user role',
63
+ permissions: nil,
64
+ type: 'custom',
65
+ created_at: '2022-05-13T17:45:31.732Z',
66
+ updated_at: '2022-07-13T17:45:42.618Z',
67
+ }.to_json
68
+
69
+ role = described_class.new(role_json)
70
+
71
+ expect(role.permissions).to eq([])
72
+ end
73
+ end
74
+
75
+ context 'with role data with empty permissions array' do
76
+ it 'preserves empty permissions array' do
77
+ role_json = {
78
+ id: 'role_01FAEAJCJ3P1Z6WP5Y9VQPN2XY',
79
+ name: 'User',
80
+ slug: 'user',
81
+ description: 'Basic user role',
82
+ permissions: [],
83
+ type: 'custom',
84
+ created_at: '2022-05-13T17:45:31.732Z',
85
+ updated_at: '2022-07-13T17:45:42.618Z',
86
+ }.to_json
87
+
88
+ role = described_class.new(role_json)
89
+
90
+ expect(role.permissions).to eq([])
91
+ end
92
+ end
93
+ end
94
+
95
+ describe '.to_json' do
96
+ context 'with role that has permissions' do
97
+ it 'includes permissions in serialized output' do
98
+ role_json = {
99
+ id: 'role_01FAEAJCJ3P1Z6WP5Y9VQPN2XY',
100
+ name: 'Admin',
101
+ slug: 'admin',
102
+ description: 'Administrator role',
103
+ permissions: ['read:all', 'write:all'],
104
+ type: 'system',
105
+ created_at: '2022-05-13T17:45:31.732Z',
106
+ updated_at: '2022-07-13T17:45:42.618Z',
107
+ }.to_json
108
+
109
+ role = described_class.new(role_json)
110
+ serialized = role.to_json
111
+
112
+ expect(serialized[:id]).to eq('role_01FAEAJCJ3P1Z6WP5Y9VQPN2XY')
113
+ expect(serialized[:name]).to eq('Admin')
114
+ expect(serialized[:slug]).to eq('admin')
115
+ expect(serialized[:description]).to eq('Administrator role')
116
+ expect(serialized[:permissions]).to eq(['read:all', 'write:all'])
117
+ expect(serialized[:type]).to eq('system')
118
+ expect(serialized[:created_at]).to eq('2022-05-13T17:45:31.732Z')
119
+ expect(serialized[:updated_at]).to eq('2022-07-13T17:45:42.618Z')
120
+ end
121
+ end
122
+
123
+ context 'with role that has no permissions' do
124
+ it 'includes empty permissions array in serialized output' do
125
+ role_json = {
126
+ id: 'role_01FAEAJCJ3P1Z6WP5Y9VQPN2XY',
127
+ name: 'User',
128
+ slug: 'user',
129
+ description: 'Basic user role',
130
+ type: 'custom',
131
+ created_at: '2022-05-13T17:45:31.732Z',
132
+ updated_at: '2022-07-13T17:45:42.618Z',
133
+ }.to_json
134
+
135
+ role = described_class.new(role_json)
136
+ serialized = role.to_json
137
+
138
+ expect(serialized[:permissions]).to eq([])
139
+ end
140
+ end
141
+ end
142
+ end
@@ -36,6 +36,32 @@ describe WorkOS::UserManagement do
36
36
  'edit%22%7D&provider=authkit',
37
37
  )
38
38
  end
39
+
40
+ context 'with provider_scopes' do
41
+ it 'returns a valid authorization URL that includes provider_scopes' do
42
+ url = WorkOS::UserManagement.authorization_url(
43
+ provider: 'GoogleOAuth',
44
+ provider_scopes: %w[custom-scope-1 custom-scope-2],
45
+ client_id: 'workos-proj-123',
46
+ redirect_uri: 'foo.com/auth/callback',
47
+ state: {
48
+ next_page: '/dashboard/edit',
49
+ }.to_s,
50
+ )
51
+
52
+ expect(url).to eq(
53
+ 'https://api.workos.com/user_management/authorize?' \
54
+ 'client_id=workos-proj-123' \
55
+ '&redirect_uri=foo.com%2Fauth%2Fcallback' \
56
+ '&response_type=code' \
57
+ '&state=%7B%3Anext_page%3D%3E%22%2Fdashboard%2F' \
58
+ 'edit%22%7D' \
59
+ '&provider=GoogleOAuth' \
60
+ '&provider_scopes=custom-scope-1' \
61
+ '&provider_scopes=custom-scope-2',
62
+ )
63
+ end
64
+ end
39
65
  end
40
66
 
41
67
  context 'with a connection selector' do
@@ -336,10 +362,12 @@ describe WorkOS::UserManagement do
336
362
  first_name: 'Jane',
337
363
  last_name: 'Doe',
338
364
  email_verified: false,
365
+ external_id: '123',
339
366
  )
340
367
  expect(user.first_name).to eq('Jane')
341
368
  expect(user.last_name).to eq('Doe')
342
369
  expect(user.email_verified).to eq(false)
370
+ expect(user.external_id).to eq('123')
343
371
  end
344
372
  end
345
373
 
@@ -453,6 +481,40 @@ describe WorkOS::UserManagement do
453
481
  end
454
482
  end
455
483
 
484
+ context 'when oauth_tokens is present in the api response' do
485
+ it 'returns an oauth_tokens object' do
486
+ VCR.use_cassette('user_management/authenticate_with_code/valid_with_oauth_tokens') do
487
+ authentication_response = WorkOS::UserManagement.authenticate_with_code(
488
+ code: '01H93ZZHA0JBHFJH9RR11S83YN',
489
+ client_id: 'client_123',
490
+ ip_address: '200.240.210.16',
491
+ user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/108.0.0.0 Safari/537.36',
492
+ )
493
+
494
+ expect(authentication_response.oauth_tokens).to be_a(WorkOS::OAuthTokens)
495
+ expect(authentication_response.oauth_tokens.access_token).to eq('oauth_access_token')
496
+ expect(authentication_response.oauth_tokens.refresh_token).to eq('oauth_refresh_token')
497
+ expect(authentication_response.oauth_tokens.scopes).to eq(%w[read write])
498
+ expect(authentication_response.oauth_tokens.expires_at).to eq(1_234_567_890)
499
+ end
500
+ end
501
+ end
502
+
503
+ context 'when oauth_tokens is not present in the api response' do
504
+ it 'returns nil oauth_tokens' do
505
+ VCR.use_cassette('user_management/authenticate_with_code/valid') do
506
+ authentication_response = WorkOS::UserManagement.authenticate_with_code(
507
+ code: '01H93ZZHA0JBHFJH9RR11S83YN',
508
+ client_id: 'client_123',
509
+ ip_address: '200.240.210.16',
510
+ user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/108.0.0.0 Safari/537.36',
511
+ )
512
+
513
+ expect(authentication_response.oauth_tokens).to be_nil
514
+ end
515
+ end
516
+ end
517
+
456
518
  context 'when the user is being impersonated' do
457
519
  it 'contains the impersonator metadata' do
458
520
  VCR.use_cassette('user_management/authenticate_with_code/valid_with_impersonator') do
@@ -70,13 +70,13 @@ http_interactions:
70
70
  encoding: ASCII-8BIT
71
71
  string:
72
72
  '{"object":"list","data":[{"object":"role","id":"role_01HS1C7GRJE08PBR3M6Y0ZYGDZ","description":"Write
73
- access to every resource available","name":"Admin","slug":"admin","type":"EnvironmentRole","created_at":"2024-03-15T15:38:29.521Z","updated_at":"2024-11-14T17:08:00.556Z"},{"object":"role","id":"role_01JA8GJZRDSZEB9289DQXJ3N9Z","description":"","name":"Billing
74
- Manager","slug":"billing","type":"EnvironmentRole","created_at":"2024-10-15T16:36:11.653Z","updated_at":"2024-12-19T21:27:01.286Z"},{"object":"role","id":"role_01HSBH4R6RX0V86S3R590NNZW2","description":"Developer
75
- role","name":"Developer","slug":"developer","type":"EnvironmentRole","created_at":"2024-03-19T14:16:46.038Z","updated_at":"2024-03-19T14:16:46.038Z"},{"object":"role","id":"role_01HS4GDWJ8T6NQPTX2D0R5KBHN","description":"Edit
76
- and view access to non-critical resources","name":"Editor","slug":"editor","type":"EnvironmentRole","created_at":"2024-03-16T20:49:35.815Z","updated_at":"2024-03-16T20:52:19.410Z"},{"object":"role","id":"role_01HRFZE22WS2MGX6EWAG2JX6NW","description":"The
77
- default user role","name":"Member","slug":"member","type":"EnvironmentRole","created_at":"2024-03-08T21:27:47.034Z","updated_at":"2024-08-14T00:27:46.265Z"},{"object":"role","id":"role_01JEYJ2Z5MYG0TZYTDF02MW11N","description":"Manage
78
- billing for organization.","name":"Billing manager","slug":"org-billing-manager","type":"OrganizationRole","created_at":"2024-12-12T23:08:28.712Z","updated_at":"2024-12-12T23:08:28.712Z"},{"object":"role","id":"role_01JF0B7MQ9X414WQRAQMQYE1GS","description":"","name":"Platform
79
- Manager","slug":"org-platform-manager","type":"OrganizationRole","created_at":"2024-12-13T15:47:10.692Z","updated_at":"2024-12-13T15:47:10.692Z"}]}'
73
+ access to every resource available","name":"Admin","slug":"admin","permissions":["admin:all","read:users","write:users","manage:roles"],"type":"EnvironmentRole","created_at":"2024-03-15T15:38:29.521Z","updated_at":"2024-11-14T17:08:00.556Z"},{"object":"role","id":"role_01JA8GJZRDSZEB9289DQXJ3N9Z","description":"","name":"Billing
74
+ Manager","slug":"billing","permissions":["read:billing","write:billing"],"type":"EnvironmentRole","created_at":"2024-10-15T16:36:11.653Z","updated_at":"2024-12-19T21:27:01.286Z"},{"object":"role","id":"role_01HSBH4R6RX0V86S3R590NNZW2","description":"Developer
75
+ role","name":"Developer","slug":"developer","permissions":["read:code","write:code","deploy:apps"],"type":"EnvironmentRole","created_at":"2024-03-19T14:16:46.038Z","updated_at":"2024-03-19T14:16:46.038Z"},{"object":"role","id":"role_01HS4GDWJ8T6NQPTX2D0R5KBHN","description":"Edit
76
+ and view access to non-critical resources","name":"Editor","slug":"editor","permissions":["read:content","write:content","publish:content"],"type":"EnvironmentRole","created_at":"2024-03-16T20:49:35.815Z","updated_at":"2024-03-16T20:52:19.410Z"},{"object":"role","id":"role_01HRFZE22WS2MGX6EWAG2JX6NW","description":"The
77
+ default user role","name":"Member","slug":"member","permissions":["read:basic"],"type":"EnvironmentRole","created_at":"2024-03-08T21:27:47.034Z","updated_at":"2024-08-14T00:27:46.265Z"},{"object":"role","id":"role_01JEYJ2Z5MYG0TZYTDF02MW11N","description":"Manage
78
+ billing for organization.","name":"Billing manager","slug":"org-billing-manager","permissions":["read:org:billing","write:org:billing"],"type":"OrganizationRole","created_at":"2024-12-12T23:08:28.712Z","updated_at":"2024-12-12T23:08:28.712Z"},{"object":"role","id":"role_01JF0B7MQ9X414WQRAQMQYE1GS","description":"","name":"Platform
79
+ Manager","slug":"org-platform-manager","permissions":[],"type":"OrganizationRole","created_at":"2024-12-13T15:47:10.692Z","updated_at":"2024-12-13T15:47:10.692Z"}]}'
80
80
  http_version:
81
81
  recorded_at: Mon, 23 Dec 2024 20:23:07 GMT
82
82
  recorded_with: VCR 5.0.0
@@ -0,0 +1,82 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://api.workos.com/user_management/authenticate
6
+ body:
7
+ encoding: UTF-8
8
+ string:
9
+ '{"code":"01H93ZZHA0JBHFJH9RR11S83YN","client_id":"client_123","client_secret":"<API_KEY>","ip_address":"200.240.210.16","user_agent":"Mozilla/5.0
10
+ (Macintosh; Intel Mac OS X 10_15_7) Chrome/108.0.0.0 Safari/537.36","grant_type":"authorization_code"}'
11
+ headers:
12
+ Content-Type:
13
+ - application/json
14
+ Accept-Encoding:
15
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
+ Accept:
17
+ - "*/*"
18
+ User-Agent:
19
+ - WorkOS; ruby/3.0.2; arm64-darwin21; v2.16.0
20
+ response:
21
+ status:
22
+ code: 200
23
+ message: OK
24
+ headers:
25
+ Date:
26
+ - Wed, 30 Aug 2023 19:51:51 GMT
27
+ Content-Type:
28
+ - application/json; charset=utf-8
29
+ Transfer-Encoding:
30
+ - chunked
31
+ Connection:
32
+ - keep-alive
33
+ Cf-Ray:
34
+ - 7fef921deeca091f-SEA
35
+ Cf-Cache-Status:
36
+ - DYNAMIC
37
+ Etag:
38
+ - W/"13b-pHataL1lHEvsW5EO4vq5QgAdcWw"
39
+ Strict-Transport-Security:
40
+ - max-age=15552000; includeSubDomains
41
+ Vary:
42
+ - Origin, Accept-Encoding
43
+ Via:
44
+ - 1.1 spaces-router (devel)
45
+ Access-Control-Allow-Credentials:
46
+ - "true"
47
+ Content-Security-Policy:
48
+ - "default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self'
49
+ https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src
50
+ 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests"
51
+ Expect-Ct:
52
+ - max-age=0
53
+ Referrer-Policy:
54
+ - no-referrer
55
+ X-Content-Type-Options:
56
+ - nosniff
57
+ X-Dns-Prefetch-Control:
58
+ - "off"
59
+ X-Download-Options:
60
+ - noopen
61
+ X-Frame-Options:
62
+ - SAMEORIGIN
63
+ X-Permitted-Cross-Domain-Policies:
64
+ - none
65
+ X-Request-Id:
66
+ - 630bec5a-5a13-4311-a0b7-958889a3bbb2
67
+ X-Xss-Protection:
68
+ - "0"
69
+ Set-Cookie:
70
+ - __cf_bm=o5KBdIAUFZp0azSQnnd1GlQcIlcPCz95uFg6hFNnKM8-1693425111-0-ARSauqdojZdKD6Z7vp12JBrxCp6wE1s0JzEhaN0XE2DqME76OnJiDJugj2TsbNGXtqWaH3By7XHUXVZDf+AdFxU=;
71
+ path=/; expires=Wed, 30-Aug-23 20:21:51 GMT; domain=.workos.com; HttpOnly;
72
+ Secure; SameSite=None
73
+ - __cfruid=3e9a5d359ba92753e7626245fef8b2f1ee096477-1693425111; path=/; domain=.workos.com;
74
+ HttpOnly; Secure; SameSite=None
75
+ Server:
76
+ - cloudflare
77
+ body:
78
+ encoding: ASCII-8BIT
79
+ string: '{"user":{"object":"user","id":"user_01H93ZY4F80YZRRS6N59Z2HFVS","email":"test@workos.app","email_verified":false,"first_name":"Lucille","last_name":"Bluth","created_at":"2023-08-30T19:50:13.214Z","updated_at":"2023-08-30T19:50:13.214Z","user_type":"managed","sso_profile_id":"prof_01H93ZTVWYPAT4RKDSPFPPXH0J"},"access_token":"<ACCESS_TOKEN>","refresh_token":"<REFRESH_TOKEN>","oauth_tokens":{"access_token":"oauth_access_token","refresh_token":"oauth_refresh_token","scopes":["read","write"],"expires_at":1234567890}}'
80
+ http_version:
81
+ recorded_at: Wed, 30 Aug 2023 19:51:51 GMT
82
+ recorded_with: VCR 5.0.0
@@ -5,7 +5,7 @@ http_interactions:
5
5
  uri: https://api.workos.com/user_management/users/user_01H7TVSKS45SDHN5V9XPSM6H44
6
6
  body:
7
7
  encoding: UTF-8
8
- string: '{"first_name":"Jane","last_name":"Doe","email_verified":false}'
8
+ string: '{"first_name":"Jane","last_name":"Doe","email_verified":false,"external_id":"123"}'
9
9
  headers:
10
10
  Content-Type:
11
11
  - application/json
@@ -76,7 +76,7 @@ http_interactions:
76
76
  - cloudflare
77
77
  body:
78
78
  encoding: ASCII-8BIT
79
- string: '{"object":"user","id":"user_01H7TVSKS45SDHN5V9XPSM6H44","email":"willman@blips.app","email_verified":false,"first_name":"Jane","last_name":"Doe","created_at":"2023-08-14T20:28:58.929Z","updated_at":"2023-08-25T22:57:44.262Z","user_type":"unmanaged","email_verified_at":null,"google_oauth_profile_id":null,"microsoft_oauth_profile_id":null}'
79
+ string: '{"object":"user","id":"user_01H7TVSKS45SDHN5V9XPSM6H44","email":"willman@blips.app","email_verified":false,"first_name":"Jane","last_name":"Doe","external_id":"123","created_at":"2023-08-14T20:28:58.929Z","updated_at":"2023-08-25T22:57:44.262Z","user_type":"unmanaged","email_verified_at":null,"google_oauth_profile_id":null,"microsoft_oauth_profile_id":null}'
80
80
  http_version:
81
81
  recorded_at: Fri, 25 Aug 2023 23:37:04 GMT
82
82
  recorded_with: VCR 5.0.0
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: 5.19.0
4
+ version: 5.21.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - WorkOS
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-05-29 00:00:00.000000000 Z
11
+ date: 2025-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: encryptor
@@ -158,6 +158,7 @@ files:
158
158
  - lib/workos/invitation.rb
159
159
  - lib/workos/magic_auth.rb
160
160
  - lib/workos/mfa.rb
161
+ - lib/workos/oauth_tokens.rb
161
162
  - lib/workos/organization.rb
162
163
  - lib/workos/organization_membership.rb
163
164
  - lib/workos/organizations.rb
@@ -196,6 +197,7 @@ files:
196
197
  - spec/lib/workos/organizations_spec.rb
197
198
  - spec/lib/workos/passwordless_spec.rb
198
199
  - spec/lib/workos/portal_spec.rb
200
+ - spec/lib/workos/role_spec.rb
199
201
  - spec/lib/workos/session_spec.rb
200
202
  - spec/lib/workos/sso_spec.rb
201
203
  - spec/lib/workos/user_management_spec.rb
@@ -300,6 +302,7 @@ files:
300
302
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_code/invalid.yml
301
303
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_code/valid.yml
302
304
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_code/valid_with_impersonator.yml
305
+ - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_code/valid_with_oauth_tokens.yml
303
306
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_email_verification/invalid.yml
304
307
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_email_verification/valid.yml
305
308
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_magic_auth/invalid.yml
@@ -419,6 +422,7 @@ test_files:
419
422
  - spec/lib/workos/organizations_spec.rb
420
423
  - spec/lib/workos/passwordless_spec.rb
421
424
  - spec/lib/workos/portal_spec.rb
425
+ - spec/lib/workos/role_spec.rb
422
426
  - spec/lib/workos/session_spec.rb
423
427
  - spec/lib/workos/sso_spec.rb
424
428
  - spec/lib/workos/user_management_spec.rb
@@ -523,6 +527,7 @@ test_files:
523
527
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_code/invalid.yml
524
528
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_code/valid.yml
525
529
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_code/valid_with_impersonator.yml
530
+ - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_code/valid_with_oauth_tokens.yml
526
531
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_email_verification/invalid.yml
527
532
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_email_verification/valid.yml
528
533
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_magic_auth/invalid.yml