descope 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yaml +4 -4
- data/.github/workflows/publish-gem.yaml +2 -2
- data/.github/workflows/release-please.yaml +1 -1
- data/.release-please-manifest.json +1 -1
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +1 -1
- data/.ruby-version +1 -1
- data/CHANGELOG.md +10 -0
- data/Gemfile +5 -5
- data/Gemfile.lock +32 -32
- data/README.md +233 -1
- data/lib/descope/api/v1/auth/enchantedlink.rb +76 -9
- data/lib/descope/api/v1/management/access_key.rb +8 -7
- data/lib/descope/api/v1/management/analytics.rb +62 -0
- data/lib/descope/api/v1/management/audit.rb +2 -2
- data/lib/descope/api/v1/management/authz.rb +15 -15
- data/lib/descope/api/v1/management/common.rb +76 -0
- data/lib/descope/api/v1/management/descoper.rb +45 -0
- data/lib/descope/api/v1/management/engine.rb +44 -0
- data/lib/descope/api/v1/management/fga.rb +64 -0
- data/lib/descope/api/v1/management/flow.rb +5 -5
- data/lib/descope/api/v1/management/group.rb +42 -0
- data/lib/descope/api/v1/management/jwt_template.rb +49 -0
- data/lib/descope/api/v1/management/lists.rb +96 -0
- data/lib/descope/api/v1/management/management_key.rb +54 -0
- data/lib/descope/api/v1/management/outbound_app.rb +112 -0
- data/lib/descope/api/v1/management/password.rb +2 -2
- data/lib/descope/api/v1/management/permission.rb +4 -4
- data/lib/descope/api/v1/management/project.rb +5 -5
- data/lib/descope/api/v1/management/role.rb +5 -5
- data/lib/descope/api/v1/management/scim.rb +14 -14
- data/lib/descope/api/v1/management/scope_claim_mapping.rb +34 -0
- data/lib/descope/api/v1/management/sso_application.rb +7 -7
- data/lib/descope/api/v1/management/sso_settings.rb +5 -5
- data/lib/descope/api/v1/management/tenant.rb +8 -6
- data/lib/descope/api/v1/management/third_party_application.rb +190 -0
- data/lib/descope/api/v1/management/user.rb +36 -36
- data/lib/descope/api/v1/management.rb +22 -0
- data/lib/descope/http_client.rb +30 -0
- data/lib/descope/mixins/common.rb +1 -0
- data/lib/descope/mixins/http.rb +23 -16
- data/lib/descope/mixins/initializer.rb +19 -9
- data/lib/descope/mixins/requests.rb +24 -0
- data/lib/descope/mixins.rb +2 -1
- data/lib/descope/version.rb +1 -1
- data/spec/integration/lib.descope/api/v1/management/user_spec.rb +1 -1
- data/spec/lib.descope/api/v1/auth/enchantedlink_spec.rb +163 -1
- data/spec/lib.descope/api/v1/management/access_key_spec.rb +7 -7
- data/spec/lib.descope/api/v1/management/analytics_spec.rb +82 -0
- data/spec/lib.descope/api/v1/management/audit_spec.rb +2 -2
- data/spec/lib.descope/api/v1/management/authz_spec.rb +16 -16
- data/spec/lib.descope/api/v1/management/descoper_spec.rb +101 -0
- data/spec/lib.descope/api/v1/management/engine_spec.rb +115 -0
- data/spec/lib.descope/api/v1/management/fga_spec.rb +169 -0
- data/spec/lib.descope/api/v1/management/flow_spec.rb +5 -5
- data/spec/lib.descope/api/v1/management/group_spec.rb +72 -0
- data/spec/lib.descope/api/v1/management/jwt_template_spec.rb +103 -0
- data/spec/lib.descope/api/v1/management/lists_spec.rb +285 -0
- data/spec/lib.descope/api/v1/management/management_key_spec.rb +109 -0
- data/spec/lib.descope/api/v1/management/outbound_app_spec.rb +236 -0
- data/spec/lib.descope/api/v1/management/password_spec.rb +2 -2
- data/spec/lib.descope/api/v1/management/permission_spec.rb +4 -4
- data/spec/lib.descope/api/v1/management/project_spec.rb +4 -4
- data/spec/lib.descope/api/v1/management/role_spec.rb +5 -5
- data/spec/lib.descope/api/v1/management/scim_spec.rb +14 -14
- data/spec/lib.descope/api/v1/management/scope_claim_mapping_spec.rb +59 -0
- data/spec/lib.descope/api/v1/management/sso_application_spec.rb +6 -6
- data/spec/lib.descope/api/v1/management/sso_settings_spec.rb +5 -5
- data/spec/lib.descope/api/v1/management/tenant_spec.rb +6 -6
- data/spec/lib.descope/api/v1/management/third_party_application_spec.rb +171 -0
- data/spec/lib.descope/api/v1/management/user_spec.rb +36 -36
- data/spec/lib.descope/auth_management_key_spec.rb +151 -0
- data/spec/support/client_config.rb +1 -0
- data/spec/support/dummy_class.rb +12 -9
- metadata +28 -3
|
@@ -15,7 +15,7 @@ describe Descope::Api::V1::Management::Tenant do
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
it 'is expected to create a new tenant' do
|
|
18
|
-
expect(@instance).to receive(:
|
|
18
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
19
19
|
TENANT_CREATE_PATH, {
|
|
20
20
|
name: 'test',
|
|
21
21
|
id: 'test',
|
|
@@ -46,7 +46,7 @@ describe Descope::Api::V1::Management::Tenant do
|
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
it 'is expected to update a tenant' do
|
|
49
|
-
expect(@instance).to receive(:
|
|
49
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
50
50
|
TENANT_UPDATE_PATH, {
|
|
51
51
|
name: 'test',
|
|
52
52
|
id: 'test',
|
|
@@ -77,7 +77,7 @@ describe Descope::Api::V1::Management::Tenant do
|
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
it 'is expected to delete a tenant' do
|
|
80
|
-
expect(@instance).to receive(:
|
|
80
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
81
81
|
TENANT_DELETE_PATH, { id: 'test' }
|
|
82
82
|
)
|
|
83
83
|
expect { @instance.delete_tenant('test') }.not_to raise_error
|
|
@@ -90,7 +90,7 @@ describe Descope::Api::V1::Management::Tenant do
|
|
|
90
90
|
end
|
|
91
91
|
|
|
92
92
|
it 'is expected to load a tenant' do
|
|
93
|
-
expect(@instance).to receive(:
|
|
93
|
+
expect(@instance).to receive(:mgmt_get).with(
|
|
94
94
|
TENANT_LOAD_PATH, { id: 'test' }
|
|
95
95
|
)
|
|
96
96
|
expect { @instance.load_tenant('test') }.not_to raise_error
|
|
@@ -103,7 +103,7 @@ describe Descope::Api::V1::Management::Tenant do
|
|
|
103
103
|
end
|
|
104
104
|
|
|
105
105
|
it 'is expected to load all tenants' do
|
|
106
|
-
expect(@instance).to receive(:
|
|
106
|
+
expect(@instance).to receive(:mgmt_get).with(TENANT_LOAD_ALL_PATH)
|
|
107
107
|
expect { @instance.load_all_tenants }.not_to raise_error
|
|
108
108
|
end
|
|
109
109
|
end
|
|
@@ -114,7 +114,7 @@ describe Descope::Api::V1::Management::Tenant do
|
|
|
114
114
|
end
|
|
115
115
|
|
|
116
116
|
it 'is expected to search all tenants' do
|
|
117
|
-
expect(@instance).to receive(:
|
|
117
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
118
118
|
TENANT_SEARCH_ALL_PATH, {
|
|
119
119
|
ids: %w[test1 test2],
|
|
120
120
|
names: %w[test1 test2],
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe Descope::Api::V1::Management::ThirdPartyApplication do
|
|
6
|
+
before(:all) do
|
|
7
|
+
dummy_instance = DummyClass.new
|
|
8
|
+
dummy_instance.extend(Descope::Api::V1::Management::ThirdPartyApplication)
|
|
9
|
+
@instance = dummy_instance
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
context('.create_application') do
|
|
13
|
+
it 'should respond to .create_application' do
|
|
14
|
+
expect(@instance).to respond_to :create_application
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'is expected to create a third party application' do
|
|
18
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
19
|
+
THIRD_PARTY_APP_CREATE_PATH, {
|
|
20
|
+
id: 'app1',
|
|
21
|
+
name: 'test',
|
|
22
|
+
description: 'awesome app',
|
|
23
|
+
logo: 'https://logo.com',
|
|
24
|
+
loginPageUrl: 'https://dummy.com/login',
|
|
25
|
+
approvedCallbackUrls: ['https://dummy.com/callback'],
|
|
26
|
+
permissionsScopes: [{ name: 'read' }],
|
|
27
|
+
attributesScopes: [{ name: 'email' }],
|
|
28
|
+
jwtBearerSettings: [{ tenantId: 'tenant1' }],
|
|
29
|
+
customAttributes: { key: 'value' },
|
|
30
|
+
forcePkce: true,
|
|
31
|
+
defaultAudience: 'aud1'
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
expect do
|
|
35
|
+
@instance.create_application(
|
|
36
|
+
id: 'app1',
|
|
37
|
+
name: 'test',
|
|
38
|
+
description: 'awesome app',
|
|
39
|
+
logo: 'https://logo.com',
|
|
40
|
+
login_page_url: 'https://dummy.com/login',
|
|
41
|
+
approved_callback_urls: ['https://dummy.com/callback'],
|
|
42
|
+
permissions_scopes: [{ name: 'read' }],
|
|
43
|
+
attributes_scopes: [{ name: 'email' }],
|
|
44
|
+
jwt_bearer_settings: [{ tenantId: 'tenant1' }],
|
|
45
|
+
custom_attributes: { key: 'value' },
|
|
46
|
+
force_pkce: true,
|
|
47
|
+
default_audience: 'aud1'
|
|
48
|
+
)
|
|
49
|
+
end.not_to raise_error
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context('.update_application') do
|
|
54
|
+
it 'should respond to .update_application' do
|
|
55
|
+
expect(@instance).to respond_to :update_application
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'is expected to update a third party application' do
|
|
59
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
60
|
+
THIRD_PARTY_APP_UPDATE_PATH, {
|
|
61
|
+
id: 'app1',
|
|
62
|
+
name: 'test',
|
|
63
|
+
description: 'awesome app',
|
|
64
|
+
logo: 'https://logo.com',
|
|
65
|
+
loginPageUrl: 'https://dummy.com/login'
|
|
66
|
+
}
|
|
67
|
+
)
|
|
68
|
+
expect do
|
|
69
|
+
@instance.update_application(
|
|
70
|
+
id: 'app1',
|
|
71
|
+
name: 'test',
|
|
72
|
+
description: 'awesome app',
|
|
73
|
+
logo: 'https://logo.com',
|
|
74
|
+
login_page_url: 'https://dummy.com/login'
|
|
75
|
+
)
|
|
76
|
+
end.not_to raise_error
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
context('.patch_application') do
|
|
81
|
+
it 'should respond to .patch_application' do
|
|
82
|
+
expect(@instance).to respond_to :patch_application
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it 'is expected to patch a third party application' do
|
|
86
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
87
|
+
THIRD_PARTY_APP_PATCH_PATH, {
|
|
88
|
+
id: 'app1',
|
|
89
|
+
name: 'test'
|
|
90
|
+
}
|
|
91
|
+
)
|
|
92
|
+
expect do
|
|
93
|
+
@instance.patch_application(
|
|
94
|
+
id: 'app1',
|
|
95
|
+
name: 'test'
|
|
96
|
+
)
|
|
97
|
+
end.not_to raise_error
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it 'is expected to delete a third party application' do
|
|
102
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
103
|
+
THIRD_PARTY_APP_DELETE_PATH, { id: 'app1' }
|
|
104
|
+
)
|
|
105
|
+
expect { @instance.delete_application('app1') }.not_to raise_error
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it 'is expected to load a third party application' do
|
|
109
|
+
expect(@instance).to receive(:mgmt_get).with(
|
|
110
|
+
THIRD_PARTY_APP_LOAD_PATH, { id: 'app1' }
|
|
111
|
+
)
|
|
112
|
+
expect { @instance.load_application('app1') }.not_to raise_error
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it 'is expected to load all third party applications' do
|
|
116
|
+
expect(@instance).to receive(:mgmt_get).with(
|
|
117
|
+
THIRD_PARTY_APP_LOAD_ALL_PATH, {}
|
|
118
|
+
)
|
|
119
|
+
expect { @instance.load_all_applications }.not_to raise_error
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it 'is expected to get a third party application secret' do
|
|
123
|
+
expect(@instance).to receive(:mgmt_get).with(
|
|
124
|
+
THIRD_PARTY_APP_SECRET_PATH, { id: 'app1' }
|
|
125
|
+
)
|
|
126
|
+
expect { @instance.get_application_secret('app1') }.not_to raise_error
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it 'is expected to rotate a third party application secret' do
|
|
130
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
131
|
+
THIRD_PARTY_APP_ROTATE_PATH, { id: 'app1' }
|
|
132
|
+
)
|
|
133
|
+
expect { @instance.rotate_application_secret('app1') }.not_to raise_error
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it 'is expected to delete consents' do
|
|
137
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
138
|
+
THIRD_PARTY_APP_DELETE_CONSENTS_PATH, {
|
|
139
|
+
consentIds: %w[consent1 consent2],
|
|
140
|
+
appId: 'app1',
|
|
141
|
+
userIds: %w[user1 user2],
|
|
142
|
+
tenantId: 'tenant1'
|
|
143
|
+
}
|
|
144
|
+
)
|
|
145
|
+
expect do
|
|
146
|
+
@instance.delete_consents(
|
|
147
|
+
app_id: 'app1',
|
|
148
|
+
consent_ids: %w[consent1 consent2],
|
|
149
|
+
user_ids: %w[user1 user2],
|
|
150
|
+
tenant_id: 'tenant1'
|
|
151
|
+
)
|
|
152
|
+
end.not_to raise_error
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
it 'is expected to delete tenant consents' do
|
|
156
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
157
|
+
THIRD_PARTY_APP_DELETE_TENANT_CONSENTS_PATH, {
|
|
158
|
+
consentIds: %w[consent1 consent2],
|
|
159
|
+
appId: 'app1',
|
|
160
|
+
tenantId: 'tenant1'
|
|
161
|
+
}
|
|
162
|
+
)
|
|
163
|
+
expect do
|
|
164
|
+
@instance.delete_tenant_consents(
|
|
165
|
+
app_id: 'app1',
|
|
166
|
+
consent_ids: %w[consent1 consent2],
|
|
167
|
+
tenant_id: 'tenant1'
|
|
168
|
+
)
|
|
169
|
+
end.not_to raise_error
|
|
170
|
+
end
|
|
171
|
+
end
|
|
@@ -58,7 +58,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
it 'is expected to create a user with user data' do
|
|
61
|
-
expect(@instance).to receive(:
|
|
61
|
+
expect(@instance).to receive(:mgmt_post).with(USER_CREATE_PATH, params)
|
|
62
62
|
|
|
63
63
|
expect do
|
|
64
64
|
@instance.create_user(**args)
|
|
@@ -67,7 +67,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
67
67
|
|
|
68
68
|
it 'is expected to create a test user with user data' do
|
|
69
69
|
params[:test] = true
|
|
70
|
-
expect(@instance).to receive(:
|
|
70
|
+
expect(@instance).to receive(:mgmt_post).with(TEST_USER_CREATE_PATH, params)
|
|
71
71
|
|
|
72
72
|
expect do
|
|
73
73
|
args[:test] = true
|
|
@@ -101,7 +101,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
101
101
|
}
|
|
102
102
|
]
|
|
103
103
|
}
|
|
104
|
-
expect(@instance).to receive(:
|
|
104
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
105
105
|
USER_CREATE_BATCH_PATH, users_params
|
|
106
106
|
)
|
|
107
107
|
|
|
@@ -117,7 +117,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
117
117
|
end
|
|
118
118
|
|
|
119
119
|
it "is expected to post #{USER_CREATE_PATH} with invite true" do
|
|
120
|
-
expect(@instance).to receive(:
|
|
120
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
121
121
|
USER_CREATE_PATH, {
|
|
122
122
|
loginId: 'name@mail.com',
|
|
123
123
|
email: 'name@mail.com',
|
|
@@ -143,7 +143,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
143
143
|
end
|
|
144
144
|
|
|
145
145
|
it 'is expected to respond to a user update method' do
|
|
146
|
-
expect(@instance).to receive(:
|
|
146
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
147
147
|
USER_UPDATE_PATH, {
|
|
148
148
|
loginId: 'name@mail.com',
|
|
149
149
|
email: 'name@mail.com',
|
|
@@ -171,7 +171,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
171
171
|
end
|
|
172
172
|
|
|
173
173
|
it 'is expected to respond to a user delete method' do
|
|
174
|
-
expect(@instance).to receive(:
|
|
174
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
175
175
|
USER_DELETE_PATH, { loginId: 'name@mail.com' }
|
|
176
176
|
)
|
|
177
177
|
|
|
@@ -183,7 +183,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
183
183
|
|
|
184
184
|
context '.delete_all_user' do
|
|
185
185
|
it 'is expected to respond to a user delete method' do
|
|
186
|
-
expect(@instance).to receive(:
|
|
186
|
+
expect(@instance).to receive(:mgmt_delete).with(USER_DELETE_ALL_TEST_USERS_PATH)
|
|
187
187
|
|
|
188
188
|
expect do
|
|
189
189
|
@instance.delete_all_test_users
|
|
@@ -197,7 +197,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
197
197
|
end
|
|
198
198
|
|
|
199
199
|
it "is expected to get #{USER_LOAD_PATH} with login_id" do
|
|
200
|
-
expect(@instance).to receive(:
|
|
200
|
+
expect(@instance).to receive(:mgmt_get).with(
|
|
201
201
|
USER_LOAD_PATH, { loginId: 'someone' }
|
|
202
202
|
)
|
|
203
203
|
expect { @instance.load_user('someone') }.not_to raise_error
|
|
@@ -206,7 +206,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
206
206
|
|
|
207
207
|
context '.load_by_user_id' do
|
|
208
208
|
it "is expected to get #{USER_LOAD_PATH} with user_id" do
|
|
209
|
-
allow(@instance).to receive(:
|
|
209
|
+
allow(@instance).to receive(:mgmt_get).with(
|
|
210
210
|
USER_LOAD_PATH, { userId: 'ABCD' }
|
|
211
211
|
)
|
|
212
212
|
expect { @instance.load_by_user_id('ABCD') }.not_to raise_error
|
|
@@ -215,7 +215,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
215
215
|
|
|
216
216
|
context '.logout_user' do
|
|
217
217
|
it 'is expected to respond to a logout user method' do
|
|
218
|
-
expect(@instance).to receive(:
|
|
218
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
219
219
|
USER_LOGOUT_PATH, { loginId: 'name@mail.com' }
|
|
220
220
|
)
|
|
221
221
|
|
|
@@ -225,7 +225,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
225
225
|
end
|
|
226
226
|
|
|
227
227
|
it 'is expected to respond to a logout user by id method' do
|
|
228
|
-
expect(@instance).to receive(:
|
|
228
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
229
229
|
USER_LOGOUT_PATH, { userId: 'U2ZpARjKAJJmq0fzU2lXNNCGnF4j' }
|
|
230
230
|
)
|
|
231
231
|
|
|
@@ -241,7 +241,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
241
241
|
|
|
242
242
|
tenant_role_ids = { 'tenant1' => ['roleA', 'roleB'] }
|
|
243
243
|
tenant_role_names = { 'tenant1' => ['roleName1', 'roleName2'] }
|
|
244
|
-
expect(@instance).to receive(:
|
|
244
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
245
245
|
USERS_SEARCH_PATH, {
|
|
246
246
|
loginId: 'someone@example.com',
|
|
247
247
|
tenantIds: [],
|
|
@@ -284,7 +284,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
284
284
|
it 'is expected to respond to a get_provider_token method' do
|
|
285
285
|
expect(@instance).to respond_to(:get_provider_token)
|
|
286
286
|
|
|
287
|
-
expect(@instance).to receive(:
|
|
287
|
+
expect(@instance).to receive(:mgmt_get).with(
|
|
288
288
|
USER_GET_PROVIDER_TOKEN, {
|
|
289
289
|
loginId: 'someone@example.com',
|
|
290
290
|
provider: 'google-oauth2'
|
|
@@ -304,7 +304,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
304
304
|
it 'is expected to respond to a activate method' do
|
|
305
305
|
expect(@instance).to respond_to(:activate)
|
|
306
306
|
|
|
307
|
-
expect(@instance).to receive(:
|
|
307
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
308
308
|
USER_UPDATE_STATUS_PATH, {
|
|
309
309
|
loginId: 'someone@example.com',
|
|
310
310
|
status: 'enabled'
|
|
@@ -321,7 +321,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
321
321
|
it 'is expected to respond to a activate method' do
|
|
322
322
|
expect(@instance).to respond_to(:activate)
|
|
323
323
|
|
|
324
|
-
expect(@instance).to receive(:
|
|
324
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
325
325
|
USER_UPDATE_STATUS_PATH, {
|
|
326
326
|
loginId: 'someone@example.com',
|
|
327
327
|
status: 'disabled'
|
|
@@ -338,7 +338,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
338
338
|
it 'is expected to respond to a update_email method' do
|
|
339
339
|
expect(@instance).to respond_to(:update_email)
|
|
340
340
|
|
|
341
|
-
expect(@instance).to receive(:
|
|
341
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
342
342
|
USER_UPDATE_EMAIL_PATH, {
|
|
343
343
|
loginId: 'someone@example.com',
|
|
344
344
|
email: 'tester@test.com',
|
|
@@ -360,7 +360,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
360
360
|
it 'is expected to respond to a update_phone method' do
|
|
361
361
|
expect(@instance).to respond_to(:update_phone)
|
|
362
362
|
|
|
363
|
-
expect(@instance).to receive(:
|
|
363
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
364
364
|
USER_UPDATE_PHONE_PATH, {
|
|
365
365
|
loginId: 'someone@example.com',
|
|
366
366
|
phone: '1234567890',
|
|
@@ -382,7 +382,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
382
382
|
it 'is expected to respond to a update_display_name method' do
|
|
383
383
|
expect(@instance).to respond_to(:update_display_name)
|
|
384
384
|
|
|
385
|
-
expect(@instance).to receive(:
|
|
385
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
386
386
|
USER_UPDATE_NAME_PATH, {
|
|
387
387
|
loginId: 'someone@example.com',
|
|
388
388
|
name: 'some guy',
|
|
@@ -408,7 +408,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
408
408
|
it 'is expected to respond to a update_picture method' do
|
|
409
409
|
expect(@instance).to respond_to(:update_picture)
|
|
410
410
|
|
|
411
|
-
expect(@instance).to receive(:
|
|
411
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
412
412
|
USER_UPDATE_PICTURE_PATH, {
|
|
413
413
|
loginId: 'someone@example.com',
|
|
414
414
|
picture: 'https://www.example.com/picture.png'
|
|
@@ -428,7 +428,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
428
428
|
it 'is expected to respond to a update_custom_attribute method' do
|
|
429
429
|
expect(@instance).to respond_to(:update_custom_attribute)
|
|
430
430
|
|
|
431
|
-
expect(@instance).to receive(:
|
|
431
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
432
432
|
USER_UPDATE_CUSTOM_ATTRIBUTE_PATH, {
|
|
433
433
|
loginId: 'someone@example.com',
|
|
434
434
|
attributeKey: 'OU',
|
|
@@ -450,7 +450,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
450
450
|
it 'is expected to respond to a add_roles method' do
|
|
451
451
|
expect(@instance).to respond_to(:user_add_roles)
|
|
452
452
|
|
|
453
|
-
expect(@instance).to receive(:
|
|
453
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
454
454
|
USER_ADD_ROLE_PATH, {
|
|
455
455
|
loginId: 'someone@example.com',
|
|
456
456
|
roleNames: %w[role1 role2],
|
|
@@ -472,7 +472,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
472
472
|
it 'is expected to respond to a user_remove_roles method' do
|
|
473
473
|
expect(@instance).to respond_to(:user_remove_roles)
|
|
474
474
|
|
|
475
|
-
expect(@instance).to receive(:
|
|
475
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
476
476
|
USER_REMOVE_ROLE_PATH, {
|
|
477
477
|
loginId: 'someone@example.com',
|
|
478
478
|
roleNames: %w[role1 role2],
|
|
@@ -494,7 +494,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
494
494
|
it 'is expected to respond to a add_tenant method' do
|
|
495
495
|
expect(@instance).to respond_to(:user_add_tenant)
|
|
496
496
|
|
|
497
|
-
expect(@instance).to receive(:
|
|
497
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
498
498
|
USER_ADD_TENANT_PATH, {
|
|
499
499
|
loginId: 'someone@example.com',
|
|
500
500
|
tenantId: 'tenant1'
|
|
@@ -514,7 +514,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
514
514
|
it 'is expected to respond to a remove_tenant method' do
|
|
515
515
|
expect(@instance).to respond_to(:user_remove_tenant)
|
|
516
516
|
|
|
517
|
-
expect(@instance).to receive(:
|
|
517
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
518
518
|
USER_REMOVE_TENANT_PATH, {
|
|
519
519
|
loginId: 'someone@example.com',
|
|
520
520
|
tenantId: 'tenant1'
|
|
@@ -534,7 +534,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
534
534
|
it 'is expected to respond to a add_tenant_role method' do
|
|
535
535
|
expect(@instance).to respond_to(:add_tenant_role)
|
|
536
536
|
|
|
537
|
-
expect(@instance).to receive(:
|
|
537
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
538
538
|
USER_ADD_TENANT_PATH, {
|
|
539
539
|
loginId: 'someone@example.com',
|
|
540
540
|
tenantId: 'tenant1',
|
|
@@ -556,7 +556,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
556
556
|
it 'is expected to respond to a remove_tenant_role method' do
|
|
557
557
|
expect(@instance).to respond_to(:user_remove_tenant_roles)
|
|
558
558
|
|
|
559
|
-
expect(@instance).to receive(:
|
|
559
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
560
560
|
USER_REMOVE_TENANT_PATH, {
|
|
561
561
|
loginId: 'someone@example.com',
|
|
562
562
|
tenantId: 'tenant1',
|
|
@@ -578,7 +578,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
578
578
|
it 'is expected to respond to a set_temporary_password method' do
|
|
579
579
|
expect(@instance).to respond_to(:set_temporary_password)
|
|
580
580
|
|
|
581
|
-
expect(@instance).to receive(:
|
|
581
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
582
582
|
USER_SET_TEMPORARY_PASSWORD_PATH, {
|
|
583
583
|
loginId: 'someone@example.com',
|
|
584
584
|
password: 's3cr3t'
|
|
@@ -598,7 +598,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
598
598
|
it 'is expected to respond to a set_active_password method' do
|
|
599
599
|
expect(@instance).to respond_to(:set_active_password)
|
|
600
600
|
|
|
601
|
-
expect(@instance).to receive(:
|
|
601
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
602
602
|
USER_SET_ACTIVE_PASSWORD_PATH, {
|
|
603
603
|
loginId: 'someone@example.com',
|
|
604
604
|
password: 's3cr3t'
|
|
@@ -618,7 +618,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
618
618
|
it 'is expected to respond to a set_password method' do
|
|
619
619
|
expect(@instance).to respond_to(:set_password)
|
|
620
620
|
|
|
621
|
-
expect(@instance).to receive(:
|
|
621
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
622
622
|
USER_SET_PASSWORD_PATH, {
|
|
623
623
|
loginId: 'someone@example.com',
|
|
624
624
|
password: 's3cr3t'
|
|
@@ -638,7 +638,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
638
638
|
it 'is expected to respond to a expire_password method' do
|
|
639
639
|
expect(@instance).to respond_to(:expire_password)
|
|
640
640
|
|
|
641
|
-
expect(@instance).to receive(:
|
|
641
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
642
642
|
USER_EXPIRE_PASSWORD_PATH, { loginId: 'someone@example.com' }
|
|
643
643
|
)
|
|
644
644
|
|
|
@@ -650,7 +650,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
650
650
|
it 'is expected to respond to a generate_otp_for_test method' do
|
|
651
651
|
expect(@instance).to respond_to(:generate_otp_for_test_user)
|
|
652
652
|
|
|
653
|
-
expect(@instance).to receive(:
|
|
653
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
654
654
|
USER_GENERATE_OTP_FOR_TEST_PATH, {
|
|
655
655
|
loginId: 'someone@example.com',
|
|
656
656
|
deliveryMethod: 'email'
|
|
@@ -670,7 +670,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
670
670
|
it 'is expected to respond to a generate_enchanted_link_for_test method' do
|
|
671
671
|
expect(@instance).to respond_to(:generate_enchanted_link_for_test_user)
|
|
672
672
|
|
|
673
|
-
expect(@instance).to receive(:
|
|
673
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
674
674
|
USER_GENERATE_ENCHANTED_LINK_FOR_TEST_PATH, {
|
|
675
675
|
loginId: 'someone@example.com',
|
|
676
676
|
URI: 'https://www.example.com'
|
|
@@ -690,7 +690,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
690
690
|
it 'is expected to respond to a update_jwt method' do
|
|
691
691
|
expect(@instance).to respond_to(:update_jwt)
|
|
692
692
|
|
|
693
|
-
expect(@instance).to receive(:
|
|
693
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
694
694
|
UPDATE_JWT_PATH, {
|
|
695
695
|
jwt: 'eyJ3abcde12345',
|
|
696
696
|
customClaims: { 'claim1' => 'value1', 'claim2' => 'value2' }
|
|
@@ -717,7 +717,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
717
717
|
customClaims: { 'abc': '123' }
|
|
718
718
|
}
|
|
719
719
|
|
|
720
|
-
expect(@instance).to receive(:
|
|
720
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
721
721
|
USER_GENERATE_EMBEDDED_LINK_PATH,
|
|
722
722
|
request_params
|
|
723
723
|
)
|
|
@@ -737,7 +737,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
737
737
|
end
|
|
738
738
|
|
|
739
739
|
it 'is expected to respond to a user patch method' do
|
|
740
|
-
expect(@instance).to receive(:
|
|
740
|
+
expect(@instance).to receive(:mgmt_patch).with(
|
|
741
741
|
USER_PATCH_PATH, {
|
|
742
742
|
loginId: 'name@mail.com',
|
|
743
743
|
email: 'name@mail.com',
|
|
@@ -765,7 +765,7 @@ describe Descope::Api::V1::Management::User do
|
|
|
765
765
|
|
|
766
766
|
tenant_role_ids = { 'tenant1' => ['roleA', 'roleB'] }
|
|
767
767
|
tenant_role_names = { 'tenant1' => ['roleName1', 'roleName2'] }
|
|
768
|
-
expect(@instance).to receive(:
|
|
768
|
+
expect(@instance).to receive(:mgmt_post).with(
|
|
769
769
|
TEST_USERS_SEARCH_PATH, {
|
|
770
770
|
tenantIds: %w[t1 t2],
|
|
771
771
|
roleNames: %w[r1 r2],
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
# Covers the Authorization header the SDK actually sends. The auth management key rides along with
|
|
6
|
+
# every authentication request so that methods whose public access has been disabled can still be
|
|
7
|
+
# used, and it is never sent on management requests - those carry the management key instead.
|
|
8
|
+
describe 'auth management key' do
|
|
9
|
+
let(:project_id) { 'P2abcde12345' }
|
|
10
|
+
let(:management_key) { 'mgmt-key' }
|
|
11
|
+
let(:auth_management_key) { 'auth-key' }
|
|
12
|
+
let(:refresh_token) { 'refresh-token' }
|
|
13
|
+
|
|
14
|
+
# Stubs the RestClient boundary on both of the client's HTTP clients and hands back the
|
|
15
|
+
# Authorization header of whichever one ends up being used.
|
|
16
|
+
def authorization_for(client)
|
|
17
|
+
captured = nil
|
|
18
|
+
[client.auth_http, client.mgmt_http].each do |http|
|
|
19
|
+
allow(http).to receive(:call) do |_method, _url, _timeout, headers, _body|
|
|
20
|
+
captured = headers['Authorization']
|
|
21
|
+
double('response', code: 200, body: '{}', cookies: {}, headers: {})
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
yield
|
|
25
|
+
captured
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def build_client(**options)
|
|
29
|
+
Descope::Client.new({ project_id: project_id, log_level: 'fatal' }.merge(options))
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# An authentication request that presents no token of its own.
|
|
33
|
+
def sign_up(client)
|
|
34
|
+
client.otp_sign_up(method: Descope::Mixins::Common::DeliveryMethod::EMAIL, login_id: 'someone@example.com')
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
around do |example|
|
|
38
|
+
keys = %w[DESCOPE_MANAGEMENT_KEY DESCOPE_AUTH_MANAGEMENT_KEY]
|
|
39
|
+
saved = keys.to_h { |var| [var, ENV[var]] }
|
|
40
|
+
keys.each { |var| ENV.delete(var) }
|
|
41
|
+
example.run
|
|
42
|
+
ensure
|
|
43
|
+
saved.each { |var, value| ENV[var] = value }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context 'on authentication requests' do
|
|
47
|
+
it 'sends only the project ID when no auth management key is configured' do
|
|
48
|
+
client = build_client
|
|
49
|
+
header = authorization_for(client) { sign_up(client) }
|
|
50
|
+
expect(header).to eq("Bearer #{project_id}")
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'appends the auth management key when one is configured' do
|
|
54
|
+
client = build_client(auth_management_key: auth_management_key)
|
|
55
|
+
header = authorization_for(client) { sign_up(client) }
|
|
56
|
+
expect(header).to eq("Bearer #{project_id}:#{auth_management_key}")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it 'appends the auth management key after a refresh token' do
|
|
60
|
+
client = build_client(auth_management_key: auth_management_key)
|
|
61
|
+
header = authorization_for(client) { client.me(refresh_token) }
|
|
62
|
+
expect(header).to eq("Bearer #{project_id}:#{refresh_token}:#{auth_management_key}")
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it 'never sends the management key' do
|
|
66
|
+
client = build_client(management_key: management_key, auth_management_key: auth_management_key)
|
|
67
|
+
header = authorization_for(client) { sign_up(client) }
|
|
68
|
+
expect(header).to eq("Bearer #{project_id}:#{auth_management_key}")
|
|
69
|
+
expect(header).to_not include(management_key)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# DummyClass swallows extra_headers, so only a real client exercises this argument.
|
|
73
|
+
it 'tolerates a nil extra_headers from the caller' do
|
|
74
|
+
client = build_client(auth_management_key: auth_management_key)
|
|
75
|
+
header = authorization_for(client) { client.post(SIGN_IN_PASSWORD_PATH, {}, nil, refresh_token) }
|
|
76
|
+
expect(header).to eq("Bearer #{project_id}:#{refresh_token}:#{auth_management_key}")
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it 'signs in with an enchanted link' do
|
|
80
|
+
client = build_client(auth_management_key: auth_management_key)
|
|
81
|
+
header = authorization_for(client) do
|
|
82
|
+
client.enchanted_link_sign_in(login_id: 'someone@example.com', uri: 'https://example.com')
|
|
83
|
+
end
|
|
84
|
+
expect(header).to eq("Bearer #{project_id}:#{auth_management_key}")
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it 'does not substitute a key for an empty refresh token' do
|
|
88
|
+
client = build_client(management_key: management_key, auth_management_key: auth_management_key)
|
|
89
|
+
header = authorization_for(client) { client.sign_out('') }
|
|
90
|
+
expect(header).to eq("Bearer #{project_id}:#{auth_management_key}")
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
context 'on management requests' do
|
|
95
|
+
it 'appends the management key' do
|
|
96
|
+
client = build_client(management_key: management_key)
|
|
97
|
+
header = authorization_for(client) { client.load_all_tenants }
|
|
98
|
+
expect(header).to eq("Bearer #{project_id}:#{management_key}")
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it 'never sends the auth management key' do
|
|
102
|
+
client = build_client(management_key: management_key, auth_management_key: auth_management_key)
|
|
103
|
+
header = authorization_for(client) { client.load_all_tenants }
|
|
104
|
+
expect(header).to eq("Bearer #{project_id}:#{management_key}")
|
|
105
|
+
expect(header).to_not include(auth_management_key)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it 'sends only the project ID when no management key is configured' do
|
|
109
|
+
client = build_client(auth_management_key: auth_management_key)
|
|
110
|
+
header = authorization_for(client) { client.load_all_tenants }
|
|
111
|
+
expect(header).to eq("Bearer #{project_id}")
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
context 'configuration' do
|
|
116
|
+
it 'falls back to the DESCOPE_AUTH_MANAGEMENT_KEY env var' do
|
|
117
|
+
ENV['DESCOPE_AUTH_MANAGEMENT_KEY'] = 'env-auth-key'
|
|
118
|
+
client = build_client
|
|
119
|
+
header = authorization_for(client) { sign_up(client) }
|
|
120
|
+
expect(header).to eq("Bearer #{project_id}:env-auth-key")
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it 'prefers the configured key over the env var' do
|
|
124
|
+
ENV['DESCOPE_AUTH_MANAGEMENT_KEY'] = 'env-auth-key'
|
|
125
|
+
client = build_client(auth_management_key: auth_management_key)
|
|
126
|
+
header = authorization_for(client) { sign_up(client) }
|
|
127
|
+
expect(header).to eq("Bearer #{project_id}:#{auth_management_key}")
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it 'keeps the two keys distinct' do
|
|
131
|
+
ENV['DESCOPE_MANAGEMENT_KEY'] = management_key
|
|
132
|
+
ENV['DESCOPE_AUTH_MANAGEMENT_KEY'] = auth_management_key
|
|
133
|
+
client = build_client
|
|
134
|
+
expect(client.auth_http.authorization_header).to eq(
|
|
135
|
+
{ 'Authorization' => "Bearer #{project_id}:#{auth_management_key}" }
|
|
136
|
+
)
|
|
137
|
+
expect(client.mgmt_http.authorization_header).to eq(
|
|
138
|
+
{ 'Authorization' => "Bearer #{project_id}:#{management_key}" }
|
|
139
|
+
)
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
describe 'debug logging' do
|
|
144
|
+
it 'masks everything after the project ID' do
|
|
145
|
+
client = build_client(auth_management_key: auth_management_key)
|
|
146
|
+
masked = client.auth_http.mask_authorization(client.auth_http.authorization_header)
|
|
147
|
+
expect(masked['Authorization']).to eq("Bearer #{project_id}:***")
|
|
148
|
+
expect(masked['Authorization']).to_not include(auth_management_key)
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|