workos 0.8.1 → 0.10.1

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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +5 -0
  3. data/.rubocop.yml +4 -0
  4. data/Gemfile.lock +2 -2
  5. data/README.md +119 -55
  6. data/docs/WorkOS/SSO.html +235 -235
  7. data/docs/file.README.html +20 -20
  8. data/lib/workos.rb +1 -0
  9. data/lib/workos/audit_trail.rb +1 -0
  10. data/lib/workos/client.rb +22 -1
  11. data/lib/workos/connection.rb +0 -2
  12. data/lib/workos/organization.rb +0 -2
  13. data/lib/workos/passwordless.rb +3 -2
  14. data/lib/workos/portal.rb +0 -6
  15. data/lib/workos/profile.rb +6 -4
  16. data/lib/workos/sso.rb +121 -13
  17. data/lib/workos/types/profile_struct.rb +1 -0
  18. data/lib/workos/version.rb +1 -1
  19. data/spec/lib/workos/passwordless_spec.rb +1 -0
  20. data/spec/lib/workos/sso_spec.rb +213 -7
  21. data/spec/support/fixtures/vcr_cassettes/audit_trail/get_events.yml +2 -2
  22. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_directories.yml +1 -1
  23. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_directories_with_domain_param.yml +1 -1
  24. data/spec/support/fixtures/vcr_cassettes/sso/delete_connection_with_invalid_id.yml +72 -0
  25. data/spec/support/fixtures/vcr_cassettes/sso/delete_connection_with_valid_id.yml +70 -0
  26. data/spec/support/fixtures/vcr_cassettes/sso/get_connection_with_invalid_id.yml +72 -0
  27. data/spec/support/fixtures/vcr_cassettes/sso/get_connection_with_valid_id.yml +74 -0
  28. data/spec/support/fixtures/vcr_cassettes/sso/list_connections.yml +72 -0
  29. data/spec/support/fixtures/vcr_cassettes/sso/list_connections_with_after_param.yml +72 -0
  30. data/spec/support/fixtures/vcr_cassettes/sso/list_connections_with_before_param.yml +73 -0
  31. data/spec/support/fixtures/vcr_cassettes/sso/list_connections_with_connection_type_param.yml +72 -0
  32. data/spec/support/fixtures/vcr_cassettes/sso/list_connections_with_domain_param.yml +72 -0
  33. data/spec/support/fixtures/vcr_cassettes/sso/list_connections_with_limit_param.yml +72 -0
  34. data/spec/support/fixtures/vcr_cassettes/sso/list_connections_with_organization_id_param.yml +72 -0
  35. data/spec/support/profile.txt +1 -1
  36. metadata +26 -4
  37. data/CODEOWNERS +0 -1
@@ -10,6 +10,7 @@ module WorkOS
10
10
  const :email, String
11
11
  const :first_name, T.nilable(String)
12
12
  const :last_name, T.nilable(String)
13
+ const :connection_id, String
13
14
  const :connection_type, String
14
15
  const :idp_id, T.nilable(String)
15
16
  const :raw_attributes, T::Hash[Symbol, Object]
@@ -2,5 +2,5 @@
2
2
  # typed: strong
3
3
 
4
4
  module WorkOS
5
- VERSION = '0.8.1'
5
+ VERSION = '0.10.1'
6
6
  end
@@ -16,6 +16,7 @@ describe WorkOS::Passwordless do
16
16
  {
17
17
  email: 'demo@workos-okta.com',
18
18
  type: 'MagicLink',
19
+ redirect_uri: 'foo.com/auth/callback',
19
20
  }
20
21
  end
21
22
 
@@ -9,7 +9,7 @@ describe WorkOS::SSO do
9
9
  let(:args) do
10
10
  {
11
11
  domain: 'foo.com',
12
- project_id: 'workos-proj-123',
12
+ client_id: 'workos-proj-123',
13
13
  redirect_uri: 'foo.com/auth/callback',
14
14
  state: {
15
15
  next_page: '/dashboard/edit',
@@ -43,7 +43,7 @@ describe WorkOS::SSO do
43
43
  let(:args) do
44
44
  {
45
45
  provider: 'GoogleOAuth',
46
- project_id: 'workos-proj-123',
46
+ client_id: 'workos-proj-123',
47
47
  redirect_uri: 'foo.com/auth/callback',
48
48
  state: {
49
49
  next_page: '/dashboard/edit',
@@ -76,7 +76,7 @@ describe WorkOS::SSO do
76
76
  context 'with neither domain or provider' do
77
77
  let(:args) do
78
78
  {
79
- project_id: 'workos-proj-123',
79
+ client_id: 'workos-proj-123',
80
80
  redirect_uri: 'foo.com/auth/callback',
81
81
  state: {
82
82
  next_page: '/dashboard/edit',
@@ -97,7 +97,7 @@ describe WorkOS::SSO do
97
97
  let(:args) do
98
98
  {
99
99
  provider: 'Okta',
100
- project_id: 'workos-proj-123',
100
+ client_id: 'workos-proj-123',
101
101
  redirect_uri: 'foo.com/auth/callback',
102
102
  state: {
103
103
  next_page: '/dashboard/edit',
@@ -113,6 +113,49 @@ describe WorkOS::SSO do
113
113
  )
114
114
  end
115
115
  end
116
+
117
+ context 'passing the project_id' do
118
+ let(:args) do
119
+ {
120
+ domain: 'foo.com',
121
+ project_id: 'workos-proj-123',
122
+ redirect_uri: 'foo.com/auth/callback',
123
+ state: {
124
+ next_page: '/dashboard/edit',
125
+ }.to_s,
126
+ }
127
+ end
128
+ it 'raises a deprecation warning' do
129
+ expect do
130
+ described_class.authorization_url(**args)
131
+ end.to output(
132
+ "[DEPRECATION] `project_id` is deprecated.
133
+ Please use `client_id` instead.\n",
134
+ ).to_stderr
135
+ end
136
+
137
+ it 'returns a valid URL' do
138
+ authorization_url = described_class.authorization_url(**args)
139
+
140
+ expect(URI.parse(authorization_url)).to be_a URI
141
+ end
142
+
143
+ it 'returns the expected hostname' do
144
+ authorization_url = described_class.authorization_url(**args)
145
+
146
+ expect(URI.parse(authorization_url).host).to eq(WorkOS::API_HOSTNAME)
147
+ end
148
+
149
+ it 'returns the expected query string' do
150
+ authorization_url = described_class.authorization_url(**args)
151
+
152
+ expect(URI.parse(authorization_url).query).to eq(
153
+ 'client_id=workos-proj-123&redirect_uri=foo.com%2Fauth%2Fcallback' \
154
+ '&response_type=code&state=%7B%3Anext_page%3D%3E%22%2Fdashboard%2F' \
155
+ 'edit%22%7D&domain=foo.com',
156
+ )
157
+ end
158
+ end
116
159
  end
117
160
 
118
161
  describe '.profile' do
@@ -123,13 +166,13 @@ describe WorkOS::SSO do
123
166
  let(:args) do
124
167
  {
125
168
  code: SecureRandom.hex(10),
126
- project_id: 'workos-proj-123',
169
+ client_id: 'workos-proj-123',
127
170
  }
128
171
  end
129
172
 
130
173
  let(:request_body) do
131
174
  {
132
- client_id: args[:project_id],
175
+ client_id: args[:client_id],
133
176
  client_secret: WorkOS.key,
134
177
  code: args[:code],
135
178
  grant_type: 'authorization_code',
@@ -163,6 +206,7 @@ describe WorkOS::SSO do
163
206
  expect(profile).to be_a(WorkOS::Profile)
164
207
 
165
208
  expectation = {
209
+ connection_id: 'conn_01EMH8WAK20T42N2NBMNBCYHAG',
166
210
  connection_type: 'OktaSAML',
167
211
  email: 'demo@workos-okta.com',
168
212
  first_name: 'WorkOS',
@@ -277,7 +321,7 @@ describe WorkOS::SSO do
277
321
  end
278
322
 
279
323
  let(:token) { 'draft_conn_id' }
280
- let(:project_id) { 'proj_0239u590h' }
324
+ let(:client_id) { 'proj_0239u590h' }
281
325
 
282
326
  context 'with a valid request' do
283
327
  before do
@@ -311,4 +355,166 @@ describe WorkOS::SSO do
311
355
  end
312
356
  end
313
357
  end
358
+
359
+ describe '.list_connections' do
360
+ before(:all) do
361
+ WorkOS.key = 'key'
362
+ end
363
+
364
+ after(:all) do
365
+ WorkOS.key = nil
366
+ end
367
+
368
+ context 'with no options' do
369
+ it 'returns connections' do
370
+ VCR.use_cassette('sso/list_connections') do
371
+ connections = WorkOS::SSO.list_connections
372
+ expect(connections.size).to eq(1)
373
+ end
374
+ end
375
+ end
376
+
377
+ context 'with connection_type option' do
378
+ it 'returns connections' do
379
+ VCR.use_cassette('sso/list_connections_with_connection_type_param') do
380
+ connections = WorkOS::SSO.list_connections(
381
+ connection_type: 'OktaSAML',
382
+ )
383
+ expect(connections.first['connection_type']).to eq('OktaSAML')
384
+ end
385
+ end
386
+ end
387
+
388
+ context 'with domain option' do
389
+ it 'returns connections' do
390
+ VCR.use_cassette('sso/list_connections_with_domain_param') do
391
+ connections = WorkOS::SSO.list_connections(
392
+ domain: 'foo-corp.com',
393
+ )
394
+ domains = connections.first['domains']
395
+ expect(domains.first['domain']).to eq('foo-corp.com')
396
+ end
397
+ end
398
+ end
399
+
400
+ context 'with organization_id option' do
401
+ it 'returns connections' do
402
+ VCR.use_cassette('sso/list_connections_with_organization_id_param') do
403
+ connections = WorkOS::SSO.list_connections(
404
+ organization_id: 'org_01EGS4P7QR31EZ4YWD1Z1XA176',
405
+ )
406
+ expect(connections.size).to eq(1)
407
+ expect(connections.first['organization_id']).to eq(
408
+ 'org_01EGS4P7QR31EZ4YWD1Z1XA176',
409
+ )
410
+ end
411
+ end
412
+ end
413
+
414
+ context 'with limit option' do
415
+ it 'returns connections' do
416
+ VCR.use_cassette('sso/list_connections_with_limit_param') do
417
+ connections = WorkOS::SSO.list_connections(
418
+ limit: 1,
419
+ )
420
+ expect(connections.size).to eq(1)
421
+ end
422
+ end
423
+ end
424
+
425
+ context 'with before option' do
426
+ it 'returns connections' do
427
+ VCR.use_cassette('sso/list_connections_with_before_param') do
428
+ connections = WorkOS::SSO.list_connections(
429
+ before: 'conn_01EQKPMQAPV02H270HKVNS4CTA',
430
+ )
431
+ expect(connections.size).to eq(1)
432
+ end
433
+ end
434
+ end
435
+
436
+ context 'with after option' do
437
+ it 'returns connections' do
438
+ VCR.use_cassette('sso/list_connections_with_after_param') do
439
+ connections = WorkOS::SSO.list_connections(
440
+ after: 'conn_01EQKPMQAPV02H270HKVNS4CTA',
441
+ )
442
+ expect(connections.size).to eq(1)
443
+ end
444
+ end
445
+ end
446
+ end
447
+
448
+ describe '.get_connection' do
449
+ before(:all) do
450
+ WorkOS.key = 'key'
451
+ end
452
+
453
+ after(:all) do
454
+ WorkOS.key = nil
455
+ end
456
+
457
+ context 'with a valid id' do
458
+ it 'gets the connection details' do
459
+ VCR.use_cassette('sso/get_connection_with_valid_id') do
460
+ connection = WorkOS::SSO.get_connection(
461
+ id: 'conn_01EX00NB050H354WKGC7990AR2',
462
+ )
463
+
464
+ expect(connection.id).to eq('conn_01EX00NB050H354WKGC7990AR2')
465
+ expect(connection.connection_type).to eq('OktaSAML')
466
+ expect(connection.name).to eq('Foo Corp')
467
+ expect(connection.domains.first[:domain]).to eq('foo-corp.com')
468
+ end
469
+ end
470
+ end
471
+
472
+ context 'with an invalid id' do
473
+ it 'raises an error' do
474
+ VCR.use_cassette('sso/get_connection_with_invalid_id') do
475
+ expect do
476
+ WorkOS::SSO.get_connection(id: 'invalid')
477
+ end.to raise_error(
478
+ WorkOS::APIError,
479
+ 'Status 404, Not Found - request ID: ',
480
+ )
481
+ end
482
+ end
483
+ end
484
+ end
485
+
486
+ describe '.delete_connection' do
487
+ before(:all) do
488
+ WorkOS.key = 'key'
489
+ end
490
+
491
+ after(:all) do
492
+ WorkOS.key = nil
493
+ end
494
+
495
+ context 'with a valid id' do
496
+ it 'returns true' do
497
+ VCR.use_cassette('sso/delete_connection_with_valid_id') do
498
+ response = WorkOS::SSO.delete_connection(
499
+ id: 'conn_01EX55FRVN1V2PCA9YWTMZQMMQ',
500
+ )
501
+
502
+ expect(response).to be(true)
503
+ end
504
+ end
505
+ end
506
+
507
+ context 'with an invalid id' do
508
+ it 'returns false' do
509
+ VCR.use_cassette('sso/delete_connection_with_invalid_id') do
510
+ expect do
511
+ WorkOS::SSO.delete_connection(id: 'invalid')
512
+ end.to raise_error(
513
+ WorkOS::APIError,
514
+ 'Status 404, Not Found - request ID: ',
515
+ )
516
+ end
517
+ end
518
+ end
519
+ end
314
520
  end
@@ -54,8 +54,8 @@ http_interactions:
54
54
  encoding: ASCII-8BIT
55
55
  string:
56
56
  '{"data":[{"object":"event","id":"evt_01EEJM9Q9SMC3W2SZDKA5VJ8XQ","group":"workos.com","location":"::1","latitude":null,"longitude":null,"type":"r","actor_name":"foo@example.com","actor_id":"user_01EEG9P7A1DA9VY9CX7GT47RPF","target_name":"api_key_query","target_id":"key_01EEG9MPHAYX46BBZKGK3BGQXJ","metadata":{"description":"User
57
- viewed API key.","x_request_id":""},"occurred_at":"2020-07-31T14:27:00.384Z","action":{"object":"event_action","id":"evt_action_01EEGQXWAHB065P5JD0QDAAGDC","name":"user.viewed_api_key","project_id":"project_01DZB0E7HQMA6G85PQNHQJMZD0"}},{"object":"event","id":"evt_01EEJM9Q7GMR1VGT6VXN2N2JJQ","group":"workos.com","location":"::1","latitude":null,"longitude":null,"type":"r","actor_name":"foo@example.com","actor_id":"user_01EEG9P7A1DA9VY9CX7GT47RPF","target_name":"api_key_query","target_id":"key_01EEG9MPGM8KFT9VBQHJMV8YZB","metadata":{"description":"User
58
- viewed API key.","x_request_id":""},"occurred_at":"2020-07-31T14:27:00.360Z","action":{"object":"event_action","id":"evt_action_01EEGQXWAHB065P5JD0QDAAGDC","name":"user.viewed_api_key","project_id":"project_01DZB0E7HQMA6G85PQNHQJMZD0"}}],"listMetadata":{"before":"evt_01EEJKZDAR6G4JHFQT4R3KSZDQ","after":null}}'
57
+ viewed API key.","x_request_id":""},"occurred_at":"2020-07-31T14:27:00.384Z","action":{"object":"event_action","id":"evt_action_01EEGQXWAHB065P5JD0QDAAGDC","name":"user.viewed_api_key","client_id":"project_01DZB0E7HQMA6G85PQNHQJMZD0"}},{"object":"event","id":"evt_01EEJM9Q7GMR1VGT6VXN2N2JJQ","group":"workos.com","location":"::1","latitude":null,"longitude":null,"type":"r","actor_name":"foo@example.com","actor_id":"user_01EEG9P7A1DA9VY9CX7GT47RPF","target_name":"api_key_query","target_id":"key_01EEG9MPGM8KFT9VBQHJMV8YZB","metadata":{"description":"User
58
+ viewed API key.","x_request_id":""},"occurred_at":"2020-07-31T14:27:00.360Z","action":{"object":"event_action","id":"evt_action_01EEGQXWAHB065P5JD0QDAAGDC","name":"user.viewed_api_key","client_id":"project_01DZB0E7HQMA6G85PQNHQJMZD0"}}],"listMetadata":{"before":"evt_01EEJKZDAR6G4JHFQT4R3KSZDQ","after":null}}'
59
59
  http_version:
60
60
  recorded_at: Fri, 31 Jul 2020 14:41:12 GMT
61
61
  recorded_with: VCR 5.0.0
@@ -56,7 +56,7 @@ http_interactions:
56
56
  - 1.1 vegur
57
57
  body:
58
58
  encoding: ASCII-8BIT
59
- string: '{"object":"list","listMetadata":{"before":"directory_edp_01E44H95QPBGZ6A4D89VYZ0WX1","after":null},"data":[{"object":"directory","id":"directory_edp_01E64QQVQTCB0DECJ9CFNXEWDW","external_key":"lA3gS1kCZMCkk82E","state":"linked","type":"gsuite directory","name":"Foo Corp","bearer_token":null,"project_id":"project_01DFYCG8RCB1DB6DKFTGXF4Q9F","domain":"foo-corp.com"}]}'
59
+ string: '{"object":"list","listMetadata":{"before":"directory_edp_01E44H95QPBGZ6A4D89VYZ0WX1","after":null},"data":[{"object":"directory","id":"directory_edp_01E64QQVQTCB0DECJ9CFNXEWDW","external_key":"lA3gS1kCZMCkk82E","state":"linked","type":"gsuite directory","name":"Foo Corp","bearer_token":null,"client_id":"project_01DFYCG8RCB1DB6DKFTGXF4Q9F","domain":"foo-corp.com"}]}'
60
60
  http_version:
61
61
  recorded_at: Thu, 30 Apr 2020 03:11:45 GMT
62
62
  recorded_with: VCR 5.0.0
@@ -57,7 +57,7 @@ http_interactions:
57
57
  body:
58
58
  encoding: UTF-8
59
59
  string: '{"object":"list","listMetadata":{"before":null,"after":null},"data":[{"object":"directory","id":"directory_edp_01E64QQVQTCB0DECJ9CFNXEWDW","external_key":"lA3gS1kCZMCkk82E","state":"linked","type":"gsuite
60
- directory","name":"Foo Corp","bearer_token":null,"project_id":"project_01DFYCG8RCB1DB6DKFTGXF4Q9F","domain":"foo-corp.com"}]}'
60
+ directory","name":"Foo Corp","bearer_token":null,"client_id":"project_01DFYCG8RCB1DB6DKFTGXF4Q9F","domain":"foo-corp.com"}]}'
61
61
  http_version:
62
62
  recorded_at: Thu, 30 Apr 2020 03:42:20 GMT
63
63
  recorded_with: VCR 5.0.0
@@ -0,0 +1,72 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: delete
5
+ uri: https://api.workos.com/connections/invalid
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Content-Type:
11
+ - application/json
12
+ Accept-Encoding:
13
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
14
+ Accept:
15
+ - "*/*"
16
+ User-Agent:
17
+ - WorkOS; ruby/2.7.1; x86_64-darwin19; v0.10.0
18
+ Authorization:
19
+ - Bearer <API_KEY>
20
+ response:
21
+ status:
22
+ code: 404
23
+ message: Not Found
24
+ headers:
25
+ Server:
26
+ - Cowboy
27
+ Connection:
28
+ - keep-alive
29
+ Vary:
30
+ - Origin, Accept-Encoding
31
+ Access-Control-Allow-Credentials:
32
+ - 'true'
33
+ Content-Security-Policy:
34
+ - 'default-src ''self'';base-uri ''self'';block-all-mixed-content;font-src ''self''
35
+ https: data:;frame-ancestors ''self'';img-src ''self'' data:;object-src ''none'';script-src
36
+ ''self'';script-src-attr ''none'';style-src ''self'' https: ''unsafe-inline'';upgrade-insecure-requests'
37
+ X-Dns-Prefetch-Control:
38
+ - 'off'
39
+ Expect-Ct:
40
+ - max-age=0
41
+ X-Frame-Options:
42
+ - SAMEORIGIN
43
+ Strict-Transport-Security:
44
+ - max-age=15552000; includeSubDomains
45
+ X-Download-Options:
46
+ - noopen
47
+ X-Content-Type-Options:
48
+ - nosniff
49
+ X-Permitted-Cross-Domain-Policies:
50
+ - none
51
+ Referrer-Policy:
52
+ - no-referrer
53
+ X-Xss-Protection:
54
+ - '0'
55
+ X-Request-Id:
56
+ -
57
+ Content-Type:
58
+ - application/json; charset=utf-8
59
+ Content-Length:
60
+ - '23'
61
+ Etag:
62
+ - W/"17-SuRA/yvUWUo8rK6x7dKURLeBo+0"
63
+ Date:
64
+ - Thu, 04 Feb 2021 17:20:08 GMT
65
+ Via:
66
+ - 1.1 vegur
67
+ body:
68
+ encoding: UTF-8
69
+ string: '{"message":"Not Found"}'
70
+ http_version:
71
+ recorded_at: Thu, 04 Feb 2021 17:20:08 GMT
72
+ recorded_with: VCR 5.0.0
@@ -0,0 +1,70 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: delete
5
+ uri: https://api.workos.com/connections/conn_01EX55FRVN1V2PCA9YWTMZQMMQ
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Content-Type:
11
+ - application/json
12
+ Accept-Encoding:
13
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
14
+ Accept:
15
+ - "*/*"
16
+ User-Agent:
17
+ - WorkOS; ruby/2.7.1; x86_64-darwin19; v0.10.0
18
+ Authorization:
19
+ - Bearer <API_KEY>
20
+ response:
21
+ status:
22
+ code: 204
23
+ message: No Content
24
+ headers:
25
+ Server:
26
+ - Cowboy
27
+ Content-Length:
28
+ - '0'
29
+ Connection:
30
+ - keep-alive
31
+ Vary:
32
+ - Origin
33
+ Access-Control-Allow-Credentials:
34
+ - 'true'
35
+ Content-Security-Policy:
36
+ - 'default-src ''self'';base-uri ''self'';block-all-mixed-content;font-src ''self''
37
+ https: data:;frame-ancestors ''self'';img-src ''self'' data:;object-src ''none'';script-src
38
+ ''self'';script-src-attr ''none'';style-src ''self'' https: ''unsafe-inline'';upgrade-insecure-requests'
39
+ X-Dns-Prefetch-Control:
40
+ - 'off'
41
+ Expect-Ct:
42
+ - max-age=0
43
+ X-Frame-Options:
44
+ - SAMEORIGIN
45
+ Strict-Transport-Security:
46
+ - max-age=15552000; includeSubDomains
47
+ X-Download-Options:
48
+ - noopen
49
+ X-Content-Type-Options:
50
+ - nosniff
51
+ X-Permitted-Cross-Domain-Policies:
52
+ - none
53
+ Referrer-Policy:
54
+ - no-referrer
55
+ X-Xss-Protection:
56
+ - '0'
57
+ X-Request-Id:
58
+ -
59
+ Etag:
60
+ - W/"a-bAsFyilMr4Ra1hIU5PyoyFRunpI"
61
+ Date:
62
+ - Thu, 04 Feb 2021 17:20:08 GMT
63
+ Via:
64
+ - 1.1 vegur
65
+ body:
66
+ encoding: UTF-8
67
+ string: ''
68
+ http_version:
69
+ recorded_at: Thu, 04 Feb 2021 17:20:08 GMT
70
+ recorded_with: VCR 5.0.0