auth0-deploy-cli 8.31.0 → 8.33.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.
- package/CHANGELOG.md +46 -1
- package/lib/args.d.ts +4 -0
- package/lib/args.js +18 -0
- package/lib/commands/import.js +40 -3
- package/lib/context/directory/handlers/clients.js +14 -0
- package/lib/context/directory/handlers/connections.js +1 -0
- package/lib/context/directory/handlers/guardianFactors.js +8 -6
- package/lib/context/directory/handlers/tenant.d.ts +1 -6
- package/lib/context/directory/handlers/tenant.js +0 -1
- package/lib/context/index.js +5 -0
- package/lib/context/yaml/handlers/clients.js +12 -0
- package/lib/context/yaml/handlers/connections.js +1 -17
- package/lib/context/yaml/handlers/guardianFactors.js +3 -1
- package/lib/context/yaml/handlers/tenant.js +1 -1
- package/lib/sessionDurationsToMinutes.d.ts +9 -7
- package/lib/sessionDurationsToMinutes.js +11 -10
- package/lib/tools/auth0/handlers/actions.d.ts +1 -0
- package/lib/tools/auth0/handlers/actions.js +68 -29
- package/lib/tools/auth0/handlers/attackProtection.js +15 -0
- package/lib/tools/auth0/handlers/branding.js +7 -0
- package/lib/tools/auth0/handlers/clientGrants.d.ts +5 -0
- package/lib/tools/auth0/handlers/clientGrants.js +31 -9
- package/lib/tools/auth0/handlers/clients.d.ts +62 -2
- package/lib/tools/auth0/handlers/clients.js +187 -22
- package/lib/tools/auth0/handlers/connections.d.ts +18 -0
- package/lib/tools/auth0/handlers/connections.js +86 -5
- package/lib/tools/auth0/handlers/databases.d.ts +91 -0
- package/lib/tools/auth0/handlers/databases.js +162 -2
- package/lib/tools/auth0/handlers/default.d.ts +4 -0
- package/lib/tools/auth0/handlers/default.js +82 -4
- package/lib/tools/auth0/handlers/emailProvider.js +8 -0
- package/lib/tools/auth0/handlers/emailTemplates.js +7 -0
- package/lib/tools/auth0/handlers/flowVaultConnections.js +6 -1
- package/lib/tools/auth0/handlers/flows.js +13 -4
- package/lib/tools/auth0/handlers/forms.js +10 -1
- package/lib/tools/auth0/handlers/guardianFactors.js +7 -1
- package/lib/tools/auth0/handlers/guardianPhoneFactorMessageTypes.js +8 -1
- package/lib/tools/auth0/handlers/guardianPhoneFactorSelectedProvider.js +8 -1
- package/lib/tools/auth0/handlers/guardianPolicies.js +7 -0
- package/lib/tools/auth0/handlers/hooks.d.ts +1 -0
- package/lib/tools/auth0/handlers/hooks.js +10 -0
- package/lib/tools/auth0/handlers/organizations.d.ts +11 -1
- package/lib/tools/auth0/handlers/organizations.js +48 -52
- package/lib/tools/auth0/handlers/pages.js +7 -0
- package/lib/tools/auth0/handlers/phoneProvider.js +7 -0
- package/lib/tools/auth0/handlers/prompts.js +7 -0
- package/lib/tools/auth0/handlers/resourceServers.d.ts +1 -2
- package/lib/tools/auth0/handlers/resourceServers.js +9 -25
- package/lib/tools/auth0/handlers/roles.js +7 -0
- package/lib/tools/auth0/handlers/rules.d.ts +1 -0
- package/lib/tools/auth0/handlers/rules.js +9 -0
- package/lib/tools/auth0/handlers/rulesConfigs.d.ts +1 -0
- package/lib/tools/auth0/handlers/rulesConfigs.js +3 -0
- package/lib/tools/auth0/handlers/scimHandler.js +8 -1
- package/lib/tools/auth0/handlers/selfServiceProfiles.d.ts +1 -1
- package/lib/tools/auth0/handlers/selfServiceProfiles.js +10 -17
- package/lib/tools/auth0/handlers/tenant.d.ts +18 -1
- package/lib/tools/auth0/handlers/tenant.js +48 -4
- package/lib/tools/auth0/handlers/themes.js +11 -2
- package/lib/tools/auth0/handlers/triggers.js +6 -0
- package/lib/tools/auth0/handlers/userAttributeProfiles.js +16 -10
- package/lib/tools/auth0/index.d.ts +3 -0
- package/lib/tools/auth0/index.js +204 -0
- package/lib/tools/calculateChanges.d.ts +2 -2
- package/lib/tools/calculateChanges.js +21 -6
- package/lib/tools/calculateDryRunChanges.d.ts +71 -0
- package/lib/tools/calculateDryRunChanges.js +492 -0
- package/lib/tools/deploy.js +25 -1
- package/lib/tools/utils.d.ts +5 -0
- package/lib/tools/utils.js +64 -3
- package/lib/types.d.ts +16 -0
- package/lib/utils.d.ts +7 -0
- package/lib/utils.js +33 -1
- package/package.json +7 -4
|
@@ -73,8 +73,13 @@ exports.schema = {
|
|
|
73
73
|
type: 'boolean',
|
|
74
74
|
description: 'When enabled, all scopes configured on the resource server are allowed for by this client grant.',
|
|
75
75
|
},
|
|
76
|
+
default_for: {
|
|
77
|
+
type: 'string',
|
|
78
|
+
enum: ['third_party_clients'],
|
|
79
|
+
description: 'Indicates that a client grant is the default client grant for third party clients.',
|
|
80
|
+
},
|
|
76
81
|
},
|
|
77
|
-
required: ['
|
|
82
|
+
required: ['audience'],
|
|
78
83
|
},
|
|
79
84
|
};
|
|
80
85
|
class ClientGrantsHandler extends default_1.default {
|
|
@@ -83,11 +88,18 @@ class ClientGrantsHandler extends default_1.default {
|
|
|
83
88
|
...config,
|
|
84
89
|
type: 'clientGrants',
|
|
85
90
|
id: 'id',
|
|
86
|
-
//
|
|
87
|
-
// Try ['client_id', 'audience', 'subject_type'] first
|
|
88
|
-
// ['
|
|
89
|
-
|
|
90
|
-
|
|
91
|
+
// Nested arrays are not reflected in the type but are supported at runtime.
|
|
92
|
+
// Try ['client_id', 'audience', 'subject_type'] first, then ['client_id', 'audience']
|
|
93
|
+
// for regular grants, then ['default_for', 'audience'] for default third-party grants
|
|
94
|
+
// which have no client_id.
|
|
95
|
+
identifiers: [
|
|
96
|
+
'id',
|
|
97
|
+
['client_id', 'audience', 'subject_type'],
|
|
98
|
+
['client_id', 'audience'],
|
|
99
|
+
['default_for', 'audience'],
|
|
100
|
+
],
|
|
101
|
+
stripUpdateFields: ['audience', 'client_id', 'subject_type', 'is_system', 'default_for'],
|
|
102
|
+
ignoreDryRunFields: ['_clientName'],
|
|
91
103
|
});
|
|
92
104
|
}
|
|
93
105
|
objString(item) {
|
|
@@ -100,6 +112,15 @@ class ClientGrantsHandler extends default_1.default {
|
|
|
100
112
|
return;
|
|
101
113
|
// Validate each client grant
|
|
102
114
|
clientGrants.forEach((grant) => {
|
|
115
|
+
// client_id and default_for are mutually exclusive; exactly one must be present
|
|
116
|
+
const hasClientId = !!grant.client_id;
|
|
117
|
+
const hasDefaultFor = !!grant.default_for;
|
|
118
|
+
if (hasClientId && hasDefaultFor) {
|
|
119
|
+
throw new Error(`Client grant for audience "${grant.audience}": Cannot specify both "client_id" and "default_for". They are mutually exclusive.`);
|
|
120
|
+
}
|
|
121
|
+
if (!hasClientId && !hasDefaultFor) {
|
|
122
|
+
throw new Error(`Client grant for audience "${grant.audience}": One of "client_id" or "default_for" is required.`);
|
|
123
|
+
}
|
|
103
124
|
// When allow_all_scopes is true, scope should not be present
|
|
104
125
|
if (grant.allow_all_scopes === true && grant.scope && grant.scope.length > 0) {
|
|
105
126
|
throw new Error(`Client grant for client_id "${grant.client_id}" and audience "${grant.audience}": Cannot specify "scope" when "allow_all_scopes" is set to true. Remove the "scope" property or set "allow_all_scopes" to false.`);
|
|
@@ -126,7 +147,8 @@ class ClientGrantsHandler extends default_1.default {
|
|
|
126
147
|
is_first_party: true,
|
|
127
148
|
});
|
|
128
149
|
const firstPartyClientIds = new Set(clients.map((c) => c.client_id));
|
|
129
|
-
|
|
150
|
+
// default_for grants have no client_id and are not tied to a specific client; always keep them
|
|
151
|
+
this.existing = this.existing.filter((grant) => !grant.client_id || firstPartyClientIds.has(grant.client_id));
|
|
130
152
|
}
|
|
131
153
|
return this.existing;
|
|
132
154
|
}
|
|
@@ -186,9 +208,9 @@ class ClientGrantsHandler extends default_1.default {
|
|
|
186
208
|
let filtered = list;
|
|
187
209
|
// Filter out the current client (Auth0 Management API client)
|
|
188
210
|
filtered = filtered.filter((item) => item.client_id !== currentClient);
|
|
189
|
-
// Filter out excluded clients
|
|
211
|
+
// Filter out excluded clients; default_for grants have no client_id and are never excluded
|
|
190
212
|
if (excludedClients.length) {
|
|
191
|
-
filtered = filtered.filter((item) => item.client_id
|
|
213
|
+
filtered = filtered.filter((item) => !item.client_id ||
|
|
192
214
|
![...excludedClientsByNames, ...excludedClients].includes(item.client_id));
|
|
193
215
|
}
|
|
194
216
|
// Filter out system grants
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Management } from 'auth0';
|
|
2
|
-
import { Assets, Auth0APIClient } from '../../../types';
|
|
2
|
+
import { Assets, Auth0APIClient, CalculatedChanges } from '../../../types';
|
|
3
3
|
import DefaultAPIHandler from './default';
|
|
4
4
|
export declare const schema: {
|
|
5
5
|
type: string;
|
|
@@ -11,6 +11,22 @@ export declare const schema: {
|
|
|
11
11
|
minLength: number;
|
|
12
12
|
pattern: string;
|
|
13
13
|
};
|
|
14
|
+
external_client_id: {
|
|
15
|
+
type: string;
|
|
16
|
+
description: string;
|
|
17
|
+
};
|
|
18
|
+
external_metadata_type: {
|
|
19
|
+
type: string;
|
|
20
|
+
description: string;
|
|
21
|
+
};
|
|
22
|
+
external_metadata_created_by: {
|
|
23
|
+
type: string;
|
|
24
|
+
description: string;
|
|
25
|
+
};
|
|
26
|
+
jwks_uri: {
|
|
27
|
+
type: string;
|
|
28
|
+
description: string;
|
|
29
|
+
};
|
|
14
30
|
mobile: {
|
|
15
31
|
type: string;
|
|
16
32
|
properties: {
|
|
@@ -184,6 +200,35 @@ export declare const schema: {
|
|
|
184
200
|
enum: string[];
|
|
185
201
|
};
|
|
186
202
|
};
|
|
203
|
+
my_organization_configuration: {
|
|
204
|
+
type: string[];
|
|
205
|
+
description: string;
|
|
206
|
+
properties: {
|
|
207
|
+
connection_profile_id: {
|
|
208
|
+
type: string;
|
|
209
|
+
description: string;
|
|
210
|
+
};
|
|
211
|
+
user_attribute_profile_id: {
|
|
212
|
+
type: string;
|
|
213
|
+
description: string;
|
|
214
|
+
};
|
|
215
|
+
allowed_strategies: {
|
|
216
|
+
type: string;
|
|
217
|
+
description: string;
|
|
218
|
+
items: {
|
|
219
|
+
type: string;
|
|
220
|
+
enum: ("samlp" | "pingfederate" | "adfs" | "waad" | "google-apps" | "okta" | "oidc")[];
|
|
221
|
+
};
|
|
222
|
+
uniqueItems: boolean;
|
|
223
|
+
};
|
|
224
|
+
connection_deletion_behavior: {
|
|
225
|
+
type: string;
|
|
226
|
+
enum: ("allow" | "allow_if_empty")[];
|
|
227
|
+
description: string;
|
|
228
|
+
};
|
|
229
|
+
};
|
|
230
|
+
required: string[];
|
|
231
|
+
};
|
|
187
232
|
async_approval_notification_channels: {
|
|
188
233
|
type: string[];
|
|
189
234
|
description: string;
|
|
@@ -263,6 +308,16 @@ export declare const schema: {
|
|
|
263
308
|
};
|
|
264
309
|
};
|
|
265
310
|
};
|
|
311
|
+
third_party_security_mode: {
|
|
312
|
+
type: string;
|
|
313
|
+
enum: string[];
|
|
314
|
+
description: string;
|
|
315
|
+
};
|
|
316
|
+
redirection_policy: {
|
|
317
|
+
type: string;
|
|
318
|
+
enum: string[];
|
|
319
|
+
description: string;
|
|
320
|
+
};
|
|
266
321
|
oidc_logout: {
|
|
267
322
|
type: string[];
|
|
268
323
|
description: string;
|
|
@@ -315,7 +370,12 @@ export default class ClientHandler extends DefaultAPIHandler {
|
|
|
315
370
|
existing: Client[];
|
|
316
371
|
constructor(config: DefaultAPIHandler);
|
|
317
372
|
objString(item: any): string;
|
|
373
|
+
calcChanges(assets: Assets): Promise<CalculatedChanges>;
|
|
318
374
|
processChanges(assets: Assets): Promise<void>;
|
|
319
375
|
getType(): Promise<Management.Client[]>;
|
|
320
|
-
|
|
376
|
+
private isCimdClient;
|
|
377
|
+
private createClient;
|
|
378
|
+
private getCIMDEditableFields;
|
|
379
|
+
private updateClient;
|
|
380
|
+
sanitizeMapClientReferences(auth0Client: Auth0APIClient, clientList: Client[]): Promise<Client[]>;
|
|
321
381
|
}
|
|
@@ -4,9 +4,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.schema = void 0;
|
|
7
|
+
const auth0_1 = require("auth0");
|
|
7
8
|
const lodash_1 = require("lodash");
|
|
8
9
|
const client_1 = require("../client");
|
|
9
10
|
const default_1 = __importDefault(require("./default"));
|
|
11
|
+
const calculateChanges_1 = require("../../calculateChanges");
|
|
10
12
|
const connectionProfiles_1 = require("./connectionProfiles");
|
|
11
13
|
const userAttributeProfiles_1 = require("./userAttributeProfiles");
|
|
12
14
|
const logger_1 = __importDefault(require("../../../logger"));
|
|
@@ -31,12 +33,57 @@ const multiResourceRefreshTokenPoliciesSchema = {
|
|
|
31
33
|
required: ['audience', 'scope'],
|
|
32
34
|
},
|
|
33
35
|
};
|
|
36
|
+
const myOrganizationConfigurationSchema = {
|
|
37
|
+
type: ['object', 'null'],
|
|
38
|
+
description: 'Configuration related to the My Organization API for the client.',
|
|
39
|
+
properties: {
|
|
40
|
+
connection_profile_id: {
|
|
41
|
+
type: 'string',
|
|
42
|
+
description: 'The name of the connection profile to use for this application',
|
|
43
|
+
},
|
|
44
|
+
user_attribute_profile_id: {
|
|
45
|
+
type: 'string',
|
|
46
|
+
description: 'The name of the user attribute profile to use for this application',
|
|
47
|
+
},
|
|
48
|
+
allowed_strategies: {
|
|
49
|
+
type: 'array',
|
|
50
|
+
description: 'The allowed connection strategies for the My Organization configuration',
|
|
51
|
+
items: {
|
|
52
|
+
type: 'string',
|
|
53
|
+
enum: Object.values(auth0_1.Management.ClientMyOrganizationConfigurationAllowedStrategiesEnum),
|
|
54
|
+
},
|
|
55
|
+
uniqueItems: true,
|
|
56
|
+
},
|
|
57
|
+
connection_deletion_behavior: {
|
|
58
|
+
type: 'string',
|
|
59
|
+
enum: Object.values(auth0_1.Management.ClientMyOrganizationDeletionBehaviorEnum),
|
|
60
|
+
description: 'The deletion behavior for My Organization connections created by this client',
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
required: ['allowed_strategies', 'connection_deletion_behavior'],
|
|
64
|
+
};
|
|
34
65
|
exports.schema = {
|
|
35
66
|
type: 'array',
|
|
36
67
|
items: {
|
|
37
68
|
type: 'object',
|
|
38
69
|
properties: {
|
|
39
70
|
name: { type: 'string', minLength: 1, pattern: '[^<>]+' },
|
|
71
|
+
external_client_id: {
|
|
72
|
+
type: 'string',
|
|
73
|
+
description: 'Alternative identifier for the client. For CIMD clients, this is the HTTPS URL to the OAuth 2.0 Client ID Metadata Document. Client name should match the client_name value in the metadata document.',
|
|
74
|
+
},
|
|
75
|
+
external_metadata_type: {
|
|
76
|
+
type: 'string',
|
|
77
|
+
description: 'Type of external client registration metadata.',
|
|
78
|
+
},
|
|
79
|
+
external_metadata_created_by: {
|
|
80
|
+
type: 'string',
|
|
81
|
+
description: 'Indicates who created the external metadata client: admin for Management API, client for dynamic registration.',
|
|
82
|
+
},
|
|
83
|
+
jwks_uri: {
|
|
84
|
+
type: 'string',
|
|
85
|
+
description: 'JSON Web Key Set endpoint associated with the client.',
|
|
86
|
+
},
|
|
40
87
|
mobile: {
|
|
41
88
|
type: 'object',
|
|
42
89
|
properties: {
|
|
@@ -177,6 +224,7 @@ exports.schema = {
|
|
|
177
224
|
enum: ['email', 'organization_name'],
|
|
178
225
|
},
|
|
179
226
|
},
|
|
227
|
+
my_organization_configuration: myOrganizationConfigurationSchema,
|
|
180
228
|
async_approval_notification_channels: {
|
|
181
229
|
type: ['array', 'null'],
|
|
182
230
|
description: 'An ordered array of notification channels enabled for CIBA (Client-Initiated Backchannel Authentication) requests. Channels are evaluated in the order specified.',
|
|
@@ -259,11 +307,21 @@ exports.schema = {
|
|
|
259
307
|
description: 'List of enabled token exchange profile types for this client',
|
|
260
308
|
items: {
|
|
261
309
|
type: 'string',
|
|
262
|
-
enum: ['custom_authentication'],
|
|
310
|
+
enum: ['custom_authentication', 'on_behalf_of_token_exchange'],
|
|
263
311
|
},
|
|
264
312
|
},
|
|
265
313
|
},
|
|
266
314
|
},
|
|
315
|
+
third_party_security_mode: {
|
|
316
|
+
type: 'string',
|
|
317
|
+
enum: ['strict', 'permissive'],
|
|
318
|
+
description: 'Indicates the security mode for a Third Party Client, to apply new security semantics and improvements.',
|
|
319
|
+
},
|
|
320
|
+
redirection_policy: {
|
|
321
|
+
type: 'string',
|
|
322
|
+
enum: ['allow_always', 'open_redirect_protection'],
|
|
323
|
+
description: 'Determines how OAuth2/OIDC errors are handled when a non-recoverable error happens.',
|
|
324
|
+
},
|
|
267
325
|
oidc_logout: {
|
|
268
326
|
type: ['object', 'null'],
|
|
269
327
|
description: 'Configuration for OIDC backchannel logout',
|
|
@@ -376,6 +434,7 @@ class ClientHandler extends default_1.default {
|
|
|
376
434
|
id: 'client_id',
|
|
377
435
|
identifiers: ['client_id', 'name'],
|
|
378
436
|
objectFields: ['client_metadata'],
|
|
437
|
+
stripCreateFields: ['external_metadata_type', 'external_metadata_created_by', 'jwks_uri'],
|
|
379
438
|
stripUpdateFields: [
|
|
380
439
|
// Fields not allowed during updates
|
|
381
440
|
'callback_url_template',
|
|
@@ -384,18 +443,62 @@ class ClientHandler extends default_1.default {
|
|
|
384
443
|
'tenant',
|
|
385
444
|
'jwt_configuration.secret_encoded',
|
|
386
445
|
'resource_server_identifier',
|
|
446
|
+
'external_metadata_type',
|
|
447
|
+
'external_metadata_created_by',
|
|
448
|
+
'jwks_uri',
|
|
449
|
+
// third_party_security_mode is immutable after creation; PATCH returns 400
|
|
450
|
+
'third_party_security_mode',
|
|
387
451
|
],
|
|
452
|
+
functions: {
|
|
453
|
+
create: (client) => this.createClient(client),
|
|
454
|
+
update: (clientId, client) => this.updateClient(clientId, client),
|
|
455
|
+
},
|
|
388
456
|
});
|
|
389
457
|
}
|
|
390
458
|
objString(item) {
|
|
391
459
|
return super.objString({ name: item.name, client_id: item.client_id });
|
|
392
460
|
}
|
|
461
|
+
async calcChanges(assets) {
|
|
462
|
+
const clients = assets[this.type];
|
|
463
|
+
if (!clients) {
|
|
464
|
+
return { del: [], create: [], conflicts: [], update: [] };
|
|
465
|
+
}
|
|
466
|
+
const existing = await this.getType();
|
|
467
|
+
const allowDelete = !!this.config('AUTH0_ALLOW_DELETE');
|
|
468
|
+
const cimdClients = clients.filter((c) => this.isCimdClient(c));
|
|
469
|
+
const existingCimd = (existing || []).filter((c) => this.isCimdClient(c));
|
|
470
|
+
const regularClients = clients.filter((c) => !this.isCimdClient(c));
|
|
471
|
+
const existingRegular = (existing || []).filter((c) => !this.isCimdClient(c));
|
|
472
|
+
const regularChanges = (0, calculateChanges_1.calculateChanges)({
|
|
473
|
+
handler: this,
|
|
474
|
+
assets: regularClients,
|
|
475
|
+
existing: existingRegular,
|
|
476
|
+
identifiers: ['client_id', 'name'],
|
|
477
|
+
allowDelete,
|
|
478
|
+
});
|
|
479
|
+
// CIMD clients:
|
|
480
|
+
// If external_client_id changes (and no client_id match), old client is deleted
|
|
481
|
+
// and new registration is created with the new external_client_id.
|
|
482
|
+
const cimdChanges = (0, calculateChanges_1.calculateChanges)({
|
|
483
|
+
handler: this,
|
|
484
|
+
assets: cimdClients,
|
|
485
|
+
existing: existingCimd,
|
|
486
|
+
identifiers: ['client_id', 'external_client_id'],
|
|
487
|
+
allowDelete,
|
|
488
|
+
});
|
|
489
|
+
return {
|
|
490
|
+
del: [...regularChanges.del, ...cimdChanges.del],
|
|
491
|
+
update: [...regularChanges.update, ...cimdChanges.update],
|
|
492
|
+
create: [...regularChanges.create, ...cimdChanges.create],
|
|
493
|
+
conflicts: [...regularChanges.conflicts, ...cimdChanges.conflicts],
|
|
494
|
+
};
|
|
495
|
+
}
|
|
393
496
|
async processChanges(assets) {
|
|
394
497
|
const { clients } = assets;
|
|
395
498
|
// Do nothing if not set
|
|
396
499
|
if (!clients)
|
|
397
500
|
return;
|
|
398
|
-
assets.clients = await this.
|
|
501
|
+
assets.clients = await this.sanitizeMapClientReferences(this.client, clients);
|
|
399
502
|
const excludedClients = (assets.exclude && assets.exclude.clients) || [];
|
|
400
503
|
const { del, update, create, conflicts } = await this.calcChanges(assets);
|
|
401
504
|
// Always filter out the client we are using to access Auth0 Management API
|
|
@@ -453,37 +556,99 @@ class ClientHandler extends default_1.default {
|
|
|
453
556
|
this.existing = createClientSanitizer(clients).sanitizeCrossOriginAuth(false).get();
|
|
454
557
|
return this.existing;
|
|
455
558
|
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
559
|
+
isCimdClient(client) {
|
|
560
|
+
return !!client.external_client_id;
|
|
561
|
+
}
|
|
562
|
+
async createClient(client) {
|
|
563
|
+
if (!this.isCimdClient(client)) {
|
|
564
|
+
return this.client.clients.create(client);
|
|
565
|
+
}
|
|
566
|
+
const externalClientId = client.external_client_id;
|
|
567
|
+
const registration = await this.client.clients.registerCimdClient({
|
|
568
|
+
external_client_id: externalClientId,
|
|
569
|
+
});
|
|
570
|
+
return registration;
|
|
571
|
+
}
|
|
572
|
+
getCIMDEditableFields(client) {
|
|
573
|
+
// Only a subset of fields are editable for CIMD clients.
|
|
574
|
+
return (0, lodash_1.pick)(client, [
|
|
575
|
+
'description',
|
|
576
|
+
'app_type',
|
|
577
|
+
'allowed_origins',
|
|
578
|
+
'web_origins',
|
|
579
|
+
'grant_types',
|
|
580
|
+
'oidc_conformant',
|
|
581
|
+
'organization_discovery_methods',
|
|
582
|
+
'client_metadata',
|
|
583
|
+
'default_organization',
|
|
584
|
+
'require_proof_of_possession',
|
|
585
|
+
'token_quota',
|
|
586
|
+
'skip_non_verifiable_callback_uri_confirmation_prompt',
|
|
587
|
+
'jwt_configuration',
|
|
588
|
+
'refresh_token',
|
|
589
|
+
]);
|
|
590
|
+
}
|
|
591
|
+
async updateClient(clientId, client) {
|
|
592
|
+
// For non-CIMD clients
|
|
593
|
+
if (!this.isCimdClient(client)) {
|
|
594
|
+
return this.client.clients.update(clientId, client);
|
|
595
|
+
}
|
|
596
|
+
const updatePayload = this.getCIMDEditableFields(client);
|
|
597
|
+
const registrationClientId = client.client_id || clientId;
|
|
598
|
+
if (registrationClientId && Object.keys(updatePayload).length > 0) {
|
|
599
|
+
return this.client.clients.update(registrationClientId, updatePayload);
|
|
600
|
+
}
|
|
601
|
+
return client;
|
|
602
|
+
}
|
|
603
|
+
// convert names back to IDs for client reference-based configuration
|
|
604
|
+
async sanitizeMapClientReferences(auth0Client, clientList) {
|
|
605
|
+
const hasExpressConfiguration = clientList.some((client) => client.express_configuration);
|
|
606
|
+
const hasMyOrganizationConfiguration = clientList.some((client) => client.my_organization_configuration);
|
|
607
|
+
if (!hasExpressConfiguration && !hasMyOrganizationConfiguration) {
|
|
460
608
|
return clientList;
|
|
461
609
|
}
|
|
462
610
|
const clientData = await this.getType();
|
|
463
611
|
const connectionProfiles = await (0, connectionProfiles_1.getConnectionProfile)(auth0Client);
|
|
464
612
|
const userAttributeProfiles = await (0, userAttributeProfiles_1.getUserAttributeProfiles)(auth0Client);
|
|
465
613
|
return clientList.map((client) => {
|
|
466
|
-
if (
|
|
614
|
+
if (client.express_configuration) {
|
|
615
|
+
const userAttributeProfileName = client.express_configuration.user_attribute_profile_id;
|
|
616
|
+
if (userAttributeProfileName) {
|
|
617
|
+
const userAttributeProfile = userAttributeProfiles?.find((uap) => uap.name === userAttributeProfileName);
|
|
618
|
+
if (userAttributeProfile?.id) {
|
|
619
|
+
client.express_configuration.user_attribute_profile_id = userAttributeProfile.id;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
const connectionProfileName = client.express_configuration.connection_profile_id;
|
|
623
|
+
if (connectionProfileName) {
|
|
624
|
+
const connectionProfile = connectionProfiles?.find((cp) => cp.name === connectionProfileName);
|
|
625
|
+
if (connectionProfile?.id) {
|
|
626
|
+
client.express_configuration.connection_profile_id = connectionProfile.id;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
const oktaOinClientName = client.express_configuration.okta_oin_client_id;
|
|
630
|
+
if (oktaOinClientName) {
|
|
631
|
+
const oktaOinClient = clientData?.find((c) => c.name === oktaOinClientName);
|
|
632
|
+
if (oktaOinClient?.client_id) {
|
|
633
|
+
client.express_configuration.okta_oin_client_id = oktaOinClient.client_id;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
if (!client.my_organization_configuration) {
|
|
467
638
|
return client;
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
639
|
+
}
|
|
640
|
+
const myOrganizationUserAttributeProfileName = client.my_organization_configuration.user_attribute_profile_id;
|
|
641
|
+
if (myOrganizationUserAttributeProfileName) {
|
|
642
|
+
const userAttributeProfile = userAttributeProfiles?.find((uap) => uap.name === myOrganizationUserAttributeProfileName);
|
|
471
643
|
if (userAttributeProfile?.id) {
|
|
472
|
-
client.
|
|
644
|
+
client.my_organization_configuration.user_attribute_profile_id = userAttributeProfile.id;
|
|
473
645
|
}
|
|
474
646
|
}
|
|
475
|
-
const
|
|
476
|
-
if (
|
|
477
|
-
const connectionProfile = connectionProfiles?.find((cp) => cp.name ===
|
|
647
|
+
const myOrganizationConnectionProfileName = client.my_organization_configuration.connection_profile_id;
|
|
648
|
+
if (myOrganizationConnectionProfileName) {
|
|
649
|
+
const connectionProfile = connectionProfiles?.find((cp) => cp.name === myOrganizationConnectionProfileName);
|
|
478
650
|
if (connectionProfile?.id) {
|
|
479
|
-
client.
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
const oktaOinClientName = client.express_configuration.okta_oin_client_id;
|
|
483
|
-
if (oktaOinClientName) {
|
|
484
|
-
const oktaOinClient = clientData?.find((c) => c.name === oktaOinClientName);
|
|
485
|
-
if (oktaOinClient?.client_id) {
|
|
486
|
-
client.express_configuration.okta_oin_client_id = oktaOinClient.client_id;
|
|
651
|
+
client.my_organization_configuration.connection_profile_id = connectionProfile.id;
|
|
487
652
|
}
|
|
488
653
|
}
|
|
489
654
|
return client;
|
|
@@ -16,10 +16,26 @@ export declare const schema: {
|
|
|
16
16
|
};
|
|
17
17
|
options: {
|
|
18
18
|
type: string;
|
|
19
|
+
additionalProperties: boolean;
|
|
19
20
|
properties: {
|
|
20
21
|
dpop_signing_alg: {
|
|
21
22
|
type: string;
|
|
22
23
|
};
|
|
24
|
+
token_endpoint_auth_signing_alg: {
|
|
25
|
+
type: string;
|
|
26
|
+
enum: ("RS256" | "RS512" | "PS256" | "ES256" | "ES384" | "PS384" | "RS384")[];
|
|
27
|
+
};
|
|
28
|
+
id_token_signed_response_algs: {
|
|
29
|
+
type: string;
|
|
30
|
+
items: {
|
|
31
|
+
type: string;
|
|
32
|
+
enum: ("RS256" | "RS512" | "PS256" | "ES256" | "ES384" | "PS384" | "RS384")[];
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
token_endpoint_jwtca_aud_format: {
|
|
36
|
+
type: string;
|
|
37
|
+
enum: ("issuer" | "token_endpoint")[];
|
|
38
|
+
};
|
|
23
39
|
};
|
|
24
40
|
};
|
|
25
41
|
enabled_clients: {
|
|
@@ -169,6 +185,7 @@ export default class ConnectionsHandler extends DefaultAPIHandler {
|
|
|
169
185
|
} | {
|
|
170
186
|
options?: undefined;
|
|
171
187
|
};
|
|
188
|
+
validate(assets: Assets): Promise<void>;
|
|
172
189
|
/**
|
|
173
190
|
* Retrieves all directory provisioning configurations for all connections.
|
|
174
191
|
* @returns A promise that resolves to the configurations object, or null if not configured/supported
|
|
@@ -195,6 +212,7 @@ export default class ConnectionsHandler extends DefaultAPIHandler {
|
|
|
195
212
|
processConnectionDirectoryProvisioning(changes: CalculatedChanges): Promise<void>;
|
|
196
213
|
getType(): Promise<Asset[] | null>;
|
|
197
214
|
calcChanges(assets: Assets): Promise<CalculatedChanges>;
|
|
215
|
+
dryRunChanges(assets: Assets): Promise<CalculatedChanges>;
|
|
198
216
|
processChanges(assets: Assets): Promise<void>;
|
|
199
217
|
}
|
|
200
218
|
export {};
|
|
@@ -51,14 +51,37 @@ const utils_1 = require("../../utils");
|
|
|
51
51
|
const client_1 = require("../client");
|
|
52
52
|
const scimHandler_1 = __importDefault(require("./scimHandler"));
|
|
53
53
|
const logger_1 = __importDefault(require("../../../logger"));
|
|
54
|
+
const validationError_1 = __importDefault(require("../../validationError"));
|
|
54
55
|
const connectionOptionsSchema = {
|
|
55
56
|
type: 'object',
|
|
57
|
+
additionalProperties: true,
|
|
56
58
|
properties: {
|
|
57
59
|
dpop_signing_alg: {
|
|
58
60
|
type: 'string',
|
|
59
61
|
},
|
|
62
|
+
token_endpoint_auth_signing_alg: {
|
|
63
|
+
type: 'string',
|
|
64
|
+
enum: Object.values(auth0_1.Management.ConnectionTokenEndpointAuthSigningAlgEnum),
|
|
65
|
+
},
|
|
66
|
+
id_token_signed_response_algs: {
|
|
67
|
+
type: 'array',
|
|
68
|
+
items: {
|
|
69
|
+
type: 'string',
|
|
70
|
+
enum: Object.values(auth0_1.Management.ConnectionIdTokenSignedResponseAlgEnum),
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
token_endpoint_jwtca_aud_format: {
|
|
74
|
+
type: 'string',
|
|
75
|
+
enum: Object.values(auth0_1.Management.ConnectionTokenEndpointJwtcaAudFormatEnumOidc),
|
|
76
|
+
},
|
|
60
77
|
},
|
|
61
78
|
};
|
|
79
|
+
const oidcOktaStrategies = new Set(['oidc', 'okta']);
|
|
80
|
+
const oidcOktaOnlyConnectionOptionFields = [
|
|
81
|
+
'token_endpoint_auth_signing_alg',
|
|
82
|
+
'id_token_signed_response_algs',
|
|
83
|
+
'token_endpoint_jwtca_aud_format',
|
|
84
|
+
];
|
|
62
85
|
exports.schema = {
|
|
63
86
|
type: 'array',
|
|
64
87
|
items: {
|
|
@@ -333,6 +356,27 @@ class ConnectionsHandler extends default_1.default {
|
|
|
333
356
|
return {};
|
|
334
357
|
}
|
|
335
358
|
}
|
|
359
|
+
async validate(assets) {
|
|
360
|
+
const { connections } = assets;
|
|
361
|
+
if (!connections) {
|
|
362
|
+
await super.validate(assets);
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
connections.forEach((connection) => {
|
|
366
|
+
if (!connection?.options)
|
|
367
|
+
return;
|
|
368
|
+
const strategy = connection?.strategy ?? 'unknown';
|
|
369
|
+
if (oidcOktaStrategies.has(strategy))
|
|
370
|
+
return;
|
|
371
|
+
const unsupportedFields = oidcOktaOnlyConnectionOptionFields.filter((field) => field in connection.options);
|
|
372
|
+
if (unsupportedFields.length > 0) {
|
|
373
|
+
throw new validationError_1.default(`Connection "${connection.name}": option(s) ${unsupportedFields
|
|
374
|
+
.map((field) => `"${field}"`)
|
|
375
|
+
.join(', ')} are only supported for strategies "oidc" and "okta". Found strategy "${strategy}".`);
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
await super.validate(assets);
|
|
379
|
+
}
|
|
336
380
|
/**
|
|
337
381
|
* Retrieves all directory provisioning configurations for all connections.
|
|
338
382
|
* @returns A promise that resolves to the configurations object, or null if not configured/supported
|
|
@@ -543,11 +587,14 @@ class ConnectionsHandler extends default_1.default {
|
|
|
543
587
|
});
|
|
544
588
|
// Prepare an id map. We'll use this map later to get the `strategy` and SCIM enable status of the connections.
|
|
545
589
|
await this.scimHandler.createIdMap(existingConnections);
|
|
546
|
-
const formatted = connections.map((connection) =>
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
590
|
+
const formatted = connections.map((connection) => {
|
|
591
|
+
const enabledClients = (0, utils_1.getEnabledClients)(assets, connection, existingConnections, clients);
|
|
592
|
+
return {
|
|
593
|
+
...connection,
|
|
594
|
+
...this.getFormattedOptions(connection, clients),
|
|
595
|
+
...(enabledClients !== undefined && { enabled_clients: enabledClients }),
|
|
596
|
+
};
|
|
597
|
+
});
|
|
551
598
|
const proposedChanges = await super.calcChanges({ ...assets, connections: formatted });
|
|
552
599
|
const proposedChangesWithExcludedProperties = (0, exports.addExcludedConnectionPropertiesToChanges)({
|
|
553
600
|
proposedChanges,
|
|
@@ -556,6 +603,40 @@ class ConnectionsHandler extends default_1.default {
|
|
|
556
603
|
});
|
|
557
604
|
return proposedChangesWithExcludedProperties;
|
|
558
605
|
}
|
|
606
|
+
async dryRunChanges(assets) {
|
|
607
|
+
const { connections } = assets;
|
|
608
|
+
if (!connections) {
|
|
609
|
+
return {
|
|
610
|
+
del: [],
|
|
611
|
+
create: [],
|
|
612
|
+
update: [],
|
|
613
|
+
conflicts: [],
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
const clients = await (0, client_1.paginate)(this.client.clients.list, {
|
|
617
|
+
paginate: true,
|
|
618
|
+
include_totals: true,
|
|
619
|
+
});
|
|
620
|
+
const existingConnections = await (0, client_1.paginate)(this.client.connections.list, {
|
|
621
|
+
checkpoint: true,
|
|
622
|
+
include_totals: true,
|
|
623
|
+
});
|
|
624
|
+
await this.scimHandler.createIdMap(existingConnections);
|
|
625
|
+
const formatted = connections.map((connection) => {
|
|
626
|
+
const enabledClients = (0, utils_1.getEnabledClients)(assets, connection, existingConnections, clients);
|
|
627
|
+
return {
|
|
628
|
+
...connection,
|
|
629
|
+
...this.getFormattedOptions(connection, clients),
|
|
630
|
+
...(enabledClients !== undefined && { enabled_clients: enabledClients }),
|
|
631
|
+
};
|
|
632
|
+
});
|
|
633
|
+
const proposedChanges = await super.dryRunChanges({ ...assets, connections: formatted });
|
|
634
|
+
return (0, exports.addExcludedConnectionPropertiesToChanges)({
|
|
635
|
+
proposedChanges,
|
|
636
|
+
existingConnections,
|
|
637
|
+
config: this.config,
|
|
638
|
+
});
|
|
639
|
+
}
|
|
559
640
|
// Run after clients are updated so we can convert all the enabled_clients names to id's
|
|
560
641
|
async processChanges(assets) {
|
|
561
642
|
const { connections } = assets;
|