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
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Descope
|
|
4
|
+
module Api
|
|
5
|
+
module V1
|
|
6
|
+
module Management
|
|
7
|
+
# Management API calls
|
|
8
|
+
module SSOApplication
|
|
9
|
+
include Descope::Api::V1::Management::Common
|
|
10
|
+
|
|
11
|
+
def create_sso_oidc_app(id: nil, name: nil, description: nil, enabled: nil, logo: nil, login_page_url: nil)
|
|
12
|
+
# Create a new OIDC sso application with the given name. SSO application IDs are provisioned automatically,
|
|
13
|
+
# but can be provided explicitly if needed. Both the name and ID must be unique per project.
|
|
14
|
+
body = {}
|
|
15
|
+
body[:id] = id if id
|
|
16
|
+
body[:name] = name if name
|
|
17
|
+
body[:description] = description if description
|
|
18
|
+
body[:enabled] = enabled if enabled
|
|
19
|
+
body[:logo] = logo if logo
|
|
20
|
+
body[:loginPageUrl] = login_page_url if login_page_url
|
|
21
|
+
post(SSO_APPLICATION_OIDC_CREATE_PATH, body)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
25
|
+
def create_saml_application(
|
|
26
|
+
name: nil,
|
|
27
|
+
login_page_url: nil,
|
|
28
|
+
id: nil,
|
|
29
|
+
description: nil,
|
|
30
|
+
logo: nil,
|
|
31
|
+
enabled: nil,
|
|
32
|
+
use_metadata_info: nil,
|
|
33
|
+
metadata_url: nil,
|
|
34
|
+
entity_id: nil,
|
|
35
|
+
acs_url: nil,
|
|
36
|
+
certificate: nil,
|
|
37
|
+
attribute_mapping: nil,
|
|
38
|
+
groups_mapping: nil,
|
|
39
|
+
acs_allowed_callbacks: nil,
|
|
40
|
+
subject_name_id_type: nil,
|
|
41
|
+
subject_name_id_format: nil,
|
|
42
|
+
default_relay_state: nil,
|
|
43
|
+
force_authentication: nil,
|
|
44
|
+
logout_redirect_url: nil
|
|
45
|
+
)
|
|
46
|
+
# Create a new SAML sso application with the given name. SSO application IDs are provisioned automatically,
|
|
47
|
+
# but can be provided explicitly if needed. Both the name and ID must be unique per project.
|
|
48
|
+
|
|
49
|
+
if use_metadata_info
|
|
50
|
+
raise Descope::ArgumentException.new('metadata_url argument must be set', code: 400) unless metadata_url
|
|
51
|
+
else
|
|
52
|
+
unless entity_id && acs_url && certificate
|
|
53
|
+
raise Descope::ArgumentException.new('entity_id, acs_url, certificate arguments must be set', code: 400)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
attribute_mapping ||= []
|
|
58
|
+
groups_mapping ||= []
|
|
59
|
+
acs_allowed_callbacks ||= []
|
|
60
|
+
body = compose_create_update_saml_body(
|
|
61
|
+
name:,
|
|
62
|
+
login_page_url:,
|
|
63
|
+
id:,
|
|
64
|
+
description:,
|
|
65
|
+
enabled:,
|
|
66
|
+
logo:,
|
|
67
|
+
use_metadata_info:,
|
|
68
|
+
metadata_url:,
|
|
69
|
+
entity_id:,
|
|
70
|
+
acs_url:,
|
|
71
|
+
certificate:,
|
|
72
|
+
attribute_mapping:,
|
|
73
|
+
groups_mapping:,
|
|
74
|
+
acs_allowed_callbacks:,
|
|
75
|
+
subject_name_id_type:,
|
|
76
|
+
subject_name_id_format:,
|
|
77
|
+
default_relay_state:,
|
|
78
|
+
force_authentication:,
|
|
79
|
+
logout_redirect_url:
|
|
80
|
+
)
|
|
81
|
+
post(SSO_APPLICATION_SAML_CREATE_PATH, body)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def update_sso_oidc_app(id: nil, name: nil, description: nil, enabled: nil, logo: nil, login_page_url: nil, force_authentication: nil)
|
|
85
|
+
# Update an existing OIDC sso application with the given parameters. IMPORTANT: All parameters are used as overrides
|
|
86
|
+
# to the existing sso application. Empty fields will override populated fields. Use carefully.
|
|
87
|
+
body = compose_create_update_oidc_body(name, login_page_url, id, description, enabled, logo, force_authentication)
|
|
88
|
+
post(SSO_APPLICATION_OIDC_UPDATE_PATH, body)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def update_saml_application(
|
|
92
|
+
id: nil,
|
|
93
|
+
name: nil,
|
|
94
|
+
login_page_url: nil,
|
|
95
|
+
description: nil,
|
|
96
|
+
logo: nil,
|
|
97
|
+
enabled: nil,
|
|
98
|
+
use_metadata_info: nil,
|
|
99
|
+
metadata_url: nil,
|
|
100
|
+
entity_id: nil,
|
|
101
|
+
acs_url: nil,
|
|
102
|
+
certificate: nil,
|
|
103
|
+
attribute_mapping: nil,
|
|
104
|
+
groups_mapping: nil,
|
|
105
|
+
acs_allowed_callbacks: nil,
|
|
106
|
+
subject_name_id_type: nil,
|
|
107
|
+
subject_name_id_format: nil,
|
|
108
|
+
default_relay_state: nil,
|
|
109
|
+
force_authentication: nil,
|
|
110
|
+
logout_redirect_url: nil
|
|
111
|
+
)
|
|
112
|
+
# Update an existing SAML sso application with the given parameters. IMPORTANT: All parameters are used as overrides
|
|
113
|
+
# to the existing sso application. Empty fields will override populated fields. Use carefully.
|
|
114
|
+
|
|
115
|
+
if use_metadata_info
|
|
116
|
+
raise 'metadata_url argument must be set' unless metadata_url
|
|
117
|
+
else
|
|
118
|
+
raise 'entity_id, acs_url, certificate arguments must be set' unless entity_id && acs_url
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
attribute_mapping ||= []
|
|
122
|
+
groups_mapping ||= []
|
|
123
|
+
acs_allowed_callbacks ||= []
|
|
124
|
+
|
|
125
|
+
body = compose_create_update_saml_body(
|
|
126
|
+
name:,
|
|
127
|
+
login_page_url:,
|
|
128
|
+
id:,
|
|
129
|
+
description:,
|
|
130
|
+
enabled:,
|
|
131
|
+
logo:,
|
|
132
|
+
use_metadata_info:,
|
|
133
|
+
metadata_url:,
|
|
134
|
+
entity_id:,
|
|
135
|
+
acs_url:,
|
|
136
|
+
certificate:,
|
|
137
|
+
attribute_mapping:,
|
|
138
|
+
groups_mapping:,
|
|
139
|
+
acs_allowed_callbacks:,
|
|
140
|
+
subject_name_id_type:,
|
|
141
|
+
subject_name_id_format:,
|
|
142
|
+
default_relay_state:,
|
|
143
|
+
force_authentication:,
|
|
144
|
+
logout_redirect_url:
|
|
145
|
+
)
|
|
146
|
+
post(SSO_APPLICATION_SAML_UPDATE_PATH, body)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def delete_sso_app(id)
|
|
150
|
+
# Delete an existing sso application. IMPORTANT: This operation is irreversible. Use carefully.
|
|
151
|
+
delete(SSO_APPLICATION_DELETE_PATH, { id: })
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def load_sso_app(id)
|
|
155
|
+
# Load an existing sso application.
|
|
156
|
+
get(SSO_APPLICATION_LOAD_PATH, { id: })
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def load_all_sso_apps
|
|
160
|
+
# Load all sso applications.
|
|
161
|
+
#
|
|
162
|
+
# Return value:
|
|
163
|
+
# {
|
|
164
|
+
# "apps": [
|
|
165
|
+
# {"id":"app1","name":"<name>","description":"<description>","enabled":true,"logo":"","appType":"saml","samlSettings":{"loginPageUrl":"","idpCert":"<cert>","useMetadataInfo":true,"metadataUrl":"","entityId":"","acsUrl":"","certificate":"","attributeMapping":[{"name":"email","type":"","value":"attrVal1"}],"groupsMapping":[{"name":"grp1","type":"","filterType":"roles","value":"","roles":[{"id":"myRoleId","name":"myRole"}]}],"idpMetadataUrl":"","idpEntityId":"","idpSsoUrl":"","acsAllowedCallbacks":[],"subjectNameIdType":"","subjectNameIdFormat":"", "defaultRelayState":"", "forceAuthentication": false, "idpLogoutUrl": "", "logoutRedirectUrl": ""},"oidcSettings":{"loginPageUrl":"","issuer":"","discoveryUrl":"", "forceAuthentication":false}},
|
|
166
|
+
# {"id":"app2","name":"<name>","description":"<description>","enabled":true,"logo":"","appType":"saml","samlSettings":{"loginPageUrl":"","idpCert":"<cert>","useMetadataInfo":true,"metadataUrl":"","entityId":"","acsUrl":"","certificate":"","attributeMapping":[{"name":"email","type":"","value":"attrVal1"}],"groupsMapping":[{"name":"grp1","type":"","filterType":"roles","value":"","roles":[{"id":"myRoleId","name":"myRole"}]}],"idpMetadataUrl":"","idpEntityId":"","idpSsoUrl":"","acsAllowedCallbacks":[],"subjectNameIdType":"","subjectNameIdFormat":"", "defaultRelayState":"", "forceAuthentication": false, "idpLogoutUrl": "", "logoutRedirectUrl": ""},"oidcSettings":{"loginPageUrl":"","issuer":"","discoveryUrl":"", "forceAuthentication":false}}
|
|
167
|
+
# ]
|
|
168
|
+
# }
|
|
169
|
+
# Containing the loaded sso applications information.
|
|
170
|
+
get(SSO_APPLICATION_LOAD_ALL_PATH, {})
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
private
|
|
174
|
+
|
|
175
|
+
def compose_create_update_oidc_body(name, login_page_url, id, description, enabled, logo, force_authentication)
|
|
176
|
+
body = {}
|
|
177
|
+
body[:name] = name if name
|
|
178
|
+
body[:loginPageUrl] = login_page_url if login_page_url
|
|
179
|
+
body[:id] = id if id
|
|
180
|
+
body[:description] = description if description
|
|
181
|
+
body[:logo] = logo if logo
|
|
182
|
+
body[:enabled] = enabled if enabled
|
|
183
|
+
body[:force_authentication] = force_authentication if force_authentication
|
|
184
|
+
body
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# rubocop:disable Metrics/AbcSize
|
|
188
|
+
def compose_create_update_saml_body(
|
|
189
|
+
name: nil,
|
|
190
|
+
login_page_url: nil,
|
|
191
|
+
id: nil,
|
|
192
|
+
description: nil,
|
|
193
|
+
enabled: nil,
|
|
194
|
+
logo: nil,
|
|
195
|
+
use_metadata_info: nil,
|
|
196
|
+
metadata_url: nil,
|
|
197
|
+
entity_id: nil,
|
|
198
|
+
acs_url: nil,
|
|
199
|
+
certificate: nil,
|
|
200
|
+
attribute_mapping: nil,
|
|
201
|
+
groups_mapping: nil,
|
|
202
|
+
acs_allowed_callbacks: nil,
|
|
203
|
+
subject_name_id_type: nil,
|
|
204
|
+
subject_name_id_format: nil,
|
|
205
|
+
default_relay_state: nil,
|
|
206
|
+
force_authentication: nil,
|
|
207
|
+
logout_redirect_url: nil
|
|
208
|
+
)
|
|
209
|
+
body = {}
|
|
210
|
+
body[:name] = name if name
|
|
211
|
+
body[:loginPageUrl] = login_page_url if login_page_url
|
|
212
|
+
body[:id] = id if id
|
|
213
|
+
body[:description] = description if description
|
|
214
|
+
body[:enabled] = enabled if enabled
|
|
215
|
+
body[:logo] = logo if logo
|
|
216
|
+
body[:useMetadataInfo] = use_metadata_info if use_metadata_info
|
|
217
|
+
body[:metadataUrl] = metadata_url if metadata_url
|
|
218
|
+
body[:entityId] = entity_id if entity_id
|
|
219
|
+
body[:acsUrl] = acs_url if acs_url
|
|
220
|
+
body[:certificate] = certificate if certificate
|
|
221
|
+
body[:attributeMapping] = attribute_mapping if attribute_mapping
|
|
222
|
+
body[:groupsMapping] = groups_mapping if groups_mapping
|
|
223
|
+
body[:acsAllowedCallbacks] = acs_allowed_callbacks if acs_allowed_callbacks
|
|
224
|
+
body[:subjectNameIdType] = subject_name_id_type if subject_name_id_type
|
|
225
|
+
body[:subjectNameIdFormat] = subject_name_id_format if subject_name_id_format
|
|
226
|
+
body[:defaultRelayState] = default_relay_state if default_relay_state
|
|
227
|
+
body[:forceAuthentication] = force_authentication if force_authentication
|
|
228
|
+
body[:logoutRedirectUrl] = logout_redirect_url if logout_redirect_url
|
|
229
|
+
puts "body: #{body}"
|
|
230
|
+
body
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
end
|
|
@@ -18,28 +18,6 @@ module Descope
|
|
|
18
18
|
delete(SSO_SETTINGS_PATH, { tenantId: tenant_id })
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
def create_sso_oidc_app(id: nil, name: nil, description: nil, enabled: nil, logo: nil, login_page_url: nil)
|
|
22
|
-
body = {}
|
|
23
|
-
body[:id] = id if id
|
|
24
|
-
body[:name] = name if name
|
|
25
|
-
body[:description] = description if description
|
|
26
|
-
body[:enabled] = enabled if enabled
|
|
27
|
-
body[:logo] = logo if logo
|
|
28
|
-
body[:loginPageUrl] = login_page_url if login_page_url
|
|
29
|
-
post(SSO_OIDC_CREATE_APP_PATH, body)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def update_sso_oidc_app(id: nil, name: nil, description: nil, enabled: nil, logo: nil, login_page_url: nil)
|
|
33
|
-
body = {}
|
|
34
|
-
body[:id] = id if id
|
|
35
|
-
body[:name] = name if name
|
|
36
|
-
body[:description] = description if description
|
|
37
|
-
body[:enabled] = enabled if enabled
|
|
38
|
-
body[:logo] = logo if logo
|
|
39
|
-
body[:loginPageUrl] = login_page_url if login_page_url
|
|
40
|
-
put(SSO_OIDC_UPDATE_APP_PATH, body)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
21
|
def configure_sso_oidc(tenant_id: nil, settings: nil, redirect_url: nil, domain: nil)
|
|
44
22
|
raise Descope::ArgumentException.new('SSO settings must be a Hash', code: 400) unless settings.is_a?(Hash)
|
|
45
23
|
|
|
@@ -63,12 +41,12 @@ module Descope
|
|
|
63
41
|
redirectUrl: redirect_url,
|
|
64
42
|
domain:
|
|
65
43
|
}
|
|
66
|
-
post(
|
|
44
|
+
post(SSO_SETTINGS_PATH, request_params)
|
|
67
45
|
end
|
|
68
46
|
|
|
69
47
|
def configure_sso_saml_metadata(tenant_id: nil, settings: nil, redirect_url: nil, domain: nil)
|
|
70
48
|
# Configure tenant SSO SAML Metadata, using a valid management key.
|
|
71
|
-
post(
|
|
49
|
+
post(SSO_METADATA_PATH, compose_metadata_body(tenant_id, settings, redirect_url, domain))
|
|
72
50
|
end
|
|
73
51
|
|
|
74
52
|
private
|
|
@@ -185,7 +185,9 @@ module Descope
|
|
|
185
185
|
statuses: [],
|
|
186
186
|
emails: [],
|
|
187
187
|
phones: [],
|
|
188
|
-
sso_app_ids: []
|
|
188
|
+
sso_app_ids: [],
|
|
189
|
+
tenant_role_ids: {},
|
|
190
|
+
tenant_role_names: {}
|
|
189
191
|
)
|
|
190
192
|
body = {
|
|
191
193
|
loginId: login_id,
|
|
@@ -212,9 +214,18 @@ module Descope
|
|
|
212
214
|
body[:ssoAppIds] = sso_app_ids unless sso_app_ids.empty?
|
|
213
215
|
body[:tenantIds] = tenant_ids unless tenant_ids.empty?
|
|
214
216
|
body[:roleNames] = role_names unless role_names.empty?
|
|
217
|
+
body[:tenantRoleIds] = map_to_values_object(tenant_role_ids) unless tenant_role_ids.nil? || tenant_role_ids.empty?
|
|
218
|
+
body[:tenantRoleNames] = map_to_values_object(tenant_role_names) unless tenant_role_names.nil? || tenant_role_names.empty?
|
|
215
219
|
post(Common::USERS_SEARCH_PATH, body)
|
|
216
220
|
end
|
|
217
221
|
|
|
222
|
+
def map_to_values_object(input_map)
|
|
223
|
+
return {} unless input_map.is_a?(Hash)
|
|
224
|
+
input_map.each_with_object({}) do |(key, values), result|
|
|
225
|
+
result[key] = { values: Array(values) }
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
218
229
|
# Get an existing user's provider token, using a valid management key.
|
|
219
230
|
# @see https://docs.descope.com/api/openapi/usermanagement/operation/GetUserProviderToken/
|
|
220
231
|
def get_provider_token(login_id: nil, provider: nil)
|
|
@@ -324,6 +335,51 @@ module Descope
|
|
|
324
335
|
post(Common::USER_UPDATE_CUSTOM_ATTRIBUTE_PATH, body)
|
|
325
336
|
end
|
|
326
337
|
|
|
338
|
+
def patch_user(
|
|
339
|
+
login_id: nil,
|
|
340
|
+
email: nil,
|
|
341
|
+
phone: nil,
|
|
342
|
+
name: nil,
|
|
343
|
+
given_name: nil,
|
|
344
|
+
middle_name: nil,
|
|
345
|
+
family_name: nil,
|
|
346
|
+
role_names: [],
|
|
347
|
+
user_tenants: [],
|
|
348
|
+
picture: nil,
|
|
349
|
+
custom_attributes: nil,
|
|
350
|
+
verified_email: nil,
|
|
351
|
+
verified_phone: nil,
|
|
352
|
+
additional_identifiers: [],
|
|
353
|
+
password: nil,
|
|
354
|
+
hashed_password: {},
|
|
355
|
+
sso_app_ids: []
|
|
356
|
+
)
|
|
357
|
+
validate_login_id(login_id)
|
|
358
|
+
role_names ||= []
|
|
359
|
+
user_tenants ||= []
|
|
360
|
+
path = Common::USER_PATCH_PATH
|
|
361
|
+
request_params = user_compose_update_body(
|
|
362
|
+
login_id:,
|
|
363
|
+
email:,
|
|
364
|
+
phone:,
|
|
365
|
+
name:,
|
|
366
|
+
given_name:,
|
|
367
|
+
middle_name:,
|
|
368
|
+
family_name:,
|
|
369
|
+
role_names:,
|
|
370
|
+
user_tenants:,
|
|
371
|
+
picture:,
|
|
372
|
+
custom_attributes:,
|
|
373
|
+
verified_email:,
|
|
374
|
+
verified_phone:,
|
|
375
|
+
additional_identifiers:,
|
|
376
|
+
password:,
|
|
377
|
+
hashed_password:,
|
|
378
|
+
sso_app_ids:
|
|
379
|
+
)
|
|
380
|
+
patch(path, request_params)
|
|
381
|
+
end
|
|
382
|
+
|
|
327
383
|
def update_jwt(jwt: nil, custom_claims: nil)
|
|
328
384
|
body = {
|
|
329
385
|
jwt:,
|
|
@@ -460,6 +516,75 @@ module Descope
|
|
|
460
516
|
post(USER_GENERATE_EMBEDDED_LINK_PATH, request_params)
|
|
461
517
|
end
|
|
462
518
|
|
|
519
|
+
# Search for all test users.
|
|
520
|
+
#
|
|
521
|
+
# @param tenant_ids [Array<String>] Optional list of tenant IDs to filter by
|
|
522
|
+
# @param role_names [Array<String>] Optional list of role names to filter by
|
|
523
|
+
# @param limit [Integer] Optional limit of the number of users returned. Leave empty for default.
|
|
524
|
+
# @param page [Integer] Optional pagination control. Pages start at 0 and must be non-negative.
|
|
525
|
+
# @param custom_attributes [Hash] Optional search for an attribute with a given value
|
|
526
|
+
# @param statuses [Array<String>] Optional list of statuses to search for ("enabled", "disabled", "invited")
|
|
527
|
+
# @param emails [Array<String>] Optional list of emails to search for
|
|
528
|
+
# @param phones [Array<String>] Optional list of phones to search for
|
|
529
|
+
# @param sso_app_ids [Array<String>] Optional list of SSO application IDs to filter by
|
|
530
|
+
# @param text [String] Optional string, allows free text search among all user's attributes.
|
|
531
|
+
# @param login_ids [Array<String>] Optional list of login ids
|
|
532
|
+
# @param sort [Array<Hash>] Optional array, allows to sort by fields.
|
|
533
|
+
#
|
|
534
|
+
# @return [Hash] Return hash in the format {"users": []}
|
|
535
|
+
#
|
|
536
|
+
# The "users" key contains a list of all the found users and their information
|
|
537
|
+
#
|
|
538
|
+
# @raise [AuthException] Raised if the search operation fails
|
|
539
|
+
#
|
|
540
|
+
def search_all_test_users(
|
|
541
|
+
tenant_ids: [],
|
|
542
|
+
role_names: [],
|
|
543
|
+
limit: 0,
|
|
544
|
+
page: 0,
|
|
545
|
+
custom_attributes: {},
|
|
546
|
+
statuses: [],
|
|
547
|
+
emails: [],
|
|
548
|
+
phones: [],
|
|
549
|
+
sso_app_ids: [],
|
|
550
|
+
sort: [],
|
|
551
|
+
text: nil,
|
|
552
|
+
login_ids: [],
|
|
553
|
+
tenant_role_ids: {},
|
|
554
|
+
tenant_role_names: {}
|
|
555
|
+
)
|
|
556
|
+
tenant_ids ||= []
|
|
557
|
+
role_names ||= []
|
|
558
|
+
|
|
559
|
+
if limit < 0 || page < 0
|
|
560
|
+
raise Descope::ArgumentException.new(
|
|
561
|
+
'limit or page must be non-negative', code: 400
|
|
562
|
+
)
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
body = {
|
|
566
|
+
tenantIds: tenant_ids,
|
|
567
|
+
roleNames: role_names,
|
|
568
|
+
limit:,
|
|
569
|
+
page:,
|
|
570
|
+
testUsersOnly: true,
|
|
571
|
+
withTestUser: true
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
body[:statuses] = statuses unless statuses.nil? || statuses.empty?
|
|
575
|
+
body[:emails] = emails unless emails.nil? || emails.empty?
|
|
576
|
+
body[:phones] = phones unless phones.nil? || phones.empty?
|
|
577
|
+
body[:customAttributes] = custom_attributes unless custom_attributes.nil? || custom_attributes.empty?
|
|
578
|
+
body[:ssoAppIds] = sso_app_ids unless sso_app_ids.nil? || sso_app_ids.empty?
|
|
579
|
+
body[:loginIds] = login_ids unless login_ids.nil? || login_ids.empty?
|
|
580
|
+
body[:sort] = sort unless sort.nil? || sort.empty?
|
|
581
|
+
body[:text] = text unless text.nil? || text.empty?
|
|
582
|
+
body[:tenantRoleIds] = map_to_values_object(tenant_role_ids) unless tenant_role_ids.nil? || tenant_role_ids.empty?
|
|
583
|
+
body[:tenantRoleNames] = map_to_values_object(tenant_role_names) unless tenant_role_names.nil? || tenant_role_names.empty?
|
|
584
|
+
|
|
585
|
+
post(Common::TEST_USERS_SEARCH_PATH, body)
|
|
586
|
+
end
|
|
587
|
+
|
|
463
588
|
|
|
464
589
|
private
|
|
465
590
|
|
|
@@ -486,11 +611,15 @@ module Descope
|
|
|
486
611
|
middle_name: nil,
|
|
487
612
|
family_name: nil,
|
|
488
613
|
sso_app_ids: [],
|
|
489
|
-
skip_create: false
|
|
614
|
+
skip_create: false,
|
|
615
|
+
template_id: nil
|
|
490
616
|
)
|
|
491
617
|
role_names ||= []
|
|
492
618
|
user_tenants ||= []
|
|
493
619
|
path = Common::USER_CREATE_PATH
|
|
620
|
+
|
|
621
|
+
path = Common::TEST_USER_CREATE_PATH if test
|
|
622
|
+
|
|
494
623
|
request_params = user_compose_create_body(
|
|
495
624
|
login_id:,
|
|
496
625
|
email:,
|
|
@@ -513,7 +642,8 @@ module Descope
|
|
|
513
642
|
additional_identifiers:,
|
|
514
643
|
password:,
|
|
515
644
|
hashed_password:,
|
|
516
|
-
sso_app_ids
|
|
645
|
+
sso_app_ids:,
|
|
646
|
+
template_id:,
|
|
517
647
|
)
|
|
518
648
|
return request_params if skip_create
|
|
519
649
|
|
|
@@ -542,7 +672,8 @@ module Descope
|
|
|
542
672
|
additional_identifiers: [],
|
|
543
673
|
password: nil,
|
|
544
674
|
hashed_password: {},
|
|
545
|
-
sso_app_ids: []
|
|
675
|
+
sso_app_ids: [],
|
|
676
|
+
template_id: nil
|
|
546
677
|
)
|
|
547
678
|
body = user_compose_update_body(
|
|
548
679
|
login_id:,
|
|
@@ -561,14 +692,15 @@ module Descope
|
|
|
561
692
|
additional_identifiers:,
|
|
562
693
|
password:,
|
|
563
694
|
hashed_password:,
|
|
564
|
-
sso_app_ids
|
|
695
|
+
sso_app_ids:,
|
|
696
|
+
template_id:,
|
|
565
697
|
)
|
|
566
698
|
body[:invite] = invite
|
|
567
|
-
body[:verifiedEmail] = verified_email unless verified_email.nil? ||
|
|
568
|
-
body[:verifiedPhone] = verified_phone unless verified_phone.nil? ||
|
|
569
|
-
body[:inviteUrl] = invite_url unless invite_url.nil? ||
|
|
570
|
-
body[:sendMail] = send_mail unless send_mail.nil? ||
|
|
571
|
-
body[:sendSMS] = send_sms unless send_sms.nil? ||
|
|
699
|
+
body[:verifiedEmail] = verified_email unless verified_email.nil? || verified_email.empty?
|
|
700
|
+
body[:verifiedPhone] = verified_phone unless verified_phone.nil? || verified_phone.empty?
|
|
701
|
+
body[:inviteUrl] = invite_url unless invite_url.nil? || invite_url.empty?
|
|
702
|
+
body[:sendMail] = send_mail unless send_mail.nil? || send_mail.empty?
|
|
703
|
+
body[:sendSMS] = send_sms unless send_sms.nil? || send_sms.empty?
|
|
572
704
|
|
|
573
705
|
body
|
|
574
706
|
end
|
|
@@ -592,7 +724,8 @@ module Descope
|
|
|
592
724
|
additional_identifiers: [],
|
|
593
725
|
password: nil,
|
|
594
726
|
hashed_password: {},
|
|
595
|
-
sso_app_ids: []
|
|
727
|
+
sso_app_ids: [],
|
|
728
|
+
template_id: nil
|
|
596
729
|
)
|
|
597
730
|
body = {
|
|
598
731
|
loginId: login_id,
|
|
@@ -615,18 +748,23 @@ module Descope
|
|
|
615
748
|
body[:phone] = phone unless phone.nil? || phone.empty?
|
|
616
749
|
body[:name] = name unless name.nil? || name.empty?
|
|
617
750
|
body[:roleNames] = role_names unless role_names.nil? || role_names.empty?
|
|
618
|
-
|
|
751
|
+
unless user_tenants.nil? || user_tenants.empty?
|
|
752
|
+
body[:userTenants] = associated_tenants_to_hash_array(user_tenants)
|
|
753
|
+
end
|
|
619
754
|
body[:test] = test unless test.nil?
|
|
620
755
|
body[:invite] = invite unless invite.nil?
|
|
621
756
|
body[:picture] = picture unless picture.nil? || picture.empty?
|
|
622
757
|
body[:customAttributes] = custom_attributes unless custom_attributes.nil? || custom_attributes.empty?
|
|
623
|
-
|
|
758
|
+
unless additional_identifiers.nil? || additional_identifiers.empty?
|
|
759
|
+
body[:additionalIdentifiers] = additional_identifiers
|
|
760
|
+
end
|
|
624
761
|
body[:ssoAppIds] = sso_app_ids unless sso_app_ids.nil? || sso_app_ids.empty?
|
|
625
762
|
body[:verifiedEmail] = verified_email unless verified_email.nil? || !verified_email.to_s.empty?
|
|
626
763
|
body[:givenName] = given_name unless given_name.nil?
|
|
627
764
|
body[:middleName] = middle_name unless middle_name.nil?
|
|
628
765
|
body[:familyName] = family_name unless family_name.nil?
|
|
629
766
|
body[:verifiedPhone] = verified_phone unless verified_phone.nil?
|
|
767
|
+
body[:templateId] = template_id unless template_id.nil? || template_id.empty?
|
|
630
768
|
body
|
|
631
769
|
end
|
|
632
770
|
end
|
|
@@ -10,6 +10,7 @@ require 'descope/api/v1/management/role'
|
|
|
10
10
|
require 'descope/api/v1/management/project'
|
|
11
11
|
require 'descope/api/v1/management/authz'
|
|
12
12
|
require 'descope/api/v1/management/audit'
|
|
13
|
+
require 'descope/api/v1/management/sso_application'
|
|
13
14
|
require 'descope/api/v1/management/sso_settings'
|
|
14
15
|
require 'descope/api/v1/management/scim'
|
|
15
16
|
require 'descope/api/v1/management/password'
|
|
@@ -29,6 +30,7 @@ module Descope
|
|
|
29
30
|
include Descope::Api::V1::Management::Project
|
|
30
31
|
include Descope::Api::V1::Management::Authz
|
|
31
32
|
include Descope::Api::V1::Management::Audit
|
|
33
|
+
include Descope::Api::V1::Management::SSOApplication
|
|
32
34
|
include Descope::Api::V1::Management::SSOSettings
|
|
33
35
|
include Descope::Api::V1::Management::SCIM
|
|
34
36
|
include Descope::Api::V1::Management::Password
|
|
@@ -20,11 +20,28 @@ module Descope
|
|
|
20
20
|
# [amr, drn, exp, iss, rexp, sub, jwt] in the top level of the response dict, please use
|
|
21
21
|
# them from the sessionToken key instead, as these claims will soon be deprecated from the top level
|
|
22
22
|
# of the response dict.
|
|
23
|
-
|
|
23
|
+
# Make sure you set Enable refresh token rotation in the Project Settings before using this.
|
|
24
24
|
validate_refresh_token_not_nil(refresh_token)
|
|
25
25
|
validate_token(refresh_token, audience)
|
|
26
26
|
res = post(REFRESH_TOKEN_PATH, {}, {}, refresh_token)
|
|
27
|
-
|
|
27
|
+
cookies = res.fetch(COOKIE_DATA_NAME, nil) || res.fetch('cookies', {})
|
|
28
|
+
|
|
29
|
+
# Check each source and use the first non-empty value
|
|
30
|
+
refresh_cookie = nil
|
|
31
|
+
cookie_value = cookies.fetch(REFRESH_SESSION_COOKIE_NAME, nil)
|
|
32
|
+
if cookie_value && !cookie_value.empty?
|
|
33
|
+
refresh_cookie = cookie_value
|
|
34
|
+
else
|
|
35
|
+
jwt_value = res.fetch('refreshJwt', nil)
|
|
36
|
+
if jwt_value && !jwt_value.empty?
|
|
37
|
+
refresh_cookie = jwt_value
|
|
38
|
+
else
|
|
39
|
+
refresh_cookie = refresh_token
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
logger.debug("Refreshing refresh_cookie: #{refresh_cookie}")
|
|
44
|
+
generate_jwt_response(response_body: res, refresh_cookie: refresh_cookie, audience: audience)
|
|
28
45
|
end
|
|
29
46
|
|
|
30
47
|
def me(refresh_token = nil)
|
|
@@ -72,12 +89,28 @@ module Descope
|
|
|
72
89
|
|
|
73
90
|
begin
|
|
74
91
|
@logger.debug("Validating session token: #{session_token}")
|
|
75
|
-
validate_session(session_token
|
|
92
|
+
validate_session(session_token: session_token, audience: audience)
|
|
76
93
|
rescue Descope::AuthException
|
|
77
94
|
@logger.debug("Session is invalid, refreshing session with refresh token: #{refresh_token}")
|
|
78
|
-
refresh_session(refresh_token
|
|
95
|
+
refresh_session(refresh_token: refresh_token, audience: audience)
|
|
79
96
|
end
|
|
80
97
|
end
|
|
98
|
+
|
|
99
|
+
def history(refresh_token = nil)
|
|
100
|
+
# Retrieve user authentication history for the refresh token
|
|
101
|
+
# Return List in the format
|
|
102
|
+
# [
|
|
103
|
+
# {
|
|
104
|
+
# "userId": "User's ID",
|
|
105
|
+
# "loginTime": "User'sLogin time",
|
|
106
|
+
# "city": "User's city",
|
|
107
|
+
# "country": "User's country",
|
|
108
|
+
# "ip": User's IP
|
|
109
|
+
# }
|
|
110
|
+
# ]
|
|
111
|
+
validate_refresh_token_not_nil(refresh_token)
|
|
112
|
+
get(HISTORY_PATH, {}, {}, refresh_token)
|
|
113
|
+
end
|
|
81
114
|
end
|
|
82
115
|
end
|
|
83
116
|
end
|
|
@@ -9,7 +9,8 @@ module Descope
|
|
|
9
9
|
DEFAULT_BASE_URL = 'https://api.descope.com' # pragma: no cover
|
|
10
10
|
DEFAULT_TIMEOUT_SECONDS = 60
|
|
11
11
|
DEFAULT_JWT_VALIDATION_LEEWAY = 5
|
|
12
|
-
|
|
12
|
+
# Using E164 format,\A and \z are start and end of string respectively, to prevent multiline matching
|
|
13
|
+
PHONE_REGEX = /\A\+[1-9]\d{1,14}\z/
|
|
13
14
|
|
|
14
15
|
SESSION_COOKIE_NAME = 'DS'
|
|
15
16
|
REFRESH_SESSION_COOKIE_NAME = 'DSR'
|
|
@@ -24,13 +25,15 @@ module Descope
|
|
|
24
25
|
WHATSAPP = 1
|
|
25
26
|
SMS = 2
|
|
26
27
|
EMAIL = 3
|
|
28
|
+
VOICE = 4
|
|
27
29
|
end
|
|
28
30
|
|
|
29
31
|
def get_method_string(method)
|
|
30
32
|
name = {
|
|
31
33
|
DeliveryMethod::WHATSAPP => 'whatsapp',
|
|
32
34
|
DeliveryMethod::SMS => 'sms',
|
|
33
|
-
DeliveryMethod::EMAIL => 'email'
|
|
35
|
+
DeliveryMethod::EMAIL => 'email',
|
|
36
|
+
DeliveryMethod::VOICE => 'voice'
|
|
34
37
|
}[method]
|
|
35
38
|
|
|
36
39
|
raise ArgumentException, "Unknown delivery method: #{method}" if name.nil?
|
|
@@ -49,6 +52,7 @@ module Descope
|
|
|
49
52
|
LOGOUT_ALL_PATH = '/v1/auth/logoutall'
|
|
50
53
|
VALIDATE_SESSION_PATH = '/v1/auth/validate'
|
|
51
54
|
ME_PATH = '/v1/auth/me'
|
|
55
|
+
HISTORY_PATH = '/v1/auth/me/history'
|
|
52
56
|
|
|
53
57
|
# access key
|
|
54
58
|
EXCHANGE_AUTH_ACCESS_KEY_PATH = '/v1/auth/accesskey/exchange'
|