descope 1.0.7 → 1.2.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.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yaml +51 -12
  3. data/.github/workflows/publish-gem.yaml +6 -33
  4. data/.github/workflows/release-please.yaml +36 -0
  5. data/.gitignore +3 -2
  6. data/.release-please-manifest.json +1 -1
  7. data/.rubocop.yml +1 -1
  8. data/.rubocop_todo.yml +1 -1
  9. data/.ruby-version +1 -1
  10. data/CHANGELOG.md +31 -0
  11. data/Gemfile +7 -6
  12. data/Gemfile.lock +46 -45
  13. data/README.md +244 -1
  14. data/examples/ruby-on-rails-api/descope/package-lock.json +16 -10
  15. data/examples/ruby-on-rails-api/descope/yarn.lock +3 -3
  16. data/lib/descope/api/v1/auth/enchantedlink.rb +76 -9
  17. data/lib/descope/api/v1/management/access_key.rb +8 -7
  18. data/lib/descope/api/v1/management/analytics.rb +62 -0
  19. data/lib/descope/api/v1/management/audit.rb +2 -2
  20. data/lib/descope/api/v1/management/authz.rb +15 -15
  21. data/lib/descope/api/v1/management/common.rb +76 -0
  22. data/lib/descope/api/v1/management/descoper.rb +45 -0
  23. data/lib/descope/api/v1/management/engine.rb +44 -0
  24. data/lib/descope/api/v1/management/fga.rb +64 -0
  25. data/lib/descope/api/v1/management/flow.rb +5 -5
  26. data/lib/descope/api/v1/management/group.rb +42 -0
  27. data/lib/descope/api/v1/management/jwt_template.rb +49 -0
  28. data/lib/descope/api/v1/management/lists.rb +96 -0
  29. data/lib/descope/api/v1/management/management_key.rb +54 -0
  30. data/lib/descope/api/v1/management/outbound_app.rb +112 -0
  31. data/lib/descope/api/v1/management/password.rb +2 -2
  32. data/lib/descope/api/v1/management/permission.rb +4 -4
  33. data/lib/descope/api/v1/management/project.rb +5 -5
  34. data/lib/descope/api/v1/management/role.rb +5 -5
  35. data/lib/descope/api/v1/management/scim.rb +14 -14
  36. data/lib/descope/api/v1/management/scope_claim_mapping.rb +34 -0
  37. data/lib/descope/api/v1/management/sso_application.rb +7 -7
  38. data/lib/descope/api/v1/management/sso_settings.rb +5 -5
  39. data/lib/descope/api/v1/management/tenant.rb +8 -6
  40. data/lib/descope/api/v1/management/third_party_application.rb +190 -0
  41. data/lib/descope/api/v1/management/user.rb +36 -36
  42. data/lib/descope/api/v1/management.rb +22 -0
  43. data/lib/descope/http_client.rb +30 -0
  44. data/lib/descope/mixins/common.rb +1 -0
  45. data/lib/descope/mixins/http.rb +25 -18
  46. data/lib/descope/mixins/initializer.rb +23 -11
  47. data/lib/descope/mixins/requests.rb +24 -0
  48. data/lib/descope/mixins.rb +2 -1
  49. data/lib/descope/version.rb +1 -1
  50. data/spec/integration/lib.descope/api/v1/auth/enchantedlink_spec.rb +19 -21
  51. data/spec/integration/lib.descope/api/v1/auth/magiclink_spec.rb +5 -1
  52. data/spec/integration/lib.descope/api/v1/auth/otp_spec.rb +5 -1
  53. data/spec/integration/lib.descope/api/v1/auth/session_spec.rb +24 -5
  54. data/spec/integration/lib.descope/api/v1/auth/totp_spec.rb +5 -1
  55. data/spec/integration/lib.descope/api/v1/management/access_key_spec.rb +10 -2
  56. data/spec/integration/lib.descope/api/v1/management/authz_spec.rb +26 -5
  57. data/spec/integration/lib.descope/api/v1/management/permissions_spec.rb +20 -2
  58. data/spec/integration/lib.descope/api/v1/management/project_spec.rb +16 -2
  59. data/spec/integration/lib.descope/api/v1/management/roles_spec.rb +114 -36
  60. data/spec/integration/lib.descope/api/v1/management/user_spec.rb +21 -4
  61. data/spec/lib.descope/api/v1/auth/enchantedlink_spec.rb +163 -1
  62. data/spec/lib.descope/api/v1/management/access_key_spec.rb +7 -7
  63. data/spec/lib.descope/api/v1/management/analytics_spec.rb +82 -0
  64. data/spec/lib.descope/api/v1/management/audit_spec.rb +2 -2
  65. data/spec/lib.descope/api/v1/management/authz_spec.rb +16 -16
  66. data/spec/lib.descope/api/v1/management/descoper_spec.rb +101 -0
  67. data/spec/lib.descope/api/v1/management/engine_spec.rb +115 -0
  68. data/spec/lib.descope/api/v1/management/fga_spec.rb +169 -0
  69. data/spec/lib.descope/api/v1/management/flow_spec.rb +5 -5
  70. data/spec/lib.descope/api/v1/management/group_spec.rb +72 -0
  71. data/spec/lib.descope/api/v1/management/jwt_template_spec.rb +103 -0
  72. data/spec/lib.descope/api/v1/management/lists_spec.rb +285 -0
  73. data/spec/lib.descope/api/v1/management/management_key_spec.rb +109 -0
  74. data/spec/lib.descope/api/v1/management/outbound_app_spec.rb +236 -0
  75. data/spec/lib.descope/api/v1/management/password_spec.rb +2 -2
  76. data/spec/lib.descope/api/v1/management/permission_spec.rb +4 -4
  77. data/spec/lib.descope/api/v1/management/project_spec.rb +4 -4
  78. data/spec/lib.descope/api/v1/management/role_spec.rb +5 -5
  79. data/spec/lib.descope/api/v1/management/scim_spec.rb +14 -14
  80. data/spec/lib.descope/api/v1/management/scope_claim_mapping_spec.rb +59 -0
  81. data/spec/lib.descope/api/v1/management/sso_application_spec.rb +6 -6
  82. data/spec/lib.descope/api/v1/management/sso_settings_spec.rb +5 -5
  83. data/spec/lib.descope/api/v1/management/tenant_spec.rb +6 -6
  84. data/spec/lib.descope/api/v1/management/third_party_application_spec.rb +171 -0
  85. data/spec/lib.descope/api/v1/management/user_spec.rb +36 -36
  86. data/spec/lib.descope/auth_management_key_spec.rb +151 -0
  87. data/spec/lib.descope/mixins/http_spec.rb +17 -6
  88. data/spec/support/client_config.rb +1 -0
  89. data/spec/support/dummy_class.rb +12 -9
  90. data/spec/support/utils.rb +15 -0
  91. metadata +29 -3
@@ -0,0 +1,190 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Descope
4
+ module Api
5
+ module V1
6
+ module Management
7
+ # Management API calls for third party applications
8
+ module ThirdPartyApplication
9
+ include Descope::Api::V1::Management::Common
10
+
11
+ def create_application(
12
+ name: nil,
13
+ id: nil,
14
+ description: nil,
15
+ logo: nil,
16
+ login_page_url: nil,
17
+ approved_callback_urls: nil,
18
+ permissions_scopes: nil,
19
+ attributes_scopes: nil,
20
+ jwt_bearer_settings: nil,
21
+ custom_attributes: nil,
22
+ force_pkce: nil,
23
+ default_audience: nil
24
+ )
25
+ # Create a new third party application with the given name. Application IDs are provisioned automatically,
26
+ # but can be provided explicitly if needed. Both the name and ID must be unique per project.
27
+ body = compose_create_update_body(
28
+ name:,
29
+ id:,
30
+ description:,
31
+ logo:,
32
+ login_page_url:,
33
+ approved_callback_urls:,
34
+ permissions_scopes:,
35
+ attributes_scopes:,
36
+ jwt_bearer_settings:,
37
+ custom_attributes:,
38
+ force_pkce:,
39
+ default_audience:
40
+ )
41
+ mgmt_post(THIRD_PARTY_APP_CREATE_PATH, body)
42
+ end
43
+
44
+ def update_application(
45
+ id: nil,
46
+ name: nil,
47
+ description: nil,
48
+ logo: nil,
49
+ login_page_url: nil,
50
+ approved_callback_urls: nil,
51
+ permissions_scopes: nil,
52
+ attributes_scopes: nil,
53
+ jwt_bearer_settings: nil,
54
+ custom_attributes: nil,
55
+ force_pkce: nil,
56
+ default_audience: nil
57
+ )
58
+ # Update an existing third party application with the given parameters. IMPORTANT: All parameters are used as
59
+ # overrides to the existing application. Empty fields will override populated fields. Use carefully.
60
+ body = compose_create_update_body(
61
+ name:,
62
+ id:,
63
+ description:,
64
+ logo:,
65
+ login_page_url:,
66
+ approved_callback_urls:,
67
+ permissions_scopes:,
68
+ attributes_scopes:,
69
+ jwt_bearer_settings:,
70
+ custom_attributes:,
71
+ force_pkce:,
72
+ default_audience:
73
+ )
74
+ mgmt_post(THIRD_PARTY_APP_UPDATE_PATH, body)
75
+ end
76
+
77
+ def patch_application(
78
+ id: nil,
79
+ name: nil,
80
+ description: nil,
81
+ logo: nil,
82
+ login_page_url: nil,
83
+ approved_callback_urls: nil,
84
+ permissions_scopes: nil,
85
+ attributes_scopes: nil,
86
+ jwt_bearer_settings: nil,
87
+ custom_attributes: nil,
88
+ force_pkce: nil,
89
+ default_audience: nil
90
+ )
91
+ # Patch an existing third party application. Only the provided fields will be updated.
92
+ body = compose_create_update_body(
93
+ name:,
94
+ id:,
95
+ description:,
96
+ logo:,
97
+ login_page_url:,
98
+ approved_callback_urls:,
99
+ permissions_scopes:,
100
+ attributes_scopes:,
101
+ jwt_bearer_settings:,
102
+ custom_attributes:,
103
+ force_pkce:,
104
+ default_audience:
105
+ )
106
+ mgmt_post(THIRD_PARTY_APP_PATCH_PATH, body)
107
+ end
108
+
109
+ def delete_application(id)
110
+ # Delete an existing third party application. IMPORTANT: This operation is irreversible. Use carefully.
111
+ mgmt_post(THIRD_PARTY_APP_DELETE_PATH, { id: })
112
+ end
113
+
114
+ def load_application(id)
115
+ # Load an existing third party application.
116
+ mgmt_get(THIRD_PARTY_APP_LOAD_PATH, { id: })
117
+ end
118
+
119
+ def load_all_applications
120
+ # Load all third party applications.
121
+ mgmt_get(THIRD_PARTY_APP_LOAD_ALL_PATH, {})
122
+ end
123
+
124
+ def get_application_secret(id)
125
+ # Get the cleartext secret of an existing third party application.
126
+ mgmt_get(THIRD_PARTY_APP_SECRET_PATH, { id: })
127
+ end
128
+
129
+ def rotate_application_secret(id)
130
+ # Rotate the secret of an existing third party application, returning the new cleartext secret.
131
+ mgmt_post(THIRD_PARTY_APP_ROTATE_PATH, { id: })
132
+ end
133
+
134
+ def delete_consents(app_id: nil, consent_ids: nil, user_ids: nil, tenant_id: nil)
135
+ # Delete consents of a third party application.
136
+ body = {}
137
+ body[:consentIds] = consent_ids if consent_ids
138
+ body[:appId] = app_id if app_id
139
+ body[:userIds] = user_ids if user_ids
140
+ body[:tenantId] = tenant_id if tenant_id
141
+ mgmt_post(THIRD_PARTY_APP_DELETE_CONSENTS_PATH, body)
142
+ end
143
+
144
+ def delete_tenant_consents(app_id: nil, consent_ids: nil, tenant_id: nil)
145
+ # Delete consents of a third party application for a specific tenant.
146
+ body = {}
147
+ body[:consentIds] = consent_ids if consent_ids
148
+ body[:appId] = app_id if app_id
149
+ body[:tenantId] = tenant_id if tenant_id
150
+ mgmt_post(THIRD_PARTY_APP_DELETE_TENANT_CONSENTS_PATH, body)
151
+ end
152
+
153
+ private
154
+
155
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
156
+ def compose_create_update_body(
157
+ name: nil,
158
+ id: nil,
159
+ description: nil,
160
+ logo: nil,
161
+ login_page_url: nil,
162
+ approved_callback_urls: nil,
163
+ permissions_scopes: nil,
164
+ attributes_scopes: nil,
165
+ jwt_bearer_settings: nil,
166
+ custom_attributes: nil,
167
+ force_pkce: nil,
168
+ default_audience: nil
169
+ )
170
+ body = {}
171
+ body[:id] = id if id
172
+ body[:name] = name if name
173
+ body[:description] = description if description
174
+ body[:logo] = logo if logo
175
+ body[:loginPageUrl] = login_page_url if login_page_url
176
+ body[:approvedCallbackUrls] = approved_callback_urls if approved_callback_urls
177
+ body[:permissionsScopes] = permissions_scopes if permissions_scopes
178
+ body[:attributesScopes] = attributes_scopes if attributes_scopes
179
+ body[:jwtBearerSettings] = jwt_bearer_settings if jwt_bearer_settings
180
+ body[:customAttributes] = custom_attributes if custom_attributes
181
+ body[:forcePkce] = force_pkce unless force_pkce.nil?
182
+ body[:defaultAudience] = default_audience if default_audience
183
+ body
184
+ end
185
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end
@@ -27,7 +27,7 @@ module Descope
27
27
  request_params = {
28
28
  users: users_params
29
29
  }
30
- post(path, request_params)
30
+ mgmt_post(path, request_params)
31
31
  end
32
32
 
33
33
  # Create a new test user.
@@ -102,7 +102,7 @@ module Descope
102
102
  hashed_password:,
103
103
  sso_app_ids:
104
104
  )
105
- post(path, request_params)
105
+ mgmt_post(path, request_params)
106
106
  end
107
107
 
108
108
  # Delete a user, using a valid management key.
@@ -113,12 +113,12 @@ module Descope
113
113
  request_params = {
114
114
  loginId: login_id
115
115
  }
116
- post(path, request_params)
116
+ mgmt_post(path, request_params)
117
117
  end
118
118
 
119
119
  def delete_all_test_users
120
120
  path = Common::USER_DELETE_ALL_TEST_USERS_PATH
121
- delete(path)
121
+ mgmt_delete(path)
122
122
  end
123
123
 
124
124
  # Load a user's data, using a valid management key.
@@ -132,7 +132,7 @@ module Descope
132
132
  loginId: login_id
133
133
  }
134
134
  path = Common::USER_LOAD_PATH
135
- get(path, request_params)
135
+ mgmt_get(path, request_params)
136
136
  end
137
137
 
138
138
  # Load a user's data, using a valid management key by user id.
@@ -146,7 +146,7 @@ module Descope
146
146
  request_params = {
147
147
  userId: user_id
148
148
  }
149
- get(path, request_params)
149
+ mgmt_get(path, request_params)
150
150
  end
151
151
 
152
152
  # Log a user out of all sessions, using a valid management key.
@@ -157,7 +157,7 @@ module Descope
157
157
  request_params = {
158
158
  loginId: login_id
159
159
  }
160
- post(path, request_params)
160
+ mgmt_post(path, request_params)
161
161
  end
162
162
 
163
163
  def logout_user_by_id(user_id)
@@ -166,7 +166,7 @@ module Descope
166
166
  request_params = {
167
167
  userId: user_id
168
168
  }
169
- post(path, request_params)
169
+ mgmt_post(path, request_params)
170
170
  end
171
171
 
172
172
  # Search for users, using a valid management key.
@@ -216,7 +216,7 @@ module Descope
216
216
  body[:roleNames] = role_names unless role_names.empty?
217
217
  body[:tenantRoleIds] = map_to_values_object(tenant_role_ids) unless tenant_role_ids.nil? || tenant_role_ids.empty?
218
218
  body[:tenantRoleNames] = map_to_values_object(tenant_role_names) unless tenant_role_names.nil? || tenant_role_names.empty?
219
- post(Common::USERS_SEARCH_PATH, body)
219
+ mgmt_post(Common::USERS_SEARCH_PATH, body)
220
220
  end
221
221
 
222
222
  def map_to_values_object(input_map)
@@ -234,7 +234,7 @@ module Descope
234
234
  loginId: login_id,
235
235
  provider: provider
236
236
  }
237
- get(path, request_params)
237
+ mgmt_get(path, request_params)
238
238
  end
239
239
 
240
240
  # Updates an existing user's status, using a valid management key.
@@ -246,7 +246,7 @@ module Descope
246
246
  loginId: login_id,
247
247
  status: 'enabled'
248
248
  }
249
- post(path, request_params)
249
+ mgmt_post(path, request_params)
250
250
  end
251
251
 
252
252
  def deactivate(login_id)
@@ -256,7 +256,7 @@ module Descope
256
256
  loginId: login_id,
257
257
  status: 'disabled'
258
258
  }
259
- post(path, request_params)
259
+ mgmt_post(path, request_params)
260
260
  end
261
261
 
262
262
  # Updates an existing user's login ID, using a valid management key.
@@ -268,7 +268,7 @@ module Descope
268
268
  loginId: login_id,
269
269
  newLoginId: new_login_id
270
270
  }
271
- post(path, request_params)
271
+ mgmt_post(path, request_params)
272
272
  end
273
273
 
274
274
  # Updates an existing user's email, using a valid management key.
@@ -281,7 +281,7 @@ module Descope
281
281
  email:,
282
282
  verified:
283
283
  }
284
- post(path, request_params)
284
+ mgmt_post(path, request_params)
285
285
  end
286
286
 
287
287
  # Updates an existing user's phone number, using a valid management key.
@@ -293,7 +293,7 @@ module Descope
293
293
  phone:,
294
294
  verified:
295
295
  }
296
- post(path, request_params)
296
+ mgmt_post(path, request_params)
297
297
  end
298
298
 
299
299
  # Updates an existing user's display name, using a valid management key.
@@ -310,7 +310,7 @@ module Descope
310
310
  body[:givenName] = given_name unless given_name.nil?
311
311
  body[:middleName] = middle_name unless middle_name.nil?
312
312
  body[:familyName] = family_name unless family_name.nil?
313
- post(Common::USER_UPDATE_NAME_PATH, body)
313
+ mgmt_post(Common::USER_UPDATE_NAME_PATH, body)
314
314
  end
315
315
 
316
316
  # Update an existing user's profile picture, using a valid management key.
@@ -320,7 +320,7 @@ module Descope
320
320
  loginId: login_id,
321
321
  picture: picture
322
322
  }
323
- post(Common::USER_UPDATE_PICTURE_PATH, body)
323
+ mgmt_post(Common::USER_UPDATE_PICTURE_PATH, body)
324
324
  end
325
325
 
326
326
  # Update an existing user's custom attributes, using a valid management key.
@@ -332,7 +332,7 @@ module Descope
332
332
  attributeKey: attribute_key,
333
333
  attributeValue: attribute_value
334
334
  }
335
- post(Common::USER_UPDATE_CUSTOM_ATTRIBUTE_PATH, body)
335
+ mgmt_post(Common::USER_UPDATE_CUSTOM_ATTRIBUTE_PATH, body)
336
336
  end
337
337
 
338
338
  def patch_user(
@@ -377,7 +377,7 @@ module Descope
377
377
  hashed_password:,
378
378
  sso_app_ids:
379
379
  )
380
- patch(path, request_params)
380
+ mgmt_patch(path, request_params)
381
381
  end
382
382
 
383
383
  def update_jwt(jwt: nil, custom_claims: nil)
@@ -385,7 +385,7 @@ module Descope
385
385
  jwt:,
386
386
  customClaims: custom_claims,
387
387
  }
388
- post(Common::UPDATE_JWT_PATH, body)
388
+ mgmt_post(Common::UPDATE_JWT_PATH, body)
389
389
  end
390
390
 
391
391
  #
@@ -395,7 +395,7 @@ module Descope
395
395
  roleNames: role_names,
396
396
  tenantId: tenant_id
397
397
  }
398
- post(Common::USER_ADD_ROLE_PATH, body)
398
+ mgmt_post(Common::USER_ADD_ROLE_PATH, body)
399
399
  end
400
400
 
401
401
  def user_remove_roles(login_id: nil, tenant_id:nil, role_names: [])
@@ -404,7 +404,7 @@ module Descope
404
404
  roleNames: role_names,
405
405
  tenantId: tenant_id
406
406
  }
407
- post(Common::USER_REMOVE_ROLE_PATH, body)
407
+ mgmt_post(Common::USER_REMOVE_ROLE_PATH, body)
408
408
  end
409
409
 
410
410
  def user_add_tenant(login_id: nil, tenant_id: nil)
@@ -412,7 +412,7 @@ module Descope
412
412
  loginId: login_id,
413
413
  tenantId: tenant_id
414
414
  }
415
- post(Common::USER_ADD_TENANT_PATH, body)
415
+ mgmt_post(Common::USER_ADD_TENANT_PATH, body)
416
416
  end
417
417
 
418
418
  def user_remove_tenant(login_id: nil, tenant_id: nil)
@@ -420,7 +420,7 @@ module Descope
420
420
  loginId: login_id,
421
421
  tenantId: tenant_id
422
422
  }
423
- post(Common::USER_REMOVE_TENANT_PATH, body)
423
+ mgmt_post(Common::USER_REMOVE_TENANT_PATH, body)
424
424
  end
425
425
 
426
426
  def add_tenant_role(login_id: nil, tenant_id: nil, role_names: [])
@@ -429,7 +429,7 @@ module Descope
429
429
  tenantId: tenant_id,
430
430
  roleNames: role_names
431
431
  }
432
- post(Common::USER_ADD_TENANT_PATH, body)
432
+ mgmt_post(Common::USER_ADD_TENANT_PATH, body)
433
433
  end
434
434
 
435
435
  def user_remove_tenant_roles(login_id: nil, tenant_id: nil, role_names: [])
@@ -438,7 +438,7 @@ module Descope
438
438
  tenantId: tenant_id,
439
439
  roleNames: role_names
440
440
  }
441
- post(Common::USER_REMOVE_TENANT_PATH, body)
441
+ mgmt_post(Common::USER_REMOVE_TENANT_PATH, body)
442
442
  end
443
443
 
444
444
  def set_temporary_password(login_id: nil, password: nil)
@@ -446,7 +446,7 @@ module Descope
446
446
  loginId: login_id,
447
447
  password:
448
448
  }
449
- post(Common::USER_SET_TEMPORARY_PASSWORD_PATH, body)
449
+ mgmt_post(Common::USER_SET_TEMPORARY_PASSWORD_PATH, body)
450
450
  end
451
451
 
452
452
  def set_active_password(login_id: nil, password: nil)
@@ -454,7 +454,7 @@ module Descope
454
454
  loginId: login_id,
455
455
  password:
456
456
  }
457
- post(Common::USER_SET_ACTIVE_PASSWORD_PATH, body)
457
+ mgmt_post(Common::USER_SET_ACTIVE_PASSWORD_PATH, body)
458
458
  end
459
459
 
460
460
  # Deprecated (use set_temporary_password(..) instead)
@@ -463,7 +463,7 @@ module Descope
463
463
  loginId: login_id,
464
464
  password:
465
465
  }
466
- post(Common::USER_SET_PASSWORD_PATH, body)
466
+ mgmt_post(Common::USER_SET_PASSWORD_PATH, body)
467
467
  end
468
468
 
469
469
  def expire_password(login_id)
@@ -471,7 +471,7 @@ module Descope
471
471
  body = {
472
472
  loginId: login_id
473
473
  }
474
- post(Common::USER_EXPIRE_PASSWORD_PATH, body)
474
+ mgmt_post(Common::USER_EXPIRE_PASSWORD_PATH, body)
475
475
  end
476
476
 
477
477
  def generate_otp_for_test_user(method: nil, login_id: nil)
@@ -479,7 +479,7 @@ module Descope
479
479
  loginId: login_id,
480
480
  deliveryMethod: get_method_string(method)
481
481
  }
482
- post(Common::USER_GENERATE_OTP_FOR_TEST_PATH, body)
482
+ mgmt_post(Common::USER_GENERATE_OTP_FOR_TEST_PATH, body)
483
483
  end
484
484
 
485
485
  def generate_magic_link_for_test_user(method: nil, login_id: nil, uri: nil)
@@ -488,7 +488,7 @@ module Descope
488
488
  deliveryMethod: get_method_string(method),
489
489
  URI: uri
490
490
  }
491
- post(Common::USER_GENERATE_MAGIC_LINK_FOR_TEST_PATH, body)
491
+ mgmt_post(Common::USER_GENERATE_MAGIC_LINK_FOR_TEST_PATH, body)
492
492
  end
493
493
 
494
494
  def generate_enchanted_link_for_test_user(login_id: nil, uri: nil)
@@ -496,7 +496,7 @@ module Descope
496
496
  loginId: login_id,
497
497
  URI: uri
498
498
  }
499
- post(Common::USER_GENERATE_ENCHANTED_LINK_FOR_TEST_PATH, body)
499
+ mgmt_post(Common::USER_GENERATE_ENCHANTED_LINK_FOR_TEST_PATH, body)
500
500
  end
501
501
 
502
502
  def generate_embedded_link(login_id: nil, custom_claims: nil)
@@ -513,7 +513,7 @@ module Descope
513
513
  loginId: login_id,
514
514
  customClaims: custom_claims.to_h
515
515
  }
516
- post(USER_GENERATE_EMBEDDED_LINK_PATH, request_params)
516
+ mgmt_post(USER_GENERATE_EMBEDDED_LINK_PATH, request_params)
517
517
  end
518
518
 
519
519
  # Search for all test users.
@@ -582,7 +582,7 @@ module Descope
582
582
  body[:tenantRoleIds] = map_to_values_object(tenant_role_ids) unless tenant_role_ids.nil? || tenant_role_ids.empty?
583
583
  body[:tenantRoleNames] = map_to_values_object(tenant_role_names) unless tenant_role_names.nil? || tenant_role_names.empty?
584
584
 
585
- post(Common::TEST_USERS_SEARCH_PATH, body)
585
+ mgmt_post(Common::TEST_USERS_SEARCH_PATH, body)
586
586
  end
587
587
 
588
588
 
@@ -647,7 +647,7 @@ module Descope
647
647
  )
648
648
  return request_params if skip_create
649
649
 
650
- post(path, request_params)
650
+ mgmt_post(path, request_params)
651
651
  end
652
652
 
653
653
  def user_compose_create_body(
@@ -14,6 +14,17 @@ require 'descope/api/v1/management/sso_application'
14
14
  require 'descope/api/v1/management/sso_settings'
15
15
  require 'descope/api/v1/management/scim'
16
16
  require 'descope/api/v1/management/password'
17
+ require 'descope/api/v1/management/outbound_app'
18
+ require 'descope/api/v1/management/group'
19
+ require 'descope/api/v1/management/fga'
20
+ require 'descope/api/v1/management/third_party_application'
21
+ require 'descope/api/v1/management/management_key'
22
+ require 'descope/api/v1/management/analytics'
23
+ require 'descope/api/v1/management/descoper'
24
+ require 'descope/api/v1/management/engine'
25
+ require 'descope/api/v1/management/lists'
26
+ require 'descope/api/v1/management/jwt_template'
27
+ require 'descope/api/v1/management/scope_claim_mapping'
17
28
 
18
29
  module Descope
19
30
  module Api
@@ -34,6 +45,17 @@ module Descope
34
45
  include Descope::Api::V1::Management::SSOSettings
35
46
  include Descope::Api::V1::Management::SCIM
36
47
  include Descope::Api::V1::Management::Password
48
+ include Descope::Api::V1::Management::OutboundApp
49
+ include Descope::Api::V1::Management::Group
50
+ include Descope::Api::V1::Management::FGA
51
+ include Descope::Api::V1::Management::ThirdPartyApplication
52
+ include Descope::Api::V1::Management::ManagementKey
53
+ include Descope::Api::V1::Management::Analytics
54
+ include Descope::Api::V1::Management::Descoper
55
+ include Descope::Api::V1::Management::Engine
56
+ include Descope::Api::V1::Management::Lists
57
+ include Descope::Api::V1::Management::JWTTemplate
58
+ include Descope::Api::V1::Management::ScopeClaimMapping
37
59
  end
38
60
  end
39
61
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'descope/mixins/http'
4
+
5
+ module Descope
6
+ # Performs the SDK's HTTP calls. One instance is created per kind of request so that the two
7
+ # management keys are never sent together: the management client carries the management key, the
8
+ # authentication client carries the auth management key.
9
+ class HttpClient
10
+ include Descope::Mixins::HTTP
11
+
12
+ def initialize(base_uri:, project_id:, headers:, logger:, key: nil, timeout: nil, retry_count: nil)
13
+ @base_uri = base_uri
14
+ @project_id = project_id
15
+ @key = key
16
+ @headers = headers.dup
17
+ @logger = logger
18
+ @timeout = timeout
19
+ @retry_count = retry_count
20
+ end
21
+
22
+ # Bearer <project_id>[:<pswd>][:<key>] where pswd is a refresh token or access key presented by
23
+ # the caller and key is this client's management key. Blank parts are skipped, so callers do
24
+ # not have to branch on what happens to be configured.
25
+ def authorization_header(pswd = nil)
26
+ bearer = [@project_id, pswd, @key].reject { |part| part.nil? || part.to_s.empty? }.join(':')
27
+ { 'Authorization' => "Bearer #{bearer}" }
28
+ end
29
+ end
30
+ end
@@ -81,6 +81,7 @@ module Descope
81
81
  VERIFY_ENCHANTEDLINK_AUTH_PATH = '/v1/auth/enchantedlink/verify'
82
82
  GET_SESSION_ENCHANTEDLINK_AUTH_PATH = '/v1/auth/enchantedlink/pending-session'
83
83
  UPDATE_USER_EMAIL_ENCHANTEDLINK_PATH = '/v1/auth/enchantedlink/update/email'
84
+ UPDATE_USER_PHONE_ENCHANTEDLINK_PATH = '/v1/auth/enchantedlink/update/phone'
84
85
 
85
86
  # oauth
86
87
  OAUTH_START_PATH = '/v1/auth/oauth/authorize'
@@ -18,13 +18,18 @@ module Descope
18
18
  MIN_REQUEST_RETRY_DELAY = 250
19
19
  BASE_DELAY = 100
20
20
 
21
- %i[get post post_file post_form put patch delete delete_with_body].each do |method|
21
+ HTTP_METHODS = %i[get post put patch delete].freeze
22
+
23
+ HTTP_METHODS.each do |method|
22
24
  define_method(method) do |uri, body = {}, extra_headers = {}, pswd = nil|
23
25
  body = body.delete_if { |_, v| v.nil? }
24
- authorization_header(pswd) # This will set the pswd if provided, else default to the @default_pswd
26
+
27
+ # The Authorization header travels with the request rather than being merged into the
28
+ # shared @headers, so concurrent requests cannot send each other's credentials.
29
+ headers = authorization_header(pswd).merge(extra_headers || {})
25
30
 
26
31
  @logger.debug "request => method: #{method}, uri: #{uri}, body: #{body}, extra_headers: #{extra_headers}}"
27
- request_with_retry(method, uri, body, extra_headers)
32
+ request_with_retry(method, uri, body, headers)
28
33
  end
29
34
  end
30
35
 
@@ -63,9 +68,9 @@ module Descope
63
68
  # If no cookies found via RestClient, parse Set-Cookie headers directly
64
69
  # This handles custom domain cookies that RestClient filters out
65
70
  if extracted_cookies.empty? && headers.respond_to?(:[])
66
- set_cookie_headers = headers['set-cookie'] || headers['Set-Cookie'] || []
71
+ set_cookie_headers = headers[:set_cookie] || headers['set-cookie'] || headers['Set-Cookie'] || []
67
72
  set_cookie_headers = [set_cookie_headers] unless set_cookie_headers.is_a?(Array)
68
-
73
+
69
74
  set_cookie_headers.each do |cookie_header|
70
75
  next unless cookie_header.is_a?(String)
71
76
 
@@ -118,6 +123,15 @@ module Descope
118
123
  @headers.merge!(h.to_hash)
119
124
  end
120
125
 
126
+ # Everything after the project ID in the bearer is either a token or a management key, so
127
+ # none of it belongs in a log line.
128
+ def mask_authorization(headers)
129
+ authorization = headers['Authorization']
130
+ return headers if authorization.nil?
131
+
132
+ headers.merge('Authorization' => authorization.sub(/\A(Bearer [^:]*):.*\z/, '\1:***'))
133
+ end
134
+
121
135
  def request_with_retry(method, uri, body = {}, extra_headers = {}, pswd = nil)
122
136
  Retryable.retryable(retry_options) do
123
137
  request(method, uri, body, extra_headers)
@@ -125,23 +139,16 @@ module Descope
125
139
  end
126
140
 
127
141
  def request(method, uri, body = {}, extra_headers = {})
128
- # @headers is getting the authorization header merged in initializer.rb
129
- headers_debug = @headers.dup
130
- if headers_debug['Authorization']
131
- headers_debug['Authorization'] = headers_debug['Authorization'].gsub(/(.{10})\z/, '***********')
132
- end
142
+ request_headers = @headers.merge(extra_headers)
133
143
 
134
144
  @logger.debug "base url: #{@base_uri}"
135
- @logger.debug "request method: #{method}, uri: #{uri}, body: #{body}, extra_headers: #{extra_headers}, headers: #{headers_debug}"
145
+ @logger.debug "request method: #{method}, uri: #{uri}, body: #{body}, " \
146
+ "headers: #{mask_authorization(request_headers)}"
136
147
  result = case method
137
- when :get
138
- get_headers = @headers.merge({ params: body }).merge(extra_headers)
139
- call(:get, encode_uri(uri), timeout, get_headers)
140
- when :delete
141
- delete_headers = @headers.merge({ params: body })
142
- call(:delete, encode_uri(uri), timeout, delete_headers)
148
+ when :get, :delete
149
+ call(method, encode_uri(uri), timeout, request_headers.merge({ params: body }))
143
150
  else
144
- call(method, encode_uri(uri), timeout, @headers, body.to_json)
151
+ call(method, encode_uri(uri), timeout, request_headers, body.to_json)
145
152
  end
146
153
 
147
154
  raise Descope::Unsupported.new('No response from server', code: 400) unless result.respond_to?(:code)