workos 5.18.0 → 5.20.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: a7bcbc31ee2fd99bc75f92dd89397a5acb223fcd12f7ce5d24e396b966240cb1
4
- data.tar.gz: 7f21e67f61a6d63c746e50dd3e6753acea90ab39d765bdd0c4f9566b5b0135e5
3
+ metadata.gz: dc1f97c76fdf489cb3be51bd9026dc515195c34aaf9810379bfe4773029aafc1
4
+ data.tar.gz: 2176f6680ae6a7c46ca77824c7dcf2fbe91ca244986a05f7039a1d40265db881
5
5
  SHA512:
6
- metadata.gz: f48581ece4c6ee347403cdc865b4bb6ed0637ad7fec62ecd7926016f709988cd9106d37f8a138bbddf15a8fa0aa95fa65c3d496356fb6bcb56ce70163f1c0004
7
- data.tar.gz: ed1e358de54b404eca9ef2036dae4a4a777b519d4c00583a789221cb08393e5d4a8fbe79dfc5fe1ed632522ae02734fb1b3145a649fa6c1e0813b2d25fab4719
6
+ metadata.gz: 6bda209314485831a8237e381566472c5815dea3b727db277e2a06c3db1c06191da54dc59292ec37bd4415291ca78c7593ae4a78cad82775ce6ffb8eae6d0931
7
+ data.tar.gz: fd199d57bd3e29e0bea6b21840597ae255db869c9815b6a06348a90c3d70532606732c999c8bef3caa2ba2900914c20b222b526c7e1a9b61c836f30f5e55d694
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- workos (5.18.0)
4
+ workos (5.20.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
@@ -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}"
@@ -278,9 +281,20 @@ module WorkOS
278
281
  # @param [String] client_id The WorkOS client ID for the environment
279
282
  # @param [String] ip_address The IP address of the request from the user who is attempting to authenticate.
280
283
  # @param [String] user_agent The user agent of the request from the user who is attempting to authenticate.
284
+ # @param [Hash] session An optional hash that determines whether the session should be sealed and
285
+ # the optional cookie password.
281
286
  #
282
287
  # @return WorkOS::AuthenticationResponse
283
- def authenticate_with_password(email:, password:, client_id:, ip_address: nil, user_agent: nil)
288
+ def authenticate_with_password(
289
+ email:,
290
+ password:,
291
+ client_id:,
292
+ ip_address: nil,
293
+ user_agent: nil,
294
+ session: nil
295
+ )
296
+ validate_session(session)
297
+
284
298
  response = execute_request(
285
299
  request: post_request(
286
300
  path: '/user_management/authenticate',
@@ -296,7 +310,7 @@ module WorkOS
296
310
  ),
297
311
  )
298
312
 
299
- WorkOS::AuthenticationResponse.new(response.body)
313
+ WorkOS::AuthenticationResponse.new(response.body, session)
300
314
  end
301
315
 
302
316
  # Authenticate a user using OAuth or an organization's SSO connection.
@@ -317,9 +331,7 @@ module WorkOS
317
331
  user_agent: nil,
318
332
  session: nil
319
333
  )
320
- if session && (session[:seal_session] == true) && session[:cookie_password].nil?
321
- raise ArgumentError, 'cookie_password is required when sealing session'
322
- end
334
+ validate_session(session)
323
335
 
324
336
  response = execute_request(
325
337
  request: post_request(
@@ -357,9 +369,7 @@ module WorkOS
357
369
  user_agent: nil,
358
370
  session: nil
359
371
  )
360
- if session && (session[:seal_session] == true) && session[:cookie_password].nil?
361
- raise ArgumentError, 'cookie_password is required when sealing session'
362
- end
372
+ validate_session(session)
363
373
 
364
374
  response = execute_request(
365
375
  request: post_request(
@@ -388,16 +398,22 @@ module WorkOS
388
398
  # @param [String] link_authorization_code Used to link an OAuth profile to an existing user,
389
399
  # after having completed a Magic Code challenge.
390
400
  # @param [String] user_agent The user agent of the request from the user who is attempting to authenticate.
401
+ # @param [Hash] session An optional hash that determines whether the session should be sealed and
402
+ # the optional cookie password.
391
403
  #
392
404
  # @return WorkOS::AuthenticationResponse
405
+ # rubocop:disable Metrics/ParameterLists
393
406
  def authenticate_with_magic_auth(
394
407
  code:,
395
408
  email:,
396
409
  client_id:,
397
410
  ip_address: nil,
398
411
  user_agent: nil,
399
- link_authorization_code: nil
412
+ link_authorization_code: nil,
413
+ session: nil
400
414
  )
415
+ validate_session(session)
416
+
401
417
  response = execute_request(
402
418
  request: post_request(
403
419
  path: '/user_management/authenticate',
@@ -414,8 +430,9 @@ module WorkOS
414
430
  ),
415
431
  )
416
432
 
417
- WorkOS::AuthenticationResponse.new(response.body)
433
+ WorkOS::AuthenticationResponse.new(response.body, session)
418
434
  end
435
+ # rubocop:enable Metrics/ParameterLists
419
436
 
420
437
  # Authenticate a user into an organization they are a member of.
421
438
  #
@@ -424,6 +441,8 @@ module WorkOS
424
441
  # @param [String] pending_authentication_token The pending authentication token
425
442
  # @param [String] ip_address The IP address of the request from the user who is attempting to authenticate.
426
443
  # @param [String] user_agent The user agent of the request from the user who is attempting to authenticate.
444
+ # @param [Hash] session An optional hash that determines whether the session should be sealed and
445
+ # the optional cookie password.
427
446
  #
428
447
  # @return WorkOS::AuthenticationResponse
429
448
  def authenticate_with_organization_selection(
@@ -431,8 +450,11 @@ module WorkOS
431
450
  organization_id:,
432
451
  pending_authentication_token:,
433
452
  ip_address: nil,
434
- user_agent: nil
453
+ user_agent: nil,
454
+ session: nil
435
455
  )
456
+ validate_session(session)
457
+
436
458
  response = execute_request(
437
459
  request: post_request(
438
460
  path: '/user_management/authenticate',
@@ -448,7 +470,7 @@ module WorkOS
448
470
  ),
449
471
  )
450
472
 
451
- WorkOS::AuthenticationResponse.new(response.body)
473
+ WorkOS::AuthenticationResponse.new(response.body, session)
452
474
  end
453
475
 
454
476
  # Authenticate a user using TOTP.
@@ -461,16 +483,22 @@ module WorkOS
461
483
  # authentication request.
462
484
  # @param [String] ip_address The IP address of the request from the user who is attempting to authenticate.
463
485
  # @param [String] user_agent The user agent of the request from the user who is attempting to authenticate.
486
+ # @param [Hash] session An optional hash that determines whether the session should be sealed and
487
+ # the optional cookie password.
464
488
  #
465
489
  # @return WorkOS::AuthenticationResponse
490
+ # rubocop:disable Metrics/ParameterLists
466
491
  def authenticate_with_totp(
467
492
  code:,
468
493
  client_id:,
469
494
  pending_authentication_token:,
470
495
  authentication_challenge_id:,
471
496
  ip_address: nil,
472
- user_agent: nil
497
+ user_agent: nil,
498
+ session: nil
473
499
  )
500
+ validate_session(session)
501
+
474
502
  response = execute_request(
475
503
  request: post_request(
476
504
  path: '/user_management/authenticate',
@@ -487,8 +515,9 @@ module WorkOS
487
515
  ),
488
516
  )
489
517
 
490
- WorkOS::AuthenticationResponse.new(response.body)
518
+ WorkOS::AuthenticationResponse.new(response.body, session)
491
519
  end
520
+ # rubocop:enable Metrics/ParameterLists
492
521
 
493
522
  # Authenticate a user using Email Verification Code.
494
523
  #
@@ -498,6 +527,8 @@ module WorkOS
498
527
  # authentication attempt due to an unverified email address.
499
528
  # @param [String] ip_address The IP address of the request from the user who is attempting to authenticate.
500
529
  # @param [String] user_agent The user agent of the request from the user who is attempting to authenticate.
530
+ # @param [Hash] session An optional hash that determines whether the session should be sealed and
531
+ # the optional cookie password.
501
532
  #
502
533
  # @return WorkOS::AuthenticationResponse
503
534
  def authenticate_with_email_verification(
@@ -505,8 +536,11 @@ module WorkOS
505
536
  client_id:,
506
537
  pending_authentication_token:,
507
538
  ip_address: nil,
508
- user_agent: nil
539
+ user_agent: nil,
540
+ session: nil
509
541
  )
542
+ validate_session(session)
543
+
510
544
  response = execute_request(
511
545
  request: post_request(
512
546
  path: '/user_management/authenticate',
@@ -522,7 +556,7 @@ module WorkOS
522
556
  ),
523
557
  )
524
558
 
525
- WorkOS::AuthenticationResponse.new(response.body)
559
+ WorkOS::AuthenticationResponse.new(response.body, session)
526
560
  end
527
561
 
528
562
  # Get the logout URL for a session
@@ -1082,6 +1116,12 @@ module WorkOS
1082
1116
 
1083
1117
  private
1084
1118
 
1119
+ def validate_session(session)
1120
+ return unless session && (session[:seal_session] == true) && session[:cookie_password].nil?
1121
+
1122
+ raise ArgumentError, 'cookie_password is required when sealing session'
1123
+ end
1124
+
1085
1125
  def validate_authorization_url_arguments(
1086
1126
  provider:,
1087
1127
  connection_id:,
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WorkOS
4
- VERSION = '5.18.0'
4
+ VERSION = '5.20.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'
@@ -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
@@ -453,6 +479,40 @@ describe WorkOS::UserManagement do
453
479
  end
454
480
  end
455
481
 
482
+ context 'when oauth_tokens is present in the api response' do
483
+ it 'returns an oauth_tokens object' do
484
+ VCR.use_cassette('user_management/authenticate_with_code/valid_with_oauth_tokens') do
485
+ authentication_response = WorkOS::UserManagement.authenticate_with_code(
486
+ code: '01H93ZZHA0JBHFJH9RR11S83YN',
487
+ client_id: 'client_123',
488
+ ip_address: '200.240.210.16',
489
+ user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/108.0.0.0 Safari/537.36',
490
+ )
491
+
492
+ expect(authentication_response.oauth_tokens).to be_a(WorkOS::OAuthTokens)
493
+ expect(authentication_response.oauth_tokens.access_token).to eq('oauth_access_token')
494
+ expect(authentication_response.oauth_tokens.refresh_token).to eq('oauth_refresh_token')
495
+ expect(authentication_response.oauth_tokens.scopes).to eq(%w[read write])
496
+ expect(authentication_response.oauth_tokens.expires_at).to eq(1_234_567_890)
497
+ end
498
+ end
499
+ end
500
+
501
+ context 'when oauth_tokens is not present in the api response' do
502
+ it 'returns nil oauth_tokens' do
503
+ VCR.use_cassette('user_management/authenticate_with_code/valid') do
504
+ authentication_response = WorkOS::UserManagement.authenticate_with_code(
505
+ code: '01H93ZZHA0JBHFJH9RR11S83YN',
506
+ client_id: 'client_123',
507
+ ip_address: '200.240.210.16',
508
+ user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/108.0.0.0 Safari/537.36',
509
+ )
510
+
511
+ expect(authentication_response.oauth_tokens).to be_nil
512
+ end
513
+ end
514
+ end
515
+
456
516
  context 'when the user is being impersonated' do
457
517
  it 'contains the impersonator metadata' do
458
518
  VCR.use_cassette('user_management/authenticate_with_code/valid_with_impersonator') do
@@ -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
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.18.0
4
+ version: 5.20.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-22 00:00:00.000000000 Z
11
+ date: 2025-06-23 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
@@ -300,6 +301,7 @@ files:
300
301
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_code/invalid.yml
301
302
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_code/valid.yml
302
303
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_code/valid_with_impersonator.yml
304
+ - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_code/valid_with_oauth_tokens.yml
303
305
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_email_verification/invalid.yml
304
306
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_email_verification/valid.yml
305
307
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_magic_auth/invalid.yml
@@ -523,6 +525,7 @@ test_files:
523
525
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_code/invalid.yml
524
526
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_code/valid.yml
525
527
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_code/valid_with_impersonator.yml
528
+ - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_code/valid_with_oauth_tokens.yml
526
529
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_email_verification/invalid.yml
527
530
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_email_verification/valid.yml
528
531
  - spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_magic_auth/invalid.yml