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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yaml +2 -2
- data/.github/workflows/publish-gem.yaml +39 -7
- data/.gitignore +2 -0
- data/.ruby-version +1 -1
- data/Gemfile +7 -7
- data/Gemfile.lock +70 -65
- data/README.md +175 -52
- data/descope.gemspec +25 -20
- data/examples/ruby/.ruby-version +1 -0
- data/examples/ruby/access_key_app.rb +4 -3
- data/examples/ruby/enchantedlink_app.rb +1 -0
- data/examples/ruby/magiclink_app.rb +1 -0
- data/examples/ruby/management/.ruby-version +1 -0
- data/examples/ruby/management/Gemfile +2 -2
- data/examples/ruby/management/access_key_app.rb +2 -0
- data/examples/ruby/management/audit_app.rb +32 -8
- data/examples/ruby/management/authz_app.rb +1 -0
- data/examples/ruby/management/flow_app.rb +1 -0
- data/examples/ruby/management/permission_app.rb +3 -2
- data/examples/ruby/management/role_app.rb +3 -2
- data/examples/ruby/management/tenant_app.rb +1 -0
- data/examples/ruby/management/user_app.rb +1 -0
- data/examples/ruby/oauth_app.rb +1 -0
- data/examples/ruby/otp_app.rb +38 -12
- data/examples/ruby/password_app.rb +8 -7
- data/examples/ruby/saml_app.rb +1 -0
- data/examples/ruby/version_check.rb +17 -0
- data/examples/ruby-on-rails-api/descope/Gemfile +9 -7
- data/examples/ruby-on-rails-api/descope/Gemfile.lock +121 -90
- data/examples/ruby-on-rails-api/descope/README.md +18 -18
- data/examples/ruby-on-rails-api/descope/app/assets/builds/application.css +20092 -23
- data/examples/ruby-on-rails-api/descope/app/assets/builds/application.js +0 -1
- data/examples/ruby-on-rails-api/descope/app/assets/builds/components/index.js +0 -14
- data/examples/ruby-on-rails-api/descope/package-lock.json +1073 -19302
- data/examples/ruby-on-rails-api/descope/package.json +8 -16
- data/examples/ruby-on-rails-api/descope/yarn.lock +557 -10641
- data/lib/descope/api/v1/auth/enchantedlink.rb +3 -1
- data/lib/descope/api/v1/auth/magiclink.rb +3 -1
- data/lib/descope/api/v1/auth/otp.rb +24 -15
- data/lib/descope/api/v1/auth/password.rb +6 -2
- data/lib/descope/api/v1/auth/totp.rb +3 -1
- data/lib/descope/api/v1/auth.rb +64 -32
- data/lib/descope/api/v1/management/audit.rb +24 -0
- data/lib/descope/api/v1/management/common.rb +21 -5
- data/lib/descope/api/v1/management/sso_application.rb +236 -0
- data/lib/descope/api/v1/management/sso_settings.rb +2 -24
- data/lib/descope/api/v1/management/user.rb +151 -13
- data/lib/descope/api/v1/management.rb +2 -0
- data/lib/descope/api/v1/session.rb +37 -4
- data/lib/descope/mixins/common.rb +6 -2
- data/lib/descope/mixins/http.rb +60 -9
- data/lib/descope/mixins/initializer.rb +2 -1
- data/lib/descope/mixins/logging.rb +12 -4
- data/lib/descope/mixins/validation.rb +21 -6
- data/lib/descope/version.rb +1 -1
- data/spec/descope/api/v1/auth_spec.rb +29 -0
- data/spec/descope/api/v1/auth_token_extraction_spec.rb +126 -0
- data/spec/descope/api/v1/session_refresh_spec.rb +98 -0
- data/spec/factories/user.rb +1 -1
- data/spec/integration/lib.descope/api/v1/auth/enchantedlink_spec.rb +1 -1
- data/spec/integration/lib.descope/api/v1/auth/magiclink_spec.rb +1 -1
- data/spec/integration/lib.descope/api/v1/auth/otp_spec.rb +73 -8
- data/spec/integration/lib.descope/api/v1/auth/session_spec.rb +49 -0
- data/spec/integration/lib.descope/api/v1/auth/totp_spec.rb +1 -1
- data/spec/integration/lib.descope/api/v1/management/access_key_spec.rb +3 -0
- data/spec/integration/lib.descope/api/v1/management/audit_spec.rb +38 -0
- data/spec/integration/lib.descope/api/v1/management/authz_spec.rb +2 -0
- data/spec/integration/lib.descope/api/v1/management/flow_spec.rb +3 -1
- data/spec/integration/lib.descope/api/v1/management/permissions_spec.rb +4 -2
- data/spec/integration/lib.descope/api/v1/management/project_spec.rb +2 -0
- data/spec/integration/lib.descope/api/v1/management/roles_spec.rb +3 -1
- data/spec/integration/lib.descope/api/v1/management/user_spec.rb +55 -6
- data/spec/lib.descope/api/v1/auth/enchantedlink_spec.rb +11 -2
- data/spec/lib.descope/api/v1/auth/otp_spec.rb +176 -18
- data/spec/lib.descope/api/v1/auth/password_spec.rb +10 -1
- data/spec/lib.descope/api/v1/auth_spec.rb +168 -6
- data/spec/lib.descope/api/v1/cookie_domain_fix_integration_spec.rb +245 -0
- data/spec/lib.descope/api/v1/management/audit_spec.rb +92 -0
- data/spec/lib.descope/api/v1/management/sso_application_spec.rb +217 -0
- data/spec/lib.descope/api/v1/management/sso_settings_spec.rb +2 -2
- data/spec/lib.descope/api/v1/management/user_spec.rb +134 -46
- data/spec/lib.descope/api/v1/session_spec.rb +119 -6
- data/spec/lib.descope/mixins/http_spec.rb +218 -0
- data/spec/support/client_config.rb +0 -1
- data/spec/support/utils.rb +6 -0
- metadata +34 -137
- data/examples/ruby-on-rails-api/descope/app/assets/builds/reportWebVitals.js +0 -211
- 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.
|
|
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/
|
|
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. [
|
|
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. [
|
|
70
|
-
11. [
|
|
71
|
-
12. [
|
|
72
|
-
13. [Manage
|
|
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 (
|
|
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
|
|
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
|
|
101
|
+
method: Descope::Mixins::Common::DeliveryMethod::EMAIL, login_id: 'someone@example.com', code: '123456'
|
|
99
102
|
)
|
|
100
|
-
session_token = jwt_response['
|
|
101
|
-
refresh_token = jwt_response['
|
|
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 (
|
|
109
|
-
The Magic Link will redirect the user to page where the
|
|
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
|
|
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['
|
|
127
|
-
refresh_token = jwt_response['
|
|
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
|
|
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
|
|
184
|
+
puts "Failed pending session, err: #{e}"
|
|
179
185
|
nil
|
|
180
186
|
end
|
|
181
187
|
|
|
182
188
|
if jwt_response
|
|
183
|
-
puts
|
|
189
|
+
puts "jwt_response: #{jwt_response}"
|
|
184
190
|
refresh_token = jwt_response[Descope::Mixins::Common::REFRESH_SESSION_TOKEN_NAME]['jwt']
|
|
185
191
|
|
|
186
|
-
puts
|
|
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
|
-
|
|
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['
|
|
228
|
-
refresh_token = jwt_response['
|
|
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/
|
|
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['
|
|
251
|
-
refresh_token = jwt_response['
|
|
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
|
|
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
|
|
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['
|
|
289
|
-
refresh_token = jwt_response['
|
|
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['
|
|
311
|
-
refresh_token = jwt_response['
|
|
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['
|
|
319
|
-
refresh_token = jwt_response['
|
|
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['
|
|
357
|
-
refresh_token = jwt_response['
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
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
|
-
###
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
7
|
-
s.
|
|
8
|
-
s.
|
|
9
|
-
s.
|
|
10
|
-
s.
|
|
11
|
-
|
|
12
|
-
s.
|
|
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.
|
|
20
|
-
|
|
21
|
-
|
|
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
|
|
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
|
|
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
|
|
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}")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.3.0
|