descope 1.0.5 → 1.0.7

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 (89) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yaml +2 -2
  3. data/.github/workflows/publish-gem.yaml +39 -7
  4. data/.gitignore +2 -0
  5. data/.ruby-version +1 -1
  6. data/Gemfile +7 -7
  7. data/Gemfile.lock +70 -65
  8. data/README.md +175 -52
  9. data/descope.gemspec +25 -20
  10. data/examples/ruby/.ruby-version +1 -0
  11. data/examples/ruby/access_key_app.rb +4 -3
  12. data/examples/ruby/enchantedlink_app.rb +1 -0
  13. data/examples/ruby/magiclink_app.rb +1 -0
  14. data/examples/ruby/management/.ruby-version +1 -0
  15. data/examples/ruby/management/Gemfile +2 -2
  16. data/examples/ruby/management/access_key_app.rb +2 -0
  17. data/examples/ruby/management/audit_app.rb +32 -8
  18. data/examples/ruby/management/authz_app.rb +1 -0
  19. data/examples/ruby/management/flow_app.rb +1 -0
  20. data/examples/ruby/management/permission_app.rb +3 -2
  21. data/examples/ruby/management/role_app.rb +3 -2
  22. data/examples/ruby/management/tenant_app.rb +1 -0
  23. data/examples/ruby/management/user_app.rb +1 -0
  24. data/examples/ruby/oauth_app.rb +1 -0
  25. data/examples/ruby/otp_app.rb +38 -12
  26. data/examples/ruby/password_app.rb +8 -7
  27. data/examples/ruby/saml_app.rb +1 -0
  28. data/examples/ruby/version_check.rb +17 -0
  29. data/examples/ruby-on-rails-api/descope/Gemfile +9 -7
  30. data/examples/ruby-on-rails-api/descope/Gemfile.lock +121 -90
  31. data/examples/ruby-on-rails-api/descope/README.md +18 -18
  32. data/examples/ruby-on-rails-api/descope/app/assets/builds/application.css +20092 -23
  33. data/examples/ruby-on-rails-api/descope/app/assets/builds/application.js +0 -1
  34. data/examples/ruby-on-rails-api/descope/app/assets/builds/components/index.js +0 -14
  35. data/examples/ruby-on-rails-api/descope/package-lock.json +1073 -19302
  36. data/examples/ruby-on-rails-api/descope/package.json +8 -16
  37. data/examples/ruby-on-rails-api/descope/yarn.lock +557 -10641
  38. data/lib/descope/api/v1/auth/enchantedlink.rb +3 -1
  39. data/lib/descope/api/v1/auth/magiclink.rb +3 -1
  40. data/lib/descope/api/v1/auth/otp.rb +24 -15
  41. data/lib/descope/api/v1/auth/password.rb +6 -2
  42. data/lib/descope/api/v1/auth/totp.rb +3 -1
  43. data/lib/descope/api/v1/auth.rb +64 -32
  44. data/lib/descope/api/v1/management/audit.rb +24 -0
  45. data/lib/descope/api/v1/management/common.rb +21 -5
  46. data/lib/descope/api/v1/management/sso_application.rb +236 -0
  47. data/lib/descope/api/v1/management/sso_settings.rb +2 -24
  48. data/lib/descope/api/v1/management/user.rb +151 -13
  49. data/lib/descope/api/v1/management.rb +2 -0
  50. data/lib/descope/api/v1/session.rb +37 -4
  51. data/lib/descope/mixins/common.rb +6 -2
  52. data/lib/descope/mixins/http.rb +60 -9
  53. data/lib/descope/mixins/initializer.rb +2 -1
  54. data/lib/descope/mixins/logging.rb +12 -4
  55. data/lib/descope/mixins/validation.rb +21 -6
  56. data/lib/descope/version.rb +1 -1
  57. data/spec/descope/api/v1/auth_spec.rb +29 -0
  58. data/spec/descope/api/v1/auth_token_extraction_spec.rb +126 -0
  59. data/spec/descope/api/v1/session_refresh_spec.rb +98 -0
  60. data/spec/factories/user.rb +1 -1
  61. data/spec/integration/lib.descope/api/v1/auth/enchantedlink_spec.rb +1 -1
  62. data/spec/integration/lib.descope/api/v1/auth/magiclink_spec.rb +1 -1
  63. data/spec/integration/lib.descope/api/v1/auth/otp_spec.rb +73 -8
  64. data/spec/integration/lib.descope/api/v1/auth/session_spec.rb +49 -0
  65. data/spec/integration/lib.descope/api/v1/auth/totp_spec.rb +1 -1
  66. data/spec/integration/lib.descope/api/v1/management/access_key_spec.rb +3 -0
  67. data/spec/integration/lib.descope/api/v1/management/audit_spec.rb +38 -0
  68. data/spec/integration/lib.descope/api/v1/management/authz_spec.rb +2 -0
  69. data/spec/integration/lib.descope/api/v1/management/flow_spec.rb +3 -1
  70. data/spec/integration/lib.descope/api/v1/management/permissions_spec.rb +4 -2
  71. data/spec/integration/lib.descope/api/v1/management/project_spec.rb +2 -0
  72. data/spec/integration/lib.descope/api/v1/management/roles_spec.rb +3 -1
  73. data/spec/integration/lib.descope/api/v1/management/user_spec.rb +55 -6
  74. data/spec/lib.descope/api/v1/auth/enchantedlink_spec.rb +11 -2
  75. data/spec/lib.descope/api/v1/auth/otp_spec.rb +176 -18
  76. data/spec/lib.descope/api/v1/auth/password_spec.rb +10 -1
  77. data/spec/lib.descope/api/v1/auth_spec.rb +168 -6
  78. data/spec/lib.descope/api/v1/cookie_domain_fix_integration_spec.rb +245 -0
  79. data/spec/lib.descope/api/v1/management/audit_spec.rb +92 -0
  80. data/spec/lib.descope/api/v1/management/sso_application_spec.rb +217 -0
  81. data/spec/lib.descope/api/v1/management/sso_settings_spec.rb +2 -2
  82. data/spec/lib.descope/api/v1/management/user_spec.rb +134 -46
  83. data/spec/lib.descope/api/v1/session_spec.rb +119 -6
  84. data/spec/lib.descope/mixins/http_spec.rb +218 -0
  85. data/spec/support/client_config.rb +0 -1
  86. data/spec/support/utils.rb +6 -0
  87. metadata +34 -137
  88. data/examples/ruby-on-rails-api/descope/app/assets/builds/reportWebVitals.js +0 -211
  89. data/examples/ruby-on-rails-api/descope/app/assets/builds/reportWebVitals.js.map +0 -7
data/README.md CHANGED
@@ -5,7 +5,7 @@ for a backend written in Ruby. You can read more on the [Descope Website](https:
5
5
 
6
6
  ## Requirements
7
7
 
8
- The SDK supports Ruby 3.2 and above.
8
+ The SDK supports Ruby 3.3.0 and above.
9
9
 
10
10
  ## Installing the SDK
11
11
 
@@ -45,13 +45,14 @@ These sections show how to use the SDK to perform various authentication/authori
45
45
  2. [Magic Link](#magic-link)
46
46
  3. [Enchanted Link](#enchanted-link)
47
47
  4. [OAuth](#oauth)
48
- 5. [SSO/SAML](#ssosaml)
48
+ 5. [SSO (SAML / OIDC)](#sso-saml-oidc)
49
49
  6. [TOTP Authentication](#totp-authentication)
50
50
  7. [Passwords](#passwords)
51
51
  8. [Session Validation](#session-validation)
52
52
  9. [Roles & Permission Validation](#roles-permission-validation)
53
53
  10. [Tenant selection](#tenant-selection)
54
- 11. [Logging Out](#logging-out)
54
+ 11. [Signing Out](#signing-out)
55
+ 12. [History](#history)
55
56
 
56
57
  ## API Management Function
57
58
 
@@ -66,10 +67,12 @@ These sections show how to use the SDK to perform permission and user management
66
67
  7. [Query SSO Groups](#query-sso-groups)
67
68
  8. [Manage Flows](#manage-flows-and-theme)
68
69
  9. [Manage JWTs](#manage-jwts)
69
- 10. [Embedded links](#embedded-links)
70
- 11. [Search Audit](#search-audit)
71
- 12. [Manage ReBAC Authz](#manage-rebac-authz)
72
- 13. [Manage Project](#manage-project)
70
+ 10. [Impersonate](#impersonate)
71
+ 11. [Embedded links](#embedded-links)
72
+ 12. [Audit](#audit)
73
+ 13. [Manage ReBAC Authz](#manage-rebac-authz)
74
+ 14. [Manage Project](#manage-project)
75
+ 15. [Manage SSO Applications](#manage-sso-applications)
73
76
 
74
77
  If you wish to run any of our code examples and play with them, check out our [Code Examples](#code-examples) section.
75
78
 
@@ -79,7 +82,7 @@ For rate limiting information, please confer to the [API Rate Limits](#api-rate-
79
82
 
80
83
  ### OTP Authentication
81
84
 
82
- Send a user a one-time password (OTP) using your preferred delivery method (email/SMS). An email address or phone number must be provided accordingly.
85
+ Send a user a one-time password (OTP) using your preferred delivery method (Email/SMS/Voice call). An email address or phone number must be provided accordingly.
83
86
 
84
87
  The user can either `sign up`, `sign in` or `sign up or in`
85
88
 
@@ -88,32 +91,32 @@ The user can either `sign up`, `sign in` or `sign up or in`
88
91
  # For sign up either phone or email is required
89
92
  email = 'desmond@descope.com'
90
93
  user = {'name': 'Desmond Copeland', 'phone': '212-555-1234', 'email': email}
91
- masked_address = descope_client.otp_sign_up(method: DeliveryMethod.EMAIL, login_id: 'someone@example.com', user: user)
94
+ masked_address = descope_client.otp_sign_up(method: Descope::Mixins::Common::DeliveryMethod::EMAIL, login_id: 'someone@example.com', user: user)
92
95
  ```
93
96
 
94
97
  The user will receive a code using the selected delivery method. Verify that code using:
95
98
 
96
99
  ```ruby
97
100
  jwt_response = descope_client.otp_verify_code(
98
- method: DeliveryMethod.EMAIL, login_id: 'someone@example.com', code: '123456'
101
+ method: Descope::Mixins::Common::DeliveryMethod::EMAIL, login_id: 'someone@example.com', code: '123456'
99
102
  )
100
- session_token = jwt_response['sessionJwt']
101
- refresh_token = jwt_response['refreshJwt']
103
+ session_token = jwt_response[Descope::Mixins::Common::SESSION_TOKEN_NAME].fetch('jwt')
104
+ refresh_token = jwt_response[Descope::Mixins::Common::REFRESH_SESSION_TOKEN_NAME].fetch('jwt')
102
105
  ```
103
106
 
104
107
  The session and refresh JWTs should be returned to the caller, and passed with every request in the session. Read more on [session validation](#session-validation)
105
108
 
106
109
  ### Magic Link
107
110
 
108
- Send a user a Magic Link using your preferred delivery method (_email / SMS_).
109
- The Magic Link will redirect the user to page where the its token needs to be verified.
111
+ Send a user a Magic Link using your preferred delivery method (Email / SMS).
112
+ The Magic Link will redirect the user to page where the token needs to be verified.
110
113
  This redirection can be configured in code, or generally in the [Descope Console](https://app.descope.com/settings/authentication/magiclink)
111
114
 
112
115
  The user can either `sign up`, `sign in` or `sign up or in`
113
116
 
114
117
  ```ruby
115
118
  masked_address = descope_client.magiclink_sign_up_or_in(
116
- method: DeliveryMethod.EMAIL,
119
+ method: Descope::Mixins::Common::DeliveryMethod::EMAIL,
117
120
  login_id: 'desmond@descope.com',
118
121
  uri: 'https://myapp.com/verify-magic-link', # Set redirect URI here or via console
119
122
  )
@@ -123,8 +126,8 @@ To verify a magic link, your redirect page must call the validation function on
123
126
 
124
127
  ```ruby
125
128
  jwt_response = descope_client.magiclink_verify_token('token-here')
126
- session_token = jwt_response['sessionJwt']
127
- refresh_token = jwt_response['refreshJwt']
129
+ session_token = jwt_response[Descope::Mixins::Common::SESSION_TOKEN_NAME].fetch('jwt')
130
+ refresh_token = jwt_response[Descope::Mixins::Common::REFRESH_SESSION_TOKEN_NAME].fetch('jwt')
128
131
  ```
129
132
 
130
133
  The session and refresh JWTs should be returned to the caller, and passed with every request in the session. Read more on [session validation](#session-validation)
@@ -143,7 +146,7 @@ This method is similar to [Magic Link](#magic-link) but differs in two major way
143
146
  - This supports cross-device clicking, meaning the user can try to log in on one device,
144
147
  like a computer, while clicking the link on another device, for instance a mobile phone.
145
148
 
146
- The Enchanted Link will redirect the user to page where the its token needs to be verified.
149
+ The Enchanted Link will redirect the user to a page where the token needs to be verified.
147
150
  This redirection can be configured in code per request, or set globally in the [Descope Console](https://app.descope.com/settings/authentication/enchantedlink).
148
151
 
149
152
  The user can either `sign up`, `sign in` or `sign up or in`
@@ -162,6 +165,9 @@ After sending the link, you must poll to receive a valid session using the `pend
162
165
  the previous step. A valid session will be returned only after the user clicks the right link.
163
166
 
164
167
  ```ruby
168
+
169
+ pending_ref = res['pendingRef']
170
+
165
171
  def poll_for_session(descope_client, pending_ref)
166
172
  max_tries = 15
167
173
  i = 0
@@ -175,15 +181,15 @@ def poll_for_session(descope_client, pending_ref)
175
181
  jwt_response = descope_client.enchanted_link_get_session(pending_ref)
176
182
  done = true
177
183
  rescue Descope::AuthException, Descope::Unauthorized => e
178
- puts 'Failed pending session, err: #{e}'
184
+ puts "Failed pending session, err: #{e}"
179
185
  nil
180
186
  end
181
187
 
182
188
  if jwt_response
183
- puts 'jwt_response: #{jwt_response}'
189
+ puts "jwt_response: #{jwt_response}"
184
190
  refresh_token = jwt_response[Descope::Mixins::Common::REFRESH_SESSION_TOKEN_NAME]['jwt']
185
191
 
186
- puts 'refresh_token: #{refresh_token}'
192
+ puts "refresh_token: #{refresh_token}"
187
193
  puts :'Done logging out!'
188
194
  descope_client.sign_out(refresh_token)
189
195
  puts 'User logged out'
@@ -202,7 +208,8 @@ begin
202
208
  descope_client.enchanted_link_verify_token(token=token)
203
209
  # Token is valid
204
210
  rescue AuthException => e
205
- # Token is invalid
211
+ # Token is invalid
212
+ puts "Failed to verify token, err: #{e}"
206
213
  end
207
214
  ```
208
215
 
@@ -224,13 +231,13 @@ The user will authenticate with the authentication provider, and will be redirec
224
231
 
225
232
  ```ruby
226
233
  jwt_response = descope_client.oauth_exchange_token(code)
227
- session_token = jwt_response['sessionJwt']
228
- refresh_token = jwt_response['refreshJwt']
234
+ session_token = jwt_response[Descope::Mixins::Common::SESSION_TOKEN_NAME].fetch('jwt')
235
+ refresh_token = jwt_response[Descope::Mixins::Common::REFRESH_SESSION_TOKEN_NAME].fetch('jwt')
229
236
  ```
230
237
 
231
238
  The session and refresh JWTs should be returned to the caller, and passed with every request in the session. Read more on [session validation](#session-validation)
232
239
 
233
- ### SSO/SAML
240
+ ### SSO (SAML / OIDC)
234
241
 
235
242
  Users can authenticate to a specific tenant using SAML or Single Sign On. Configure your SSO/SAML settings on the [Descope console](https://app.descope.com/settings/authentication/sso). To start a flow call:
236
243
 
@@ -247,8 +254,8 @@ The user will authenticate with the authentication provider configured for that
247
254
 
248
255
  ```ruby
249
256
  jwt_response = descope_client.saml_exchange_token(code)
250
- session_token = jwt_response['sessionJwt']
251
- refresh_token = jwt_response['refreshJwt']
257
+ session_token = jwt_response[Descope::Mixins::Common::SESSION_TOKEN_NAME].fetch('jwt')
258
+ refresh_token = jwt_response[Descope::Mixins::Common::REFRESH_SESSION_TOKEN_NAME].fetch('jwt')
252
259
  ```
253
260
 
254
261
  The session and refresh JWTs should be returned to the caller, and passed with every request in the session. Read more on [session validation](#session-validation)
@@ -256,7 +263,7 @@ The session and refresh JWTs should be returned to the caller, and passed with e
256
263
  ### TOTP Authentication
257
264
 
258
265
  The user can authenticate using an authenticator app, such as Google Authenticator.
259
- Sign up like you would using any other authentication method. The sign up response
266
+ Sign up like you would use any other authentication method. The sign-up response
260
267
  will then contain a QR code `image` that can be displayed to the user to scan using
261
268
  their mobile device camera app, or the user can enter the `key` manually or click
262
269
  on the link provided by the `provisioning_url`.
@@ -267,7 +274,7 @@ Existing users can add TOTP using the `update` function.
267
274
  # Every user must have a login ID. All other user information is optional
268
275
  email = 'desmond@descope.com'
269
276
  user = {name: 'Desmond Copeland', phone: '212-555-1234', email: 'someone@example.com'}
270
- totp_response = descope_client.totp_sign_up(method: DeliveryMethod.EMAIL, login_id: 'someone@example.com', user: user)
277
+ totp_response = descope_client.totp_sign_up(method: Descope::Mixins::Common::DeliveryMethod::EMAIL, login_id: 'someone@example.com', user: user)
271
278
 
272
279
  # Use one of the provided options to have the user add their credentials to the authenticator
273
280
  provisioning_url = totp_response['provisioningURL']
@@ -285,8 +292,8 @@ jwt_response = descope_client.totp_sign_in_code(
285
292
  login_id: 'someone@example.com',
286
293
  code: '123456' # Code from authenticator app
287
294
  )
288
- session_token = jwt_response['sessionJwt']
289
- refresh_token = jwt_response['refreshJwt']
295
+ session_token = jwt_response[Descope::Mixins::Common::SESSION_TOKEN_NAME].fetch('jwt')
296
+ refresh_token = jwt_response[Descope::Mixins::Common::REFRESH_SESSION_TOKEN_NAME].fetch('jwt')
290
297
  ```
291
298
 
292
299
  The session and refresh JWTs should be returned to the caller, and passed with every request in the session. Read more on [session validation](#session-validation)
@@ -307,16 +314,16 @@ user = {
307
314
  email: login_id,
308
315
  }
309
316
  jwt_response = descope_client.password_sign_up(login_id:, password:, user:)
310
- session_token = jwt_response['sessionJwt']
311
- refresh_token = jwt_response['refreshJwt']
317
+ session_token = jwt_response[Descope::Mixins::Common::SESSION_TOKEN_NAME].fetch('jwt')
318
+ refresh_token = jwt_response[Descope::Mixins::Common::REFRESH_SESSION_TOKEN_NAME].fetch('jwt')
312
319
  ```
313
320
 
314
321
  The user can later sign in using the same login_id and password.
315
322
 
316
323
  ```ruby
317
324
  jwt_response = descope_client.password_sign_in(login_id:, password:)
318
- session_token = jwt_response['sessionJwt']
319
- refresh_token = jwt_response['refreshJwt']
325
+ session_token = jwt_response[Descope::Mixins::Common::SESSION_TOKEN_NAME].fetch('jwt')
326
+ refresh_token = jwt_response[Descope::Mixins::Common::REFRESH_SESSION_TOKEN_NAME].fetch('jwt')
320
327
  ```
321
328
 
322
329
  The session and refresh JWTs should be returned to the caller, and passed with every request in the session. Read more on [session validation](#session-validation)
@@ -325,7 +332,7 @@ In case the user needs to update their password, one of two methods are availabl
325
332
 
326
333
  **Changing Passwords**
327
334
 
328
- _NOTE: send_reset will only work if the user has a validated email address. Otherwise password reset prompts cannot be sent._
335
+ _NOTE: send_reset will only work if the user has a validated email address. Otherwise, password reset prompts cannot be sent._
329
336
 
330
337
  In the [password authentication method](https://app.descope.com/settings/authentication/password) in the Descope console, it is possible to define which alternative authentication method can be used in order to authenticate the user, in order to reset and update their password.
331
338
 
@@ -353,8 +360,8 @@ Alternatively, it is also possible to replace an existing active password with a
353
360
  ```ruby
354
361
  # Replaces the user's current password with a new one
355
362
  jwt_response = descope_client.password_replace(login_id: 'login', old_password: '1234', new_password: '4567')
356
- session_token = jwt_response['sessionJwt']
357
- refresh_token = jwt_response['refreshJwt']
363
+ session_token = jwt_response[Descope::Mixins::Common::SESSION_TOKEN_NAME].fetch('jwt')
364
+ refresh_token = jwt_response[Descope::Mixins::Common::REFRESH_SESSION_TOKEN_NAME].fetch('jwt')
358
365
  ```
359
366
 
360
367
  ### Session Validation
@@ -380,19 +387,19 @@ jwt_response = descope_client.validate_and_refresh_session('session_token', 'ref
380
387
 
381
388
  Choose the right session validation and refresh combination that suits your needs.
382
389
 
383
- Note: all those validation apis can receive an optional 'audience' parameter that should be provided when using jwt that has the 'aud' claim)
390
+ Note: all those validation apis can receive an optional 'audience' parameter that should be provided when using jwt that has the 'aud' claim.
384
391
 
385
392
  Refreshed sessions return the same response as is returned when users first sign up / log in,
386
- containing the session and refresh tokens, as well as all of the JWT claims.
393
+ containing the session and refresh tokens, as well as all the JWT claims.
387
394
  Make sure to return the tokens from the response to the client, or updated the cookie if you're using it.
388
395
 
389
396
  Usually, the tokens can be passed in and out via HTTP headers or via a cookie.
390
397
  The implementation can defer according to your framework of choice. See our [examples](#code-examples) for a few examples.
391
398
 
392
- If Roles & Permissions are used, validate them immediately after validating the session. See the [next section](#roles--permission-validation)
399
+ If Roles & Permissions are used, validate them immediately after validating the session. See the [next section](#roles-permission-validation)
393
400
  for more information.
394
401
 
395
- ### Roles & Permission Validation
402
+ ### Roles Permission Validation
396
403
 
397
404
  When using Roles & Permission, it's important to validate the user has the required
398
405
  authorization immediately after making sure the session is valid. Taking the `jwt_response`
@@ -459,13 +466,23 @@ After calling this function, you must invalidate or remove any cookies you have
459
466
  descope_client.sign_out('refresh_token')
460
467
  ```
461
468
 
462
- It is also possible to sign the user out of all the devices they are currently signed-in with. Calling `logout_all` will
469
+ It is also possible to sign the user out of all the devices they are currently signed in with. Calling `logout_all` will
463
470
  invalidate all user's refresh tokens. After calling this function, you must invalidate or remove any cookies you have created.
464
471
 
465
472
  ```ruby
466
473
  descope_client.sign_out_all('refresh_token')
467
474
  ```
468
475
 
476
+ ### History
477
+ You can get the current session user history.
478
+ The request requires a valid refresh token.
479
+
480
+ ```ruby
481
+ users_history_resp = descope_client.history(refresh_token)
482
+ for user_history in users_history_resp:
483
+ # Do something
484
+ ```
485
+
469
486
  ## Management API
470
487
 
471
488
  It is very common for some form of management or automation to be required. These can be performed
@@ -570,6 +587,16 @@ descope_client.update_user(
570
587
  user_tenants: client.associated_tenants_to_hash_array(associated_tenants)
571
588
  )
572
589
 
590
+ # Patch all user attribute in one api call
591
+ descope_client.patch_user(
592
+ login_id: 'desmond@descope.com',
593
+ email: 'desmond@descope.com',
594
+ given_name: 'Desmond',
595
+ family_name: 'Copeland',
596
+ display_name: 'Desmond Copeland',
597
+ user_tenants: client.associated_tenants_to_hash_array(associated_tenants)
598
+ )
599
+
573
600
  # Update explicit data for a user rather than overriding all fields
574
601
  descope_client.update_login_id(
575
602
  login_id: 'desmond@descope.com',
@@ -760,7 +787,7 @@ descope_client.update_role(
760
787
  descope_client.delete_role(name: 'My Updated Role', tenant_id: 'The tenant ID to which this role is associated, leave empty, if role is a global one')
761
788
 
762
789
  # Load all roles
763
- roles_resp = descope_client.load_all_roles()
790
+ roles_resp = descope_client.load_all_roles
764
791
  roles = roles_resp['roles']
765
792
  roles.each do |role|
766
793
  # Do something
@@ -769,11 +796,13 @@ roles = roles_resp['roles']
769
796
  ```
770
797
 
771
798
  # Search roles
799
+
800
+ ```ruby
772
801
  roles_resp = descope_client.search_roles(
773
- names: ['role1', 'role2'], # Search for roles with the names 'role1' and 'role2'
774
- role_name_like: 'role', # Search for roles that contain the string 'role'
775
- tenant_ids: ['tenant1', 'tenant2'], # Search for roles that are associated with the tenants 'tenant1' and 'tenant2'
776
- permission_names: ['permission1', 'permission2'] # Search for roles that have the permissions 'permission1' and 'permission2'
802
+ names: %w[role1 role2], # Search for roles with the names 'role1' and 'role2'
803
+ role_name_like: 'role', # Search for roles that contain the string 'role'
804
+ tenant_ids: %w[tenant1 tenant2], # Search for roles that are associated with the tenants 'tenant1' and 'tenant2'
805
+ permission_names: %w[permission1 permission2] # Search for roles that have the permissions 'permission1' and 'permission2'
777
806
  )
778
807
 
779
808
  roles = roles_resp['roles']
@@ -871,7 +900,7 @@ This token can then be verified using the magic link 'verify' function, either d
871
900
  token = descope_client.generate_embedded_link(login_id: 'desmond@descope.com', custom_claims: {'key1':'value1'})
872
901
  ```
873
902
 
874
- ### Search Audit
903
+ ### Audit
875
904
 
876
905
  You can perform an audit search for either specific values or full-text across the fields. Audit search is limited to the last 30 days.
877
906
  Below are some examples. For a full list of available search criteria options, see the function documentation.
@@ -898,6 +927,21 @@ audits = descope_client.audit_search(
898
927
  audits = descope_client.audit_search(actions: ['LoginSucceed'])
899
928
  ```
900
929
 
930
+ You can also create audit event with data
931
+
932
+ ```ruby
933
+ descope_client.audit_create_event(
934
+ actor_id: "UXXX", # required, for example a user ID
935
+ tenant_id: "tenant-id", # required
936
+ action: "pencil.created", # required
937
+ type: "info", # either: info/warn/error # required
938
+ data: {
939
+ pencil_id: "PXXX",
940
+ pencil_name: "Pencil Name"
941
+ } # optional
942
+ )
943
+ ```
944
+
901
945
  ### Manage ReBAC Authz
902
946
 
903
947
  Descope supports full relation based access control (ReBAC) using a [Google Zanzibar](https://research.google/pubs/pub48190/) like schema and operations.
@@ -1109,6 +1153,13 @@ descope_client.create_test_user(
1109
1153
  user_tenants: client.associated_tenants_to_hash_array(associated_tenants)
1110
1154
  )
1111
1155
 
1156
+ # Search all test users, optionally according to tenant and/or role filter
1157
+ # results can be paginated using the limit and page parameters
1158
+ users_resp = descope_client.search_all_test_users()
1159
+ users = users_resp["users"]
1160
+ users.each do |user|
1161
+ # Do something
1162
+
1112
1163
  # Now test user got created, and this user will be available until you delete it,
1113
1164
  # you can use any management operation for test user CRUD.
1114
1165
  # You can also delete all test users.
@@ -1116,14 +1167,14 @@ descope_client.delete_all_test_users
1116
1167
 
1117
1168
  # OTP code can be generated for test user, for example:
1118
1169
  resp = descope_client.generate_otp_for_test_user(
1119
- method: DeliveryMethod.EMAIL, login_id: 'login-id'
1170
+ method: Descope::Mixins::Common::DeliveryMethod::EMAIL, login_id: 'login-id'
1120
1171
  )
1121
1172
  code = resp['code']
1122
1173
  # Now you can verify the code is valid (using descope_client.*.verify for example)
1123
1174
 
1124
1175
  # Same as OTP, magic link can be generated for test user, for example:
1125
1176
  resp = descope_client.generate_magic_link_for_test_user(
1126
- method: DeliveryMethod.EMAIL,
1177
+ method: Descope::Mixins::Common::DeliveryMethod::EMAIL,
1127
1178
  login_id: 'login-id',
1128
1179
  )
1129
1180
  link = resp['link']
@@ -1136,6 +1187,78 @@ link = resp['link']
1136
1187
  pending_ref = resp['pendingRef']
1137
1188
  ```
1138
1189
 
1190
+ ### Manage SSO Applications
1191
+
1192
+ You can create, update, delete or load SSO applications:
1193
+
1194
+ ```ruby
1195
+ descope_client.create_sso_oidc_app(
1196
+ name: "My First sso app",
1197
+ login_page_url: "https://dummy.com/login",
1198
+ id: "my-custom-id", # this is optional
1199
+ )
1200
+
1201
+ # Create SAML sso application
1202
+ descope_client.create_saml_application(
1203
+ name: "My First sso app",
1204
+ login_page_url: "https://dummy.com/login",
1205
+ id: "my-custom-id", # this is optional
1206
+ use_metadata_info: true,
1207
+ metadata_url: "https://dummy.com/metadata",
1208
+ default_relay_state: "relayState",
1209
+ force_authentication: false,
1210
+ logout_redirect_url: "https://dummy.com/logout",
1211
+ )
1212
+ ```
1213
+
1214
+ # Update OIDC sso application
1215
+ # Update will override all fields as is. Use carefully.
1216
+
1217
+ ```ruby
1218
+ descope_client.update_sso_oidc_app(
1219
+ id: "my-custom-id",
1220
+ name: "My First sso app",
1221
+ login_page_url: "https://dummy.com/login",
1222
+ )
1223
+ ````
1224
+
1225
+ # Update SAML sso application
1226
+ # Update will override all fields as is. Use carefully.
1227
+
1228
+ ```ruby
1229
+ descope_client.update_saml_application(
1230
+ id: "my-custom-id",
1231
+ name: "My First sso app",
1232
+ login_page_url: "https://dummy.com/login",
1233
+ use_metadata_info: false,
1234
+ entity_id: "ent1234",
1235
+ acs_url: "https://dummy.com/acs",
1236
+ certificate: "my cert"
1237
+ )
1238
+ ```
1239
+
1240
+ # SSO application deletion cannot be undone. Use carefully.
1241
+
1242
+ ```ruby
1243
+ descope_client.delete_sso_app('my-custom-id')
1244
+ ```
1245
+
1246
+ # Load SSO application by id
1247
+
1248
+ ```ruby
1249
+ descope_client.load_sso_app('my-custom-id')
1250
+ ```
1251
+
1252
+ # Load all SSO applications
1253
+
1254
+ ```ruby
1255
+ resp = descope_client.load_all_sso_apps
1256
+ resp["apps"].each do |app|
1257
+ # Do something
1258
+ end
1259
+ ```
1260
+
1261
+
1139
1262
  ## API Rate Limits
1140
1263
 
1141
1264
  Handle API rate limits by comparing the exception to the APIRateLimitExceeded exception, which includes the RateLimitParameters map with the key 'Retry-After.' This key indicates how many seconds until the next valid API call can take place.
@@ -1143,7 +1266,7 @@ Handle API rate limits by comparing the exception to the APIRateLimitExceeded ex
1143
1266
  ```ruby
1144
1267
  begin
1145
1268
  descope_client.magiclink_sign_up_or_in(
1146
- method: DeliveryMethod.EMAIL,
1269
+ method: Descope::Mixins::Common::DeliveryMethod::EMAIL,
1147
1270
  login_id: 'desmond@descope.com',
1148
1271
  uri: 'https://myapp.com/verify-magic-link',
1149
1272
  )
data/descope.gemspec CHANGED
@@ -1,34 +1,39 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  $LOAD_PATH.push File.expand_path('../lib', __FILE__)
3
3
  require 'descope/version'
4
+ version = Descope::VERSION
4
5
 
5
6
  Gem::Specification.new do |s|
6
- s.name = 'descope'
7
- s.version = Descope::VERSION
8
- s.authors = ['Descope']
9
- s.email = ['support@descope.com']
10
- s.homepage = 'https://github.com/descope/descope-ruby-sdk'
11
- s.summary = 'Descope API Client'
12
- s.description = 'Ruby API Client for Descope API https://descope.com'
7
+ s.platform = Gem::Platform::RUBY
8
+ s.name = "descope"
9
+ s.version = version
10
+ s.summary = "Descope Ruby API Client"
11
+ s.description = "Ruby API Client for Descope API https://descope.com"
12
+
13
+ s.required_ruby_version = ">= 3.3.0"
14
+ s.required_rubygems_version = ">= 3.5"
15
+
16
+ s.author = "Descope Inc."
17
+ s.email = "support@descope.com"
18
+ s.homepage = "https://github.com/descope/descope-ruby-sdk"
19
+
20
+ s.license = "MIT"
13
21
 
14
22
  s.files = `git ls-files`.split("\n")
15
23
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
24
  s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
17
25
  s.require_paths = ['lib']
18
26
 
19
- s.add_runtime_dependency 'rest-client', '~> 2.1'
20
- s.add_runtime_dependency 'jwt', '~> 2.7'
21
- s.add_runtime_dependency 'zache', '~> 0.12'
27
+ s.metadata = {
28
+ "bug_tracker_uri" => "https://github.com/descope/descope-ruby-sdk/issues",
29
+ "changelog_uri" => "https://github.com/descope/descope-ruby-sdk/releases/tag/#{version}",
30
+ "documentation_uri" => "https://docs.descope.com",
31
+ "source_code_uri" => "https://github.com/descope/descope-ruby-sdk/tree/#{version}",
32
+ }
33
+
22
34
  s.add_runtime_dependency 'addressable', '~> 2.8'
35
+ s.add_runtime_dependency 'jwt', '~> 2.7'
36
+ s.add_runtime_dependency 'rest-client', '~> 2.1'
23
37
  s.add_runtime_dependency 'retryable', '~> 3.0'
24
-
25
- s.add_development_dependency 'bundler'
26
- s.add_development_dependency 'rake', '~> 13.0'
27
- s.add_development_dependency 'fuubar', '~> 2.0'
28
- s.add_development_dependency 'rspec', '~> 3.11'
29
- s.add_development_dependency 'simplecov', '~> 0.9'
30
- s.add_development_dependency 'faker', '~> 2.0'
31
- s.add_development_dependency "super_diff", "~> 1.0"
32
- s.add_development_dependency 'concurrent-ruby', '~> 1.1'
33
- s.license = 'MIT'
38
+ s.add_runtime_dependency 'zache', '~> 0.12'
34
39
  end
@@ -0,0 +1 @@
1
+ 3.3.0
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
+ require_relative './version_check'
4
5
  require 'descope'
5
6
 
6
7
  @logger = Logger.new($stdout)
@@ -25,17 +26,17 @@ begin
25
26
  login_options = {
26
27
  customClaims: { "k1": 'v1' }
27
28
  }
28
- jwt_response = @client.exchange_access_key(access_key:, login_options:)
29
+ jwt_response = @client.exchange_access_key(access_key: access_key, login_options: login_options)
29
30
  @logger.info('exchange access key successfully')
30
31
  @logger.info("jwt_response: #{jwt_response}")
31
32
 
32
33
  permission_name = 'TestPermission'
33
34
  permission_presented = @client.validate_permissions(
34
- jwt_response:, permissions: [permission_name]
35
+ jwt_response: jwt_response, permissions: [permission_name]
35
36
  )
36
37
  @logger.info("#{permission_name} presented on the jwt: [#{permission_presented}]")
37
38
  role_name = 'TestRole'
38
- role_presented = @client.validate_roles(jwt_response:, roles: [role_name])
39
+ role_presented = @client.validate_roles(jwt_response: jwt_response, roles: [role_name])
39
40
  @logger.info("#{role_name} presented on the jwt: [#{role_presented}]")
40
41
  rescue Descope::AuthException => e
41
42
  @logger.error("Failed to exchange access key #{e}")
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
+ require_relative './version_check'
4
5
  require 'descope'
5
6
 
6
7
  @logger = Logger.new($stdout)
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
+ require_relative './version_check'
4
5
  require 'descope'
5
6
 
6
7
  # include Descope::Mixin::Common
@@ -0,0 +1 @@
1
+ 3.3.0
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  # A sample Gemfile
3
- source 'http://rubygems.org'
3
+ source 'https://rubygems.org'
4
4
 
5
- gem 'descope'
5
+ gem 'descope'
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
+
5
+ require_relative '../version_check'
4
6
  require 'descope'
5
7
 
6
8
  @logger = Logger.new($stdout)