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
|
@@ -67,7 +67,9 @@ module Descope
|
|
|
67
67
|
def enchanted_link_get_session(pending_ref = nil)
|
|
68
68
|
# @see https://docs.descope.com/api/openapi/enchantedlink/operation/GetEnchantedLinkSession/
|
|
69
69
|
res = post(GET_SESSION_ENCHANTEDLINK_AUTH_PATH, { pendingRef: pending_ref })
|
|
70
|
-
|
|
70
|
+
cookies = res.fetch(COOKIE_DATA_NAME, nil) || res.fetch('cookies', {})
|
|
71
|
+
refresh_cookie = cookies.fetch(REFRESH_SESSION_COOKIE_NAME, nil) || res.fetch('refreshJwt', nil)
|
|
72
|
+
generate_jwt_response(response_body: res, refresh_cookie:)
|
|
71
73
|
end
|
|
72
74
|
|
|
73
75
|
private
|
|
@@ -42,7 +42,9 @@ module Descope
|
|
|
42
42
|
def magiclink_verify_token(token = nil)
|
|
43
43
|
validate_token_not_empty(token)
|
|
44
44
|
res = post(VERIFY_MAGICLINK_AUTH_PATH, { token: })
|
|
45
|
-
|
|
45
|
+
cookies = res.fetch(COOKIE_DATA_NAME, nil) || res.fetch('cookies', {})
|
|
46
|
+
refresh_cookie = cookies.fetch(REFRESH_SESSION_COOKIE_NAME, nil) || res.fetch('refreshJwt', nil)
|
|
47
|
+
generate_jwt_response(response_body: res, refresh_cookie:)
|
|
46
48
|
end
|
|
47
49
|
|
|
48
50
|
def magiclink_update_user_email(login_id: nil, email: nil, uri: nil, add_to_login_ids: nil, on_merge_use_existing: nil, provider_id: nil, template_id: nil, template_options: nil, refresh_token: nil)
|
|
@@ -10,10 +10,11 @@ module Descope
|
|
|
10
10
|
include Descope::Mixins::Common::EndpointsV1
|
|
11
11
|
include Descope::Mixins::Common::EndpointsV2
|
|
12
12
|
|
|
13
|
-
def otp_sign_in(method: nil, login_id: nil, login_options: nil, refresh_token: nil,
|
|
13
|
+
def otp_sign_in(method: nil, login_id: nil, login_options: nil, refresh_token: nil, provider_id: nil,
|
|
14
14
|
template_id: nil, sso_app_id: nil)
|
|
15
|
-
# Sign in (log in) an existing user with the unique login_id you provide.
|
|
16
|
-
# login_id field
|
|
15
|
+
# Sign in (log in) an existing user with the unique login_id you provide.
|
|
16
|
+
# The login_id field is used to identify the user. It can be an email address or a phone number.
|
|
17
|
+
# Provide the DeliveryMethod required for this user. If the login_id value cannot be used for the
|
|
17
18
|
# DeliverMethod selected (for example, 'login_id = 4567qq445km' and 'DeliveryMethod = email')
|
|
18
19
|
validate_login_id(login_id)
|
|
19
20
|
uri = otp_compose_signin_url(method)
|
|
@@ -23,12 +24,15 @@ module Descope
|
|
|
23
24
|
end
|
|
24
25
|
|
|
25
26
|
def otp_sign_up(method: nil, login_id: nil, user: {}, provider_id: nil, template_id: nil)
|
|
26
|
-
# Sign up (create) a new user using their email or phone number.
|
|
27
|
-
#
|
|
27
|
+
# Sign up (create) a new user using their email or phone number.
|
|
28
|
+
# The login_id field is used to identify the user. It can be an email address or a phone number.
|
|
29
|
+
# Choose a delivery method for OTP verification, for example email, SMS, or Voice.
|
|
28
30
|
# (optional) Include additional user metadata that you wish to preserve.
|
|
29
|
-
|
|
31
|
+
validate_login_id(login_id)
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
unless adjust_and_verify_delivery_method(method, login_id, user)
|
|
34
|
+
raise Descope::AuthException.new('Could not verify delivery method', code: 400)
|
|
35
|
+
end
|
|
32
36
|
|
|
33
37
|
uri = otp_compose_signup_url(method)
|
|
34
38
|
body = otp_compose_signup_body(method, login_id, user, provider_id, template_id)
|
|
@@ -38,9 +42,11 @@ module Descope
|
|
|
38
42
|
|
|
39
43
|
def otp_sign_up_or_in(method: nil, login_id: nil, login_options: nil, provider_id: nil, template_id: nil,
|
|
40
44
|
sso_app_id: nil)
|
|
41
|
-
# Sign_up_or_in lets you handle both sign up and sign in with a single call.
|
|
42
|
-
#
|
|
43
|
-
#
|
|
45
|
+
# Sign_up_or_in lets you handle both sign up and sign in with a single call.
|
|
46
|
+
# The login_id field is used to identify the user. It can be an email address or a phone number.
|
|
47
|
+
# Sign-up_or_in will first determine if login_id is a new or existing end user.
|
|
48
|
+
# If login_id is new, a new end user user will be created and then authenticated using the
|
|
49
|
+
# OTP DeliveryMethod specified.
|
|
44
50
|
# If login_id exists, the end user will be authenticated using the OTP DeliveryMethod specified.
|
|
45
51
|
validate_login_id(login_id)
|
|
46
52
|
uri = otp_compose_sign_up_or_in_url(method)
|
|
@@ -57,7 +63,9 @@ module Descope
|
|
|
57
63
|
code:
|
|
58
64
|
}
|
|
59
65
|
res = post(uri, request_params)
|
|
60
|
-
|
|
66
|
+
cookies = res.fetch(COOKIE_DATA_NAME, nil) || res.fetch('cookies', {})
|
|
67
|
+
refresh_cookie = cookies.fetch(REFRESH_SESSION_COOKIE_NAME, nil) || res.fetch('refreshJwt', nil)
|
|
68
|
+
generate_jwt_response(response_body: res, refresh_cookie:)
|
|
61
69
|
end
|
|
62
70
|
|
|
63
71
|
def otp_update_user_email(login_id: nil, email: nil, refresh_token: nil, add_to_login_ids: false,
|
|
@@ -81,9 +89,10 @@ module Descope
|
|
|
81
89
|
method: nil, login_id: nil, phone: nil, refresh_token: nil, add_to_login_ids: false,
|
|
82
90
|
on_merge_use_existing: false, provider_id: nil, template_id: nil
|
|
83
91
|
)
|
|
84
|
-
# Update the phone number of an existing end user, after verifying the authenticity of the end user using OTP
|
|
92
|
+
# Update the phone number of an existing end user, after verifying the authenticity of the end user using OTP
|
|
85
93
|
validate_login_id(login_id)
|
|
86
94
|
validate_phone(method, phone)
|
|
95
|
+
|
|
87
96
|
uri = otp_compose_update_phone_url(method)
|
|
88
97
|
request_params = {
|
|
89
98
|
loginId: login_id,
|
|
@@ -127,7 +136,7 @@ module Descope
|
|
|
127
136
|
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
128
137
|
def otp_compose_signup_body(method, login_id, user, provider_id, template_id)
|
|
129
138
|
body = {
|
|
130
|
-
loginId: login_id
|
|
139
|
+
loginId: login_id
|
|
131
140
|
}
|
|
132
141
|
|
|
133
142
|
unless user.nil?
|
|
@@ -167,7 +176,8 @@ module Descope
|
|
|
167
176
|
end
|
|
168
177
|
|
|
169
178
|
private
|
|
170
|
-
def otp_user_compose_update_body(login_id: nil, name: nil, phone: nil, email: nil, given_name: nil,
|
|
179
|
+
def otp_user_compose_update_body(login_id: nil, name: nil, phone: nil, email: nil, given_name: nil,
|
|
180
|
+
middle_name: nil, family_name: nil)
|
|
171
181
|
user = {}
|
|
172
182
|
user[:loginId] = login_id if login_id
|
|
173
183
|
user[:name] = name if name
|
|
@@ -176,7 +186,6 @@ module Descope
|
|
|
176
186
|
user[:givenName] = given_name if given_name
|
|
177
187
|
user[:middleName] = middle_name if middle_name
|
|
178
188
|
user[:familyName] = family_name if family_name
|
|
179
|
-
|
|
180
189
|
user
|
|
181
190
|
end
|
|
182
191
|
end
|
|
@@ -22,7 +22,9 @@ module Descope
|
|
|
22
22
|
|
|
23
23
|
request_params[:user] = password_user_compose_update_body(**user) unless user.nil?
|
|
24
24
|
res = post(SIGN_UP_PASSWORD_PATH, request_params)
|
|
25
|
-
|
|
25
|
+
cookies = res.fetch(COOKIE_DATA_NAME, nil) || res.fetch('cookies', {})
|
|
26
|
+
refresh_cookie = cookies.fetch(REFRESH_SESSION_COOKIE_NAME, nil) || res.fetch('refreshJwt', nil)
|
|
27
|
+
generate_jwt_response(response_body: res, refresh_cookie:)
|
|
26
28
|
end
|
|
27
29
|
|
|
28
30
|
def password_sign_in(login_id: nil, password: nil, sso_app_id: nil)
|
|
@@ -38,7 +40,9 @@ module Descope
|
|
|
38
40
|
ssoAppId: sso_app_id
|
|
39
41
|
}
|
|
40
42
|
res = post(SIGN_IN_PASSWORD_PATH, request_params)
|
|
41
|
-
|
|
43
|
+
cookies = res.fetch(COOKIE_DATA_NAME, nil) || res.fetch('cookies', {})
|
|
44
|
+
refresh_cookie = cookies.fetch(REFRESH_SESSION_COOKIE_NAME, nil) || res.fetch('refreshJwt', nil)
|
|
45
|
+
generate_jwt_response(response_body: res, refresh_cookie:)
|
|
42
46
|
end
|
|
43
47
|
|
|
44
48
|
def password_replace(login_id: nil, old_password: nil, new_password: nil)
|
|
@@ -17,7 +17,9 @@ module Descope
|
|
|
17
17
|
uri = VERIFY_TOTP_PATH
|
|
18
18
|
body = totp_compose_signin_body(login_id, code, login_options)
|
|
19
19
|
res = post(uri, body, {}, nil)
|
|
20
|
-
|
|
20
|
+
cookies = res.fetch(COOKIE_DATA_NAME, nil) || res.fetch('cookies', {})
|
|
21
|
+
refresh_cookie = cookies.fetch(REFRESH_SESSION_COOKIE_NAME, nil) || res.fetch('refreshJwt', nil)
|
|
22
|
+
generate_jwt_response(response_body: res, refresh_cookie:)
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
def totp_sign_up(login_id: nil, user: nil, sso_app_id: nil)
|
data/lib/descope/api/v1/auth.rb
CHANGED
|
@@ -34,7 +34,6 @@ module Descope
|
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
jwt_response = generate_auth_info(response_body, refresh_cookie, true, audience)
|
|
37
|
-
@logger.debug "jwt_response: #{jwt_response}"
|
|
38
37
|
jwt_response['user'] = response_body.key?('user') ? response_body['user'] : {}
|
|
39
38
|
jwt_response['firstSeen'] = response_body.key?('firstSeen') ? response_body['firstSeen'] : true
|
|
40
39
|
|
|
@@ -51,10 +50,10 @@ module Descope
|
|
|
51
50
|
# Return value (Hash): returns the session token from the server together with the expiry and key id
|
|
52
51
|
# (sessionToken:Hash, keyId:str, expiration:int)
|
|
53
52
|
unless (access_key.is_a?(String) || access_key.nil?) && !access_key.to_s.empty?
|
|
54
|
-
raise
|
|
53
|
+
raise AuthException.new('Access key should be a string!', code: 400)
|
|
55
54
|
end
|
|
56
55
|
|
|
57
|
-
res = post(EXCHANGE_AUTH_ACCESS_KEY_PATH, { loginOptions: login_options, audience: }, {}, access_key)
|
|
56
|
+
res = post(EXCHANGE_AUTH_ACCESS_KEY_PATH, { loginOptions: login_options, audience: audience }, {}, access_key)
|
|
58
57
|
generate_auth_info(res, nil, false, audience)
|
|
59
58
|
end
|
|
60
59
|
|
|
@@ -62,6 +61,8 @@ module Descope
|
|
|
62
61
|
validate_refresh_token_not_nil(refresh_token)
|
|
63
62
|
res = post(SELECT_TENANT_PATH, { tenantId: tenant_id }, {}, refresh_token)
|
|
64
63
|
@logger.debug "select_tenant response: #{res}"
|
|
64
|
+
cookies = res.fetch('cookies')
|
|
65
|
+
generate_jwt_response(response_body: res, refresh_cookie: cookies.fetch(REFRESH_SESSION_COOKIE_NAME, nil))
|
|
65
66
|
generate_jwt_response(
|
|
66
67
|
response_body: res,
|
|
67
68
|
refresh_cookie: res['refreshJwt']
|
|
@@ -71,7 +72,7 @@ module Descope
|
|
|
71
72
|
def validate_permissions(jwt_response: nil, permissions: nil)
|
|
72
73
|
# Validate that a jwt_response has been granted the specified permissions.
|
|
73
74
|
# For a multi-tenant environment use validate_tenant_permissions function
|
|
74
|
-
validate_tenant_permissions(jwt_response
|
|
75
|
+
validate_tenant_permissions(jwt_response: jwt_response, permissions: permissions)
|
|
75
76
|
end
|
|
76
77
|
|
|
77
78
|
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize, Metrics/MethodLength
|
|
@@ -122,7 +123,7 @@ module Descope
|
|
|
122
123
|
def validate_roles(jwt_response: nil, roles: nil)
|
|
123
124
|
# Validate that a jwt_response has been granted the specified roles.
|
|
124
125
|
# For a multi-tenant environment use validate_tenant_roles function
|
|
125
|
-
validate_tenant_roles(jwt_response
|
|
126
|
+
validate_tenant_roles(jwt_response: jwt_response, tenant: '', roles: roles)
|
|
126
127
|
end
|
|
127
128
|
|
|
128
129
|
def validate_tenant_roles(jwt_response: nil, tenant: nil, roles: nil)
|
|
@@ -231,24 +232,58 @@ module Descope
|
|
|
231
232
|
private
|
|
232
233
|
|
|
233
234
|
def generate_auth_info(response_body, refresh_token, user_jwt, audience = nil)
|
|
234
|
-
@logger.debug "generating auth info: #{response_body}, #{refresh_token}, #{user_jwt}, #{audience}"
|
|
235
|
+
@logger.debug "generating auth info: response_body: #{response_body}, refresh_token: #{refresh_token}, user_jwt: #{user_jwt}, audience: #{audience}"
|
|
235
236
|
jwt_response = {}
|
|
236
237
|
|
|
237
238
|
# validate the session token if sessionJwt is not empty
|
|
238
239
|
st_jwt = response_body.fetch('sessionJwt', '')
|
|
239
240
|
unless st_jwt.empty?
|
|
240
|
-
@logger.debug
|
|
241
|
-
jwt_response[SESSION_TOKEN_NAME] = validate_token(st_jwt, audience)
|
|
241
|
+
@logger.debug 'found sessionJwt in response body, adding to jwt_response'
|
|
242
|
+
jwt_response[SESSION_TOKEN_NAME] = validate_token(st_jwt, audience)
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# Check for session token in cookies if not found in response body
|
|
246
|
+
cookies = response_body.fetch('cookies', {})
|
|
247
|
+
if jwt_response[SESSION_TOKEN_NAME].nil?
|
|
248
|
+
cookies.each do |cookie_name, cookie_value|
|
|
249
|
+
if cookie_name == SESSION_COOKIE_NAME
|
|
250
|
+
@logger.debug "found session token in cookies with name #{cookie_name}, adding to jwt_response"
|
|
251
|
+
jwt_response[SESSION_TOKEN_NAME] = validate_token(cookie_value, audience)
|
|
252
|
+
break
|
|
253
|
+
end
|
|
254
|
+
end
|
|
242
255
|
end
|
|
243
256
|
|
|
244
257
|
# validate refresh token if refresh_token was passed or if refreshJwt is not empty
|
|
245
258
|
rt_jwt = response_body.fetch('refreshJwt', '')
|
|
246
259
|
|
|
247
|
-
if !
|
|
248
|
-
@logger.debug
|
|
249
|
-
|
|
250
|
-
elsif !rt_jwt.empty?
|
|
260
|
+
if !rt_jwt.empty?
|
|
261
|
+
@logger.debug 'found refreshJwt in response body, adding to jwt_response'
|
|
262
|
+
@logger.debug 'validating refreshJwt token...'
|
|
251
263
|
jwt_response[REFRESH_SESSION_TOKEN_NAME] = validate_token(rt_jwt, audience)
|
|
264
|
+
else
|
|
265
|
+
# Check cookies for refresh token
|
|
266
|
+
refresh_cookie_found = false
|
|
267
|
+
cookies.each do |cookie_name, cookie_value|
|
|
268
|
+
if cookie_name == REFRESH_SESSION_COOKIE_NAME && !cookie_value.to_s.empty?
|
|
269
|
+
@logger.debug "found refresh token in cookies with name #{cookie_name}, adding to jwt_response"
|
|
270
|
+
jwt_response[REFRESH_SESSION_TOKEN_NAME] = validate_token(cookie_value, audience)
|
|
271
|
+
refresh_cookie_found = true
|
|
272
|
+
break
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
# If not found in cookies, check if refresh_token parameter was passed
|
|
277
|
+
if !refresh_cookie_found && refresh_token && !refresh_token.to_s.empty?
|
|
278
|
+
@logger.debug 'refresh token not found in cookies, but refresh_token was passed, adding to jwt_response'
|
|
279
|
+
@logger.debug 'validating passed-in refresh token...'
|
|
280
|
+
jwt_response[REFRESH_SESSION_TOKEN_NAME] = validate_token(refresh_token, audience)
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
if jwt_response[REFRESH_SESSION_TOKEN_NAME].nil?
|
|
285
|
+
@logger.debug "Error: Could not find refreshJwt in response body: #{response_body} / cookies: #{cookies} / passed in refresh_token ->#{refresh_token}<-"
|
|
286
|
+
raise Descope::AuthException.new('Could not find refreshJwt in response body / cookies / passed in refresh_token', code: 500)
|
|
252
287
|
end
|
|
253
288
|
|
|
254
289
|
jwt_response = adjust_properties(jwt_response, user_jwt)
|
|
@@ -407,6 +442,7 @@ module Descope
|
|
|
407
442
|
login_id = {
|
|
408
443
|
DeliveryMethod::WHATSAPP => ['whatsapp', user.fetch(:phone, '')],
|
|
409
444
|
DeliveryMethod::SMS => ['phone', user.fetch(:phone, '')],
|
|
445
|
+
DeliveryMethod::VOICE => ['phone', user.fetch(:phone, '')],
|
|
410
446
|
DeliveryMethod::EMAIL => ['email', user.fetch(:email, '')]
|
|
411
447
|
}[method]
|
|
412
448
|
|
|
@@ -416,34 +452,30 @@ module Descope
|
|
|
416
452
|
end
|
|
417
453
|
|
|
418
454
|
def adjust_and_verify_delivery_method(method, login_id, user)
|
|
419
|
-
|
|
455
|
+
@logger.debug("adjust_and_verify_delivery_method: method: #{method}, login_id: #{login_id}, user: #{user}")
|
|
456
|
+
raise AuthException.new("Could not verify delivery method for method: #{method}", code: 400) if method.nil?
|
|
457
|
+
raise AuthException.new('Could not verify delivery method without login_id', code: 400) if login_id.nil?
|
|
420
458
|
|
|
421
|
-
|
|
459
|
+
unless user.is_a?(Hash)
|
|
460
|
+
raise AuthException.new('Could not verify delivery method, user is not a Hash', code: 400)
|
|
461
|
+
end
|
|
422
462
|
|
|
423
463
|
case method
|
|
424
464
|
when DeliveryMethod::EMAIL
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
when DeliveryMethod::SMS
|
|
433
|
-
user[:phone] ||= login_id
|
|
434
|
-
return false unless /^#{PHONE_REGEX}$/.match(user[:phone])
|
|
435
|
-
when DeliveryMethod::WHATSAPP
|
|
436
|
-
user[:phone] ||= login_id
|
|
437
|
-
return false unless /^#{PHONE_REGEX}$/.match(user[:phone])
|
|
465
|
+
validate_email(login_id)
|
|
466
|
+
@logger.debug("email: #{login_id} is valid")
|
|
467
|
+
true
|
|
468
|
+
when DeliveryMethod::SMS, DeliveryMethod::WHATSAPP, DeliveryMethod::VOICE
|
|
469
|
+
validate_phone(method, login_id)
|
|
470
|
+
@logger.debug("phone number (login_id): #{login_id} is valid")
|
|
471
|
+
true
|
|
438
472
|
else
|
|
439
|
-
|
|
473
|
+
false
|
|
440
474
|
end
|
|
441
|
-
|
|
442
|
-
true
|
|
443
475
|
end
|
|
444
476
|
|
|
445
477
|
def extract_masked_address(response, method)
|
|
446
|
-
if [DeliveryMethod::SMS, DeliveryMethod::WHATSAPP].include?(method)
|
|
478
|
+
if [DeliveryMethod::SMS, DeliveryMethod::WHATSAPP, DeliveryMethod::VOICE].include?(method)
|
|
447
479
|
response['maskedPhone']
|
|
448
480
|
elsif method == DeliveryMethod::EMAIL
|
|
449
481
|
response['maskedEmail']
|
|
@@ -455,7 +487,7 @@ module Descope
|
|
|
455
487
|
def exchange_token(uri, code)
|
|
456
488
|
raise Descope::ArgumentException.new("Code can't be empty", code: 400) if code.nil? || code.empty?
|
|
457
489
|
|
|
458
|
-
res = post(uri, { code: })
|
|
490
|
+
res = post(uri, { code: code })
|
|
459
491
|
generate_jwt_response(
|
|
460
492
|
response_body: res,
|
|
461
493
|
refresh_cookie: res['refreshJwt']
|
|
@@ -58,6 +58,30 @@ module Descope
|
|
|
58
58
|
{ 'audits' => res['audits'].map { |audit| convert_audit_record(audit) } }
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
+
def audit_create_event(action: nil, type: nil, data: nil, user_id: nil, actor_id: nil, tenant_id: nil)
|
|
62
|
+
# Create an audit event
|
|
63
|
+
unless %w[info warn error].include?(type)
|
|
64
|
+
raise Descope::AuthException, 'type must be either info, warn or error'
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# validation
|
|
68
|
+
raise Descope::AuthException, 'data must be provided as a key, value Hash' unless data.is_a?(Hash)
|
|
69
|
+
raise Descope::AuthException, 'action must be provided' if action.nil?
|
|
70
|
+
raise Descope::AuthException, 'actor_id must be provided' if actor_id.nil?
|
|
71
|
+
raise Descope::AuthException, 'tenant_id must be provided' if tenant_id.nil?
|
|
72
|
+
|
|
73
|
+
request_params = {
|
|
74
|
+
action:,
|
|
75
|
+
tenantId: tenant_id,
|
|
76
|
+
type:,
|
|
77
|
+
actorId: actor_id,
|
|
78
|
+
data:
|
|
79
|
+
}
|
|
80
|
+
request_params[:userId] = user_id unless user_id.nil?
|
|
81
|
+
|
|
82
|
+
post(AUDIT_CREATE_EVENT, request_params)
|
|
83
|
+
end
|
|
84
|
+
|
|
61
85
|
private
|
|
62
86
|
|
|
63
87
|
def convert_audit_record(audit)
|
|
@@ -17,6 +17,7 @@ module Descope
|
|
|
17
17
|
|
|
18
18
|
# user
|
|
19
19
|
USER_CREATE_PATH = '/v1/mgmt/user/create'
|
|
20
|
+
TEST_USER_CREATE_PATH = '/v1/mgmt/user/create/test'
|
|
20
21
|
USER_CREATE_BATCH_PATH = '/v1/mgmt/user/create/batch'
|
|
21
22
|
USER_UPDATE_PATH = '/v1/mgmt/user/update'
|
|
22
23
|
USER_DELETE_PATH = '/v1/mgmt/user/delete'
|
|
@@ -37,6 +38,8 @@ module Descope
|
|
|
37
38
|
USER_SET_TEMPORARY_PASSWORD_PATH = '/v1/mgmt/user/password/set/temporary'
|
|
38
39
|
USER_SET_ACTIVE_PASSWORD_PATH = '/v1/mgmt/user/password/set/active'
|
|
39
40
|
USER_SET_PASSWORD_PATH = '/v1/mgmt/user/password/set'
|
|
41
|
+
USER_SEARCH_PATH = "/v2/mgmt/user/search"
|
|
42
|
+
TEST_USERS_SEARCH_PATH = "/v2/mgmt/user/search/test"
|
|
40
43
|
USER_EXPIRE_PASSWORD_PATH = '/v1/mgmt/user/password/expire'
|
|
41
44
|
USER_ADD_TENANT_PATH = '/v1/mgmt/user/update/tenant/add'
|
|
42
45
|
USER_REMOVE_TENANT_PATH = '/v1/mgmt/user/update/tenant/remove'
|
|
@@ -44,6 +47,7 @@ module Descope
|
|
|
44
47
|
USER_GENERATE_MAGIC_LINK_FOR_TEST_PATH = '/v1/mgmt/tests/generate/magiclink'
|
|
45
48
|
USER_GENERATE_ENCHANTED_LINK_FOR_TEST_PATH = '/v1/mgmt/tests/generate/enchantedlink'
|
|
46
49
|
USER_GENERATE_EMBEDDED_LINK_PATH = '/v1/mgmt/user/signin/embeddedlink'
|
|
50
|
+
USER_PATCH_PATH = '/v1/mgmt/user/patch'
|
|
47
51
|
|
|
48
52
|
# access key
|
|
49
53
|
ACCESS_KEY_CREATE_PATH = '/v1/mgmt/accesskey/create'
|
|
@@ -54,13 +58,24 @@ module Descope
|
|
|
54
58
|
ACCESS_KEY_ACTIVATE_PATH = '/v1/mgmt/accesskey/activate'
|
|
55
59
|
ACCESS_KEY_DELETE_PATH = '/v1/mgmt/accesskey/delete'
|
|
56
60
|
|
|
57
|
-
# sso
|
|
61
|
+
# sso application
|
|
62
|
+
SSO_APPLICATION_OIDC_CREATE_PATH = '/v1/mgmt/sso/idp/app/oidc/create'
|
|
63
|
+
SSO_APPLICATION_SAML_CREATE_PATH = '/v1/mgmt/sso/idp/app/saml/create'
|
|
64
|
+
SSO_APPLICATION_OIDC_UPDATE_PATH = '/v1/mgmt/sso/idp/app/oidc/update'
|
|
65
|
+
SSO_APPLICATION_SAML_UPDATE_PATH = '/v1/mgmt/sso/idp/app/saml/update'
|
|
66
|
+
SSO_APPLICATION_DELETE_PATH = '/v1/mgmt/sso/idp/app/delete'
|
|
67
|
+
SSO_APPLICATION_LOAD_PATH = '/v1/mgmt/sso/idp/app/load'
|
|
68
|
+
SSO_APPLICATION_LOAD_ALL_PATH = '/v1/mgmt/sso/idp/apps/load'
|
|
69
|
+
|
|
70
|
+
# sso settings
|
|
58
71
|
SSO_SETTINGS_PATH = '/v2/mgmt/sso/settings'
|
|
72
|
+
SSO_METADATA_PATH = '/v1/mgmt/sso/metadata'
|
|
73
|
+
SSO_MAPPING_PATH = '/v1/mgmt/sso/mapping'
|
|
74
|
+
SSO_LOAD_SETTINGS_PATH = '/v2/mgmt/sso/settings' # v2 only
|
|
59
75
|
SSO_OIDC_PATH = '/v1/mgmt/sso/oidc' # configure ssp settings via oidc
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
SSO_SAML_METADATA_PATH = '/v1/mgmt/sso/saml/metadata' # configure ssp settings via saml metadata
|
|
76
|
+
SSO_CONFIGURE_OIDC_SETTINGS_PATH = '/v1/mgmt/sso/oidc'
|
|
77
|
+
SSO_CONFIGURE_SAML_SETTINGS_PATH = '/v1/mgmt/sso/saml'
|
|
78
|
+
SSO_CONFIGURE_SAML_METADATA_PATH = '/v1/mgmt/sso/saml/metadata'
|
|
64
79
|
|
|
65
80
|
# SCIM
|
|
66
81
|
SCIM_GROUPS_PATH = '/scim/v2/Groups'
|
|
@@ -100,6 +115,7 @@ module Descope
|
|
|
100
115
|
|
|
101
116
|
# Audit
|
|
102
117
|
AUDIT_SEARCH = '/v1/mgmt/audit/search'
|
|
118
|
+
AUDIT_CREATE_EVENT = '/v1/mgmt/audit/event'
|
|
103
119
|
|
|
104
120
|
# Authz ReBAC
|
|
105
121
|
AUTHZ_SCHEMA_SAVE = '/v1/mgmt/authz/schema/save'
|