@boxyhq/saml-jackson 1.2.2 → 1.3.1
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/dist/controller/admin.d.ts +4 -4
- package/dist/controller/admin.js +6 -6
- package/dist/controller/api.d.ts +460 -204
- package/dist/controller/api.js +561 -377
- package/dist/controller/connection/oidc.d.ts +9 -0
- package/dist/controller/connection/oidc.js +145 -0
- package/dist/controller/connection/saml.d.ts +9 -0
- package/dist/controller/connection/saml.js +174 -0
- package/dist/controller/logout.d.ts +3 -3
- package/dist/controller/logout.js +14 -14
- package/dist/controller/oauth.d.ts +26 -8
- package/dist/controller/oauth.js +375 -143
- package/dist/controller/oidc-discovery.js +2 -1
- package/dist/controller/utils.d.ts +10 -2
- package/dist/controller/utils.js +88 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +23 -14
- package/dist/loadConnection.d.ts +3 -0
- package/dist/{read-config.js → loadConnection.js} +13 -12
- package/dist/opentelemetry/metrics.js +12 -12
- package/dist/typings.d.ts +155 -36
- package/package.json +11 -10
- package/dist/read-config.d.ts +0 -3
package/dist/controller/api.js
CHANGED
@@ -31,394 +31,546 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
31
31
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
32
32
|
});
|
33
33
|
};
|
34
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
35
|
-
var t = {};
|
36
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
37
|
-
t[p] = s[p];
|
38
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
39
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
40
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
41
|
-
t[p[i]] = s[p[i]];
|
42
|
-
}
|
43
|
-
return t;
|
44
|
-
};
|
45
34
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
46
35
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
47
36
|
};
|
48
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
49
|
-
exports.
|
50
|
-
const crypto_1 = __importDefault(require("crypto"));
|
38
|
+
exports.ConnectionAPIController = void 0;
|
51
39
|
const dbutils = __importStar(require("../db/utils"));
|
52
40
|
const metrics = __importStar(require("../opentelemetry/metrics"));
|
53
|
-
const saml20_1 = __importDefault(require("@boxyhq/saml20"));
|
54
|
-
const x509_1 = __importDefault(require("../saml/x509"));
|
55
41
|
const error_1 = require("./error");
|
56
42
|
const utils_1 = require("./utils");
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
}
|
61
|
-
|
62
|
-
|
63
|
-
if (redirectUrlList.length > 100) {
|
64
|
-
throw new error_1.JacksonError('Exceeded maximum number of allowed redirect urls', 400);
|
65
|
-
}
|
66
|
-
for (const url of redirectUrlList) {
|
67
|
-
(0, utils_1.validateAbsoluteUrl)(url, 'redirectUrl is invalid');
|
68
|
-
}
|
69
|
-
}
|
70
|
-
if (defaultRedirectUrl) {
|
71
|
-
(0, utils_1.validateAbsoluteUrl)(defaultRedirectUrl, 'defaultRedirectUrl is invalid');
|
72
|
-
}
|
73
|
-
}
|
74
|
-
_validateIdPConfig(body) {
|
75
|
-
const { encodedRawMetadata, rawMetadata, defaultRedirectUrl, redirectUrl, tenant, product, description } = body;
|
76
|
-
if (!rawMetadata && !encodedRawMetadata) {
|
77
|
-
throw new error_1.JacksonError('Please provide rawMetadata or encodedRawMetadata', 400);
|
78
|
-
}
|
79
|
-
if (!defaultRedirectUrl) {
|
80
|
-
throw new error_1.JacksonError('Please provide a defaultRedirectUrl', 400);
|
81
|
-
}
|
82
|
-
if (!redirectUrl) {
|
83
|
-
throw new error_1.JacksonError('Please provide redirectUrl', 400);
|
84
|
-
}
|
85
|
-
if (!tenant) {
|
86
|
-
throw new error_1.JacksonError('Please provide tenant', 400);
|
87
|
-
}
|
88
|
-
if (!product) {
|
89
|
-
throw new error_1.JacksonError('Please provide product', 400);
|
90
|
-
}
|
91
|
-
if (description && description.length > 100) {
|
92
|
-
throw new error_1.JacksonError('Description should not exceed 100 characters', 400);
|
93
|
-
}
|
43
|
+
const oidc_1 = __importDefault(require("./connection/oidc"));
|
44
|
+
const saml_1 = __importDefault(require("./connection/saml"));
|
45
|
+
class ConnectionAPIController {
|
46
|
+
constructor({ connectionStore, opts }) {
|
47
|
+
this.connectionStore = connectionStore;
|
48
|
+
this.opts = opts;
|
94
49
|
}
|
95
50
|
/**
|
96
51
|
* @swagger
|
52
|
+
* definitions:
|
53
|
+
* Connection:
|
54
|
+
* type: object
|
55
|
+
* example:
|
56
|
+
* {
|
57
|
+
* "idpMetadata": {
|
58
|
+
* "sso": {
|
59
|
+
* "postUrl": "https://dev-20901260.okta.com/app/dev-20901260_jacksonnext_1/xxxxxxxxxxxsso/saml",
|
60
|
+
* "redirectUrl": "https://dev-20901260.okta.com/app/dev-20901260_jacksonnext_1/xxxxxxxxxxxsso/saml"
|
61
|
+
* },
|
62
|
+
* "entityID": "http://www.okta.com/xxxxxxxxxxxxx",
|
63
|
+
* "thumbprint": "Eo+eUi3UM3XIMkFFtdVK3yJ5vO9f7YZdasdasdad",
|
64
|
+
* "loginType": "idp",
|
65
|
+
* "provider": "okta.com"
|
66
|
+
* },
|
67
|
+
* "defaultRedirectUrl": "https://hoppscotch.io/",
|
68
|
+
* "redirectUrl": ["https://hoppscotch.io/"],
|
69
|
+
* "tenant": "hoppscotch.io",
|
70
|
+
* "product": "API Engine",
|
71
|
+
* "name": "Hoppscotch-SP",
|
72
|
+
* "description": "SP for hoppscotch.io",
|
73
|
+
* "clientID": "Xq8AJt3yYAxmXizsCWmUBDRiVP1iTC8Y/otnvFIMitk",
|
74
|
+
* "clientSecret": "00e3e11a3426f97d8000000738300009130cd45419c5943",
|
75
|
+
* "certs": {
|
76
|
+
* "publicKey": "-----BEGIN CERTIFICATE-----.......-----END CERTIFICATE-----",
|
77
|
+
* "privateKey": "-----BEGIN PRIVATE KEY-----......-----END PRIVATE KEY-----"
|
78
|
+
* }
|
79
|
+
* }
|
80
|
+
* validationErrorsPost:
|
81
|
+
* description: Please provide rawMetadata or encodedRawMetadata | Please provide a defaultRedirectUrl | Please provide redirectUrl | redirectUrl is invalid | Exceeded maximum number of allowed redirect urls | defaultRedirectUrl is invalid | Please provide tenant | Please provide product | Please provide a friendly name | Description should not exceed 100 characters | Strategy: xxxx not supported | Please provide the clientId from OpenID Provider | Please provide the clientSecret from OpenID Provider | Please provide the discoveryUrl for the OpenID Provider
|
97
82
|
*
|
83
|
+
* parameters:
|
84
|
+
* nameParamPost:
|
85
|
+
* name: name
|
86
|
+
* description: Name/identifier for the connection
|
87
|
+
* type: string
|
88
|
+
* in: formData
|
89
|
+
* descriptionParamPost:
|
90
|
+
* name: description
|
91
|
+
* description: A short description for the connection not more than 100 characters
|
92
|
+
* type: string
|
93
|
+
* in: formData
|
94
|
+
* encodedRawMetadataParamPost:
|
95
|
+
* name: encodedRawMetadata
|
96
|
+
* description: Base64 encoding of the XML metadata
|
97
|
+
* in: formData
|
98
|
+
* type: string
|
99
|
+
* rawMetadataParamPost:
|
100
|
+
* name: rawMetadata
|
101
|
+
* description: Raw XML metadata
|
102
|
+
* in: formData
|
103
|
+
* type: string
|
104
|
+
* defaultRedirectUrlParamPost:
|
105
|
+
* name: defaultRedirectUrl
|
106
|
+
* description: The redirect URL to use in the IdP login flow
|
107
|
+
* in: formData
|
108
|
+
* required: true
|
109
|
+
* type: string
|
110
|
+
* redirectUrlParamPost:
|
111
|
+
* name: redirectUrl
|
112
|
+
* description: JSON encoded array containing a list of allowed redirect URLs
|
113
|
+
* in: formData
|
114
|
+
* required: true
|
115
|
+
* type: string
|
116
|
+
* tenantParamPost:
|
117
|
+
* name: tenant
|
118
|
+
* description: Tenant
|
119
|
+
* in: formData
|
120
|
+
* required: true
|
121
|
+
* type: string
|
122
|
+
* productParamPost:
|
123
|
+
* name: product
|
124
|
+
* description: Product
|
125
|
+
* in: formData
|
126
|
+
* required: true
|
127
|
+
* type: string
|
128
|
+
* oidcDiscoveryUrlPost:
|
129
|
+
* name: oidcDiscoveryUrl
|
130
|
+
* description: well-known URL where the OpenID Provider configuration is exposed
|
131
|
+
* in: formData
|
132
|
+
* type: string
|
133
|
+
* oidcClientIdPost:
|
134
|
+
* name: oidcClientId
|
135
|
+
* description: clientId of the application set up on the OpenID Provider
|
136
|
+
* in: formData
|
137
|
+
* type: string
|
138
|
+
* oidcClientSecretPost:
|
139
|
+
* name: oidcClientSecret
|
140
|
+
* description: clientSecret of the application set up on the OpenID Provider
|
141
|
+
* in: formData
|
142
|
+
* type: string
|
98
143
|
* /api/v1/saml/config:
|
99
144
|
* post:
|
100
|
-
*
|
101
|
-
*
|
102
|
-
*
|
145
|
+
* summary: Create SAML config
|
146
|
+
* operationId: create-saml-config
|
147
|
+
* deprecated: true
|
148
|
+
* tags: [SAML Config - Deprecated]
|
149
|
+
* produces:
|
150
|
+
* - application/json
|
151
|
+
* consumes:
|
152
|
+
* - application/x-www-form-urlencoded
|
153
|
+
* - application/json
|
154
|
+
* parameters:
|
155
|
+
* - $ref: '#/parameters/nameParamPost'
|
156
|
+
* - $ref: '#/parameters/descriptionParamPost'
|
157
|
+
* - $ref: '#/parameters/encodedRawMetadataParamPost'
|
158
|
+
* - $ref: '#/parameters/rawMetadataParamPost'
|
159
|
+
* - $ref: '#/parameters/defaultRedirectUrlParamPost'
|
160
|
+
* - $ref: '#/parameters/redirectUrlParamPost'
|
161
|
+
* - $ref: '#/parameters/tenantParamPost'
|
162
|
+
* - $ref: '#/parameters/productParamPost'
|
163
|
+
* responses:
|
164
|
+
* 200:
|
165
|
+
* description: Success
|
166
|
+
* schema:
|
167
|
+
* $ref: '#/definitions/Connection'
|
168
|
+
* 400:
|
169
|
+
* $ref: '#/definitions/validationErrorsPost'
|
170
|
+
* 401:
|
171
|
+
* description: Unauthorized
|
172
|
+
* 500:
|
173
|
+
* description: Please set OpenID response handler path (oidcPath) on Jackson
|
174
|
+
* /api/v1/connections:
|
175
|
+
* post:
|
176
|
+
* summary: Create SSO connection
|
177
|
+
* operationId: create-sso-connection
|
178
|
+
* tags: [Connections]
|
103
179
|
* produces:
|
104
|
-
*
|
180
|
+
* - application/json
|
105
181
|
* consumes:
|
106
|
-
*
|
182
|
+
* - application/x-www-form-urlencoded
|
183
|
+
* - application/json
|
107
184
|
* parameters:
|
108
|
-
*
|
109
|
-
*
|
110
|
-
*
|
111
|
-
*
|
112
|
-
*
|
113
|
-
*
|
114
|
-
*
|
115
|
-
*
|
116
|
-
*
|
117
|
-
*
|
118
|
-
*
|
119
|
-
* type: string
|
120
|
-
* - name: rawMetadata
|
121
|
-
* description: Raw XML metadata
|
122
|
-
* in: formData
|
123
|
-
* type: string
|
124
|
-
* - name: defaultRedirectUrl
|
125
|
-
* description: The redirect URL to use in the IdP login flow
|
126
|
-
* in: formData
|
127
|
-
* required: true
|
128
|
-
* type: string
|
129
|
-
* - name: redirectUrl
|
130
|
-
* description: JSON encoded array containing a list of allowed redirect URLs
|
131
|
-
* in: formData
|
132
|
-
* required: true
|
133
|
-
* type: string
|
134
|
-
* - name: tenant
|
135
|
-
* description: Tenant
|
136
|
-
* in: formData
|
137
|
-
* required: true
|
138
|
-
* type: string
|
139
|
-
* - name: product
|
140
|
-
* description: Product
|
141
|
-
* in: formData
|
142
|
-
* required: true
|
143
|
-
* type: string
|
185
|
+
* - $ref: '#/parameters/nameParamPost'
|
186
|
+
* - $ref: '#/parameters/descriptionParamPost'
|
187
|
+
* - $ref: '#/parameters/encodedRawMetadataParamPost'
|
188
|
+
* - $ref: '#/parameters/rawMetadataParamPost'
|
189
|
+
* - $ref: '#/parameters/defaultRedirectUrlParamPost'
|
190
|
+
* - $ref: '#/parameters/redirectUrlParamPost'
|
191
|
+
* - $ref: '#/parameters/tenantParamPost'
|
192
|
+
* - $ref: '#/parameters/productParamPost'
|
193
|
+
* - $ref: '#/parameters/oidcDiscoveryUrlPost'
|
194
|
+
* - $ref: '#/parameters/oidcClientIdPost'
|
195
|
+
* - $ref: '#/parameters/oidcClientSecretPost'
|
144
196
|
* responses:
|
145
197
|
* 200:
|
146
198
|
* description: Success
|
147
199
|
* schema:
|
148
|
-
*
|
149
|
-
* example:
|
150
|
-
* {
|
151
|
-
* "idpMetadata": {
|
152
|
-
* "sso": {
|
153
|
-
* "postUrl": "https://dev-20901260.okta.com/app/dev-20901260_jacksonnext_1/xxxxxxxxxxxxx/sso/saml",
|
154
|
-
* "redirectUrl": "https://dev-20901260.okta.com/app/dev-20901260_jacksonnext_1/xxxxxxxxxxxxx/sso/saml"
|
155
|
-
* },
|
156
|
-
* "entityID": "http://www.okta.com/xxxxxxxxxxxxx",
|
157
|
-
* "thumbprint": "Eo+eUi3UM3XIMkFFtdVK3yJ5vO9f7YZdasdasdad",
|
158
|
-
* "loginType": "idp",
|
159
|
-
* "provider": "okta.com"
|
160
|
-
* },
|
161
|
-
* "defaultRedirectUrl": "https://hoppscotch.io/",
|
162
|
-
* "redirectUrl": ["https://hoppscotch.io/"],
|
163
|
-
* "tenant": "hoppscotch.io",
|
164
|
-
* "product": "API Engine",
|
165
|
-
* "name": "Hoppscotch-SP",
|
166
|
-
* "description": "SP for hoppscotch.io",
|
167
|
-
* "clientID": "Xq8AJt3yYAxmXizsCWmUBDRiVP1iTC8Y/otnvFIMitk",
|
168
|
-
* "clientSecret": "00e3e11a3426f97d8000000738300009130cd45419c5943",
|
169
|
-
* "certs": {
|
170
|
-
* "publicKey": "-----BEGIN CERTIFICATE-----.......-----END CERTIFICATE-----",
|
171
|
-
* "privateKey": "-----BEGIN PRIVATE KEY-----......-----END PRIVATE KEY-----"
|
172
|
-
* }
|
173
|
-
* }
|
200
|
+
* $ref: '#/definitions/Connection'
|
174
201
|
* 400:
|
175
|
-
*
|
202
|
+
* $ref: '#/definitions/validationErrorsPost'
|
176
203
|
* 401:
|
177
204
|
* description: Unauthorized
|
178
205
|
*/
|
179
|
-
|
206
|
+
createSAMLConnection(body) {
|
180
207
|
return __awaiter(this, void 0, void 0, function* () {
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
if (!
|
195
|
-
|
196
|
-
}
|
197
|
-
idpMetadata.provider = providerName ? providerName : 'Unknown';
|
198
|
-
const clientID = dbutils.keyDigest(dbutils.keyFromParts(tenant, product, idpMetadata.entityID));
|
199
|
-
let clientSecret;
|
200
|
-
const exists = yield this.configStore.get(clientID);
|
201
|
-
if (exists) {
|
202
|
-
clientSecret = exists.clientSecret;
|
203
|
-
}
|
204
|
-
else {
|
205
|
-
clientSecret = crypto_1.default.randomBytes(24).toString('hex');
|
206
|
-
}
|
207
|
-
const certs = yield x509_1.default.generate();
|
208
|
-
if (!certs) {
|
209
|
-
throw new Error('Error generating x509 certs');
|
208
|
+
metrics.increment('createConnection');
|
209
|
+
return yield saml_1.default.create(body, this.connectionStore);
|
210
|
+
});
|
211
|
+
}
|
212
|
+
// For backwards compatibility
|
213
|
+
config(...args) {
|
214
|
+
return __awaiter(this, void 0, void 0, function* () {
|
215
|
+
return this.createSAMLConnection(...args);
|
216
|
+
});
|
217
|
+
}
|
218
|
+
createOIDCConnection(body) {
|
219
|
+
return __awaiter(this, void 0, void 0, function* () {
|
220
|
+
metrics.increment('createConnection');
|
221
|
+
if (!this.opts.oidcPath) {
|
222
|
+
throw new error_1.JacksonError('Please set OpenID response handler path (oidcPath) on Jackson', 500);
|
210
223
|
}
|
211
|
-
|
212
|
-
idpMetadata,
|
213
|
-
defaultRedirectUrl,
|
214
|
-
redirectUrl: redirectUrlList,
|
215
|
-
tenant,
|
216
|
-
product,
|
217
|
-
name,
|
218
|
-
description,
|
219
|
-
clientID,
|
220
|
-
clientSecret,
|
221
|
-
certs,
|
222
|
-
forceAuthn,
|
223
|
-
};
|
224
|
-
yield this.configStore.put(clientID, record, {
|
225
|
-
// secondary index on entityID
|
226
|
-
name: utils_1.IndexNames.EntityID,
|
227
|
-
value: idpMetadata.entityID,
|
228
|
-
}, {
|
229
|
-
// secondary index on tenant + product
|
230
|
-
name: utils_1.IndexNames.TenantProduct,
|
231
|
-
value: dbutils.keyFromParts(tenant, product),
|
232
|
-
});
|
233
|
-
return record;
|
224
|
+
return yield oidc_1.default.create(body, this.connectionStore);
|
234
225
|
});
|
235
226
|
}
|
236
227
|
/**
|
237
228
|
* @swagger
|
238
|
-
*
|
229
|
+
* definitions:
|
230
|
+
* validationErrorsPatch:
|
231
|
+
* description: Please provide clientID | Please provide clientSecret | clientSecret mismatch | Tenant/Product config mismatch with IdP metadata | Description should not exceed 100 characters| redirectUrl is invalid | Exceeded maximum number of allowed redirect urls | defaultRedirectUrl is invalid | Tenant/Product config mismatch with OIDC Provider metadata
|
232
|
+
* parameters:
|
233
|
+
* clientIDParamPatch:
|
234
|
+
* name: clientID
|
235
|
+
* description: Client ID for the connection
|
236
|
+
* type: string
|
237
|
+
* in: formData
|
238
|
+
* required: true
|
239
|
+
* clientSecretParamPatch:
|
240
|
+
* name: clientSecret
|
241
|
+
* description: Client Secret for the connection
|
242
|
+
* type: string
|
243
|
+
* in: formData
|
244
|
+
* required: true
|
245
|
+
* nameParamPatch:
|
246
|
+
* name: name
|
247
|
+
* description: Name/identifier for the connection
|
248
|
+
* type: string
|
249
|
+
* in: formData
|
250
|
+
* descriptionParamPatch:
|
251
|
+
* name: description
|
252
|
+
* description: A short description for the connection not more than 100 characters
|
253
|
+
* type: string
|
254
|
+
* in: formData
|
255
|
+
* encodedRawMetadataParamPatch:
|
256
|
+
* name: encodedRawMetadata
|
257
|
+
* description: Base64 encoding of the XML metadata
|
258
|
+
* in: formData
|
259
|
+
* type: string
|
260
|
+
* rawMetadataParamPatch:
|
261
|
+
* name: rawMetadata
|
262
|
+
* description: Raw XML metadata
|
263
|
+
* in: formData
|
264
|
+
* type: string
|
265
|
+
* oidcDiscoveryUrlPatch:
|
266
|
+
* name: oidcDiscoveryUrl
|
267
|
+
* description: well-known URL where the OpenID Provider configuration is exposed
|
268
|
+
* in: formData
|
269
|
+
* type: string
|
270
|
+
* oidcClientIdPatch:
|
271
|
+
* name: oidcClientId
|
272
|
+
* description: clientId of the application set up on the OpenID Provider
|
273
|
+
* in: formData
|
274
|
+
* type: string
|
275
|
+
* oidcClientSecretPatch:
|
276
|
+
* name: oidcClientSecret
|
277
|
+
* description: clientSecret of the application set up on the OpenID Provider
|
278
|
+
* in: formData
|
279
|
+
* type: string
|
280
|
+
* defaultRedirectUrlParamPatch:
|
281
|
+
* name: defaultRedirectUrl
|
282
|
+
* description: The redirect URL to use in the IdP login flow
|
283
|
+
* in: formData
|
284
|
+
* type: string
|
285
|
+
* redirectUrlParamPatch:
|
286
|
+
* name: redirectUrl
|
287
|
+
* description: JSON encoded array containing a list of allowed redirect URLs
|
288
|
+
* in: formData
|
289
|
+
* type: string
|
290
|
+
* tenantParamPatch:
|
291
|
+
* name: tenant
|
292
|
+
* description: Tenant
|
293
|
+
* in: formData
|
294
|
+
* required: true
|
295
|
+
* type: string
|
296
|
+
* productParamPatch:
|
297
|
+
* name: product
|
298
|
+
* description: Product
|
299
|
+
* in: formData
|
300
|
+
* required: true
|
301
|
+
* type: string
|
239
302
|
* /api/v1/saml/config:
|
240
303
|
* patch:
|
241
|
-
* summary: Update SAML
|
304
|
+
* summary: Update SAML Config
|
242
305
|
* operationId: update-saml-config
|
243
|
-
* tags: [SAML Config]
|
306
|
+
* tags: [SAML Config - Deprecated]
|
307
|
+
* deprecated: true
|
244
308
|
* consumes:
|
245
309
|
* - application/json
|
246
310
|
* - application/x-www-form-urlencoded
|
247
311
|
* parameters:
|
248
|
-
* -
|
249
|
-
*
|
250
|
-
*
|
251
|
-
*
|
252
|
-
*
|
253
|
-
* -
|
254
|
-
*
|
255
|
-
*
|
256
|
-
*
|
257
|
-
*
|
258
|
-
* - name: name
|
259
|
-
* description: Name/identifier for the config
|
260
|
-
* type: string
|
261
|
-
* in: formData
|
262
|
-
* - name: description
|
263
|
-
* description: A short description for the config not more than 100 characters
|
264
|
-
* type: string
|
265
|
-
* in: formData
|
266
|
-
* - name: encodedRawMetadata
|
267
|
-
* description: Base64 encoding of the XML metadata
|
268
|
-
* in: formData
|
269
|
-
* type: string
|
270
|
-
* - name: rawMetadata
|
271
|
-
* description: Raw XML metadata
|
272
|
-
* in: formData
|
273
|
-
* type: string
|
274
|
-
* - name: defaultRedirectUrl
|
275
|
-
* description: The redirect URL to use in the IdP login flow
|
276
|
-
* in: formData
|
277
|
-
* required: true
|
278
|
-
* type: string
|
279
|
-
* - name: redirectUrl
|
280
|
-
* description: JSON encoded array containing a list of allowed redirect URLs
|
281
|
-
* in: formData
|
282
|
-
* required: true
|
283
|
-
* type: string
|
284
|
-
* - name: tenant
|
285
|
-
* description: Tenant
|
286
|
-
* in: formData
|
287
|
-
* required: true
|
288
|
-
* type: string
|
289
|
-
* - name: product
|
290
|
-
* description: Product
|
291
|
-
* in: formData
|
292
|
-
* required: true
|
293
|
-
* type: string
|
312
|
+
* - $ref: '#/parameters/clientIDParamPatch'
|
313
|
+
* - $ref: '#/parameters/clientSecretParamPatch'
|
314
|
+
* - $ref: '#/parameters/nameParamPatch'
|
315
|
+
* - $ref: '#/parameters/descriptionParamPatch'
|
316
|
+
* - $ref: '#/parameters/encodedRawMetadataParamPatch'
|
317
|
+
* - $ref: '#/parameters/rawMetadataParamPatch'
|
318
|
+
* - $ref: '#/parameters/defaultRedirectUrlParamPatch'
|
319
|
+
* - $ref: '#/parameters/redirectUrlParamPatch'
|
320
|
+
* - $ref: '#/parameters/tenantParamPatch'
|
321
|
+
* - $ref: '#/parameters/productParamPatch'
|
294
322
|
* responses:
|
295
323
|
* 204:
|
296
324
|
* description: Success
|
297
325
|
* 400:
|
298
|
-
*
|
326
|
+
* $ref: '#/definitions/validationErrorsPatch'
|
299
327
|
* 401:
|
300
328
|
* description: Unauthorized
|
329
|
+
* /api/v1/connections:
|
330
|
+
* patch:
|
331
|
+
* summary: Update SSO Connection
|
332
|
+
* operationId: update-sso-connection
|
333
|
+
* tags: [Connections]
|
334
|
+
* consumes:
|
335
|
+
* - application/json
|
336
|
+
* - application/x-www-form-urlencoded
|
337
|
+
* parameters:
|
338
|
+
* - $ref: '#/parameters/clientIDParamPatch'
|
339
|
+
* - $ref: '#/parameters/clientSecretParamPatch'
|
340
|
+
* - $ref: '#/parameters/nameParamPatch'
|
341
|
+
* - $ref: '#/parameters/descriptionParamPatch'
|
342
|
+
* - $ref: '#/parameters/encodedRawMetadataParamPatch'
|
343
|
+
* - $ref: '#/parameters/rawMetadataParamPatch'
|
344
|
+
* - $ref: '#/parameters/oidcDiscoveryUrlPatch'
|
345
|
+
* - $ref: '#/parameters/oidcClientIdPatch'
|
346
|
+
* - $ref: '#/parameters/oidcClientSecretPatch'
|
347
|
+
* - $ref: '#/parameters/defaultRedirectUrlParamPatch'
|
348
|
+
* - $ref: '#/parameters/redirectUrlParamPatch'
|
349
|
+
* - $ref: '#/parameters/tenantParamPatch'
|
350
|
+
* - $ref: '#/parameters/productParamPatch'
|
351
|
+
* responses:
|
352
|
+
* 204:
|
353
|
+
* description: Success
|
354
|
+
* 400:
|
355
|
+
* $ref: '#/definitions/validationErrorsPatch'
|
356
|
+
* 401:
|
357
|
+
* description: Unauthorized
|
358
|
+
* 500:
|
359
|
+
* description: Please set OpenID response handler path (oidcPath) on Jackson
|
301
360
|
*/
|
302
|
-
|
361
|
+
updateSAMLConnection(body) {
|
303
362
|
return __awaiter(this, void 0, void 0, function* () {
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
this._validateRedirectUrl({ defaultRedirectUrl, redirectUrlList });
|
318
|
-
const _currentConfig = yield this.getConfig(clientInfo);
|
319
|
-
if (_currentConfig.clientSecret !== (clientInfo === null || clientInfo === void 0 ? void 0 : clientInfo.clientSecret)) {
|
320
|
-
throw new error_1.JacksonError('clientSecret mismatch', 400);
|
321
|
-
}
|
322
|
-
let metaData = rawMetadata;
|
323
|
-
if (encodedRawMetadata) {
|
324
|
-
metaData = Buffer.from(encodedRawMetadata, 'base64').toString();
|
363
|
+
yield saml_1.default.update(body, this.connectionStore, this.getConnections.bind(this));
|
364
|
+
});
|
365
|
+
}
|
366
|
+
// For backwards compatibility
|
367
|
+
updateConfig(...args) {
|
368
|
+
return __awaiter(this, void 0, void 0, function* () {
|
369
|
+
yield this.updateSAMLConnection(...args);
|
370
|
+
});
|
371
|
+
}
|
372
|
+
updateOIDCConnection(body) {
|
373
|
+
return __awaiter(this, void 0, void 0, function* () {
|
374
|
+
if (!this.opts.oidcPath) {
|
375
|
+
throw new error_1.JacksonError('Please set OpenID response handler path (oidcPath) on Jackson', 500);
|
325
376
|
}
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
377
|
+
yield oidc_1.default.update(body, this.connectionStore, this.getConnections.bind(this));
|
378
|
+
});
|
379
|
+
}
|
380
|
+
/**
|
381
|
+
* @swagger
|
382
|
+
* parameters:
|
383
|
+
* tenantParamGet:
|
384
|
+
* in: query
|
385
|
+
* name: tenant
|
386
|
+
* type: string
|
387
|
+
* description: Tenant
|
388
|
+
* productParamGet:
|
389
|
+
* in: query
|
390
|
+
* name: product
|
391
|
+
* type: string
|
392
|
+
* description: Product
|
393
|
+
* clientIDParamGet:
|
394
|
+
* in: query
|
395
|
+
* name: clientID
|
396
|
+
* type: string
|
397
|
+
* description: Client ID
|
398
|
+
* strategyParamGet:
|
399
|
+
* in: query
|
400
|
+
* name: strategy
|
401
|
+
* type: string
|
402
|
+
* description: Strategy which can help to filter connections with tenant/product query
|
403
|
+
* definitions:
|
404
|
+
* Connection:
|
405
|
+
* type: object
|
406
|
+
* properties:
|
407
|
+
* clientID:
|
408
|
+
* type: string
|
409
|
+
* description: Connection clientID
|
410
|
+
* clientSecret:
|
411
|
+
* type: string
|
412
|
+
* description: Connection clientSecret
|
413
|
+
* name:
|
414
|
+
* type: string
|
415
|
+
* description: Connection name
|
416
|
+
* description:
|
417
|
+
* type: string
|
418
|
+
* description: Connection description
|
419
|
+
* redirectUrl:
|
420
|
+
* type: string
|
421
|
+
* description: A list of allowed redirect URLs
|
422
|
+
* defaultRedirectUrl:
|
423
|
+
* type: string
|
424
|
+
* description: The redirect URL to use in the IdP login flow
|
425
|
+
* tenant:
|
426
|
+
* type: string
|
427
|
+
* description: Connection tenant
|
428
|
+
* product:
|
429
|
+
* type: string
|
430
|
+
* description: Connection product
|
431
|
+
* idpMetadata:
|
432
|
+
* type: object
|
433
|
+
* description: SAML IdP metadata
|
434
|
+
* certs:
|
435
|
+
* type: object
|
436
|
+
* description: Certs generated for SAML connection
|
437
|
+
* oidcProvider:
|
438
|
+
* type: object
|
439
|
+
* description: OIDC IdP metadata
|
440
|
+
* responses:
|
441
|
+
* '200Get':
|
442
|
+
* description: Success
|
443
|
+
* schema:
|
444
|
+
* type: array
|
445
|
+
* items:
|
446
|
+
* $ref: '#/definitions/Connection'
|
447
|
+
* '400Get':
|
448
|
+
* description: Please provide `clientID` or `tenant` and `product`.
|
449
|
+
* '401Get':
|
450
|
+
* description: Unauthorized
|
451
|
+
* /api/v1/connections:
|
452
|
+
* get:
|
453
|
+
* summary: Get SSO Connections
|
454
|
+
* parameters:
|
455
|
+
* - $ref: '#/parameters/tenantParamGet'
|
456
|
+
* - $ref: '#/parameters/productParamGet'
|
457
|
+
* - $ref: '#/parameters/clientIDParamGet'
|
458
|
+
* - $ref: '#/parameters/strategyParamGet'
|
459
|
+
* operationId: get-connections
|
460
|
+
* tags: [Connections]
|
461
|
+
* responses:
|
462
|
+
* '200':
|
463
|
+
* $ref: '#/responses/200Get'
|
464
|
+
* '400':
|
465
|
+
* $ref: '#/responses/400Get'
|
466
|
+
* '401':
|
467
|
+
* $ref: '#/responses/401Get'
|
468
|
+
*/
|
469
|
+
getConnections(body) {
|
470
|
+
return __awaiter(this, void 0, void 0, function* () {
|
471
|
+
const clientID = 'clientID' in body ? body.clientID : undefined;
|
472
|
+
const tenant = 'tenant' in body ? body.tenant : undefined;
|
473
|
+
const product = 'product' in body ? body.product : undefined;
|
474
|
+
const strategy = 'strategy' in body ? body.strategy : undefined;
|
475
|
+
metrics.increment('getConnections');
|
476
|
+
if (clientID) {
|
477
|
+
const connection = yield this.connectionStore.get(clientID);
|
478
|
+
if (!connection || typeof connection !== 'object') {
|
479
|
+
return [];
|
333
480
|
}
|
334
|
-
|
481
|
+
return [connection];
|
335
482
|
}
|
336
|
-
if (
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
483
|
+
if (tenant && product) {
|
484
|
+
const connections = yield this.connectionStore.getByIndex({
|
485
|
+
name: utils_1.IndexNames.TenantProduct,
|
486
|
+
value: dbutils.keyFromParts(tenant, product),
|
487
|
+
});
|
488
|
+
if (!connections || !connections.length) {
|
489
|
+
return [];
|
490
|
+
}
|
491
|
+
// filter if strategy is passed
|
492
|
+
const filteredConnections = strategy
|
493
|
+
? connections.filter((connection) => {
|
494
|
+
if (strategy === 'saml') {
|
495
|
+
if (connection.idpMetadata) {
|
496
|
+
return true;
|
497
|
+
}
|
498
|
+
}
|
499
|
+
if (strategy === 'oidc') {
|
500
|
+
if (connection.oidcProvider) {
|
501
|
+
return true;
|
502
|
+
}
|
503
|
+
}
|
504
|
+
return false;
|
505
|
+
})
|
506
|
+
: connections;
|
507
|
+
if (!filteredConnections.length) {
|
508
|
+
return [];
|
341
509
|
}
|
510
|
+
return filteredConnections;
|
342
511
|
}
|
343
|
-
|
344
|
-
yield this.configStore.put(clientInfo === null || clientInfo === void 0 ? void 0 : clientInfo.clientID, record, {
|
345
|
-
// secondary index on entityID
|
346
|
-
name: utils_1.IndexNames.EntityID,
|
347
|
-
value: _currentConfig.idpMetadata.entityID,
|
348
|
-
}, {
|
349
|
-
// secondary index on tenant + product
|
350
|
-
name: utils_1.IndexNames.TenantProduct,
|
351
|
-
value: dbutils.keyFromParts(_currentConfig.tenant, _currentConfig.product),
|
352
|
-
});
|
512
|
+
throw new error_1.JacksonError('Please provide `clientID` or `tenant` and `product`.', 400);
|
353
513
|
});
|
354
514
|
}
|
355
515
|
/**
|
356
516
|
* @swagger
|
357
|
-
*
|
358
517
|
* /api/v1/saml/config:
|
359
518
|
* get:
|
360
|
-
* summary: Get SAML
|
519
|
+
* summary: Get SAML Config
|
361
520
|
* operationId: get-saml-config
|
362
|
-
* tags:
|
363
|
-
*
|
521
|
+
* tags: [SAML Config - Deprecated]
|
522
|
+
* deprecated: true
|
364
523
|
* parameters:
|
365
|
-
* -
|
366
|
-
*
|
367
|
-
*
|
368
|
-
* description: Tenant
|
369
|
-
* - in: query
|
370
|
-
* name: product
|
371
|
-
* type: string
|
372
|
-
* description: Product
|
373
|
-
* - in: query
|
374
|
-
* name: clientID
|
375
|
-
* type: string
|
376
|
-
* description: Client ID
|
524
|
+
* - $ref: '#/parameters/tenantParamGet'
|
525
|
+
* - $ref: '#/parameters/productParamGet'
|
526
|
+
* - $ref: '#/parameters/clientIDParamGet'
|
377
527
|
* responses:
|
378
|
-
*
|
528
|
+
* '200':
|
379
529
|
* description: Success
|
380
530
|
* schema:
|
381
531
|
* type: object
|
382
532
|
* example:
|
383
533
|
* {
|
384
|
-
*
|
385
|
-
*
|
386
|
-
*
|
387
|
-
*
|
388
|
-
*
|
389
|
-
*
|
390
|
-
*
|
391
|
-
*
|
392
|
-
*
|
393
|
-
*
|
394
|
-
*
|
395
|
-
*
|
396
|
-
*
|
397
|
-
*
|
398
|
-
*
|
399
|
-
*
|
400
|
-
*
|
401
|
-
*
|
402
|
-
*
|
403
|
-
*
|
404
|
-
*
|
405
|
-
*
|
406
|
-
*
|
407
|
-
*
|
408
|
-
*
|
409
|
-
*
|
410
|
-
*
|
534
|
+
* "idpMetadata": {
|
535
|
+
* "sso": {
|
536
|
+
* "postUrl": "https://dev-20901260.okta.com/app/dev-20901260_jacksonnext_1/xxxxxxxxxxxxx/sso/saml",
|
537
|
+
* "redirectUrl": "https://dev-20901260.okta.com/app/dev-20901260_jacksonnext_1/xxxxxxxxxxxxx/sso/saml"
|
538
|
+
* },
|
539
|
+
* "entityID": "http://www.okta.com/xxxxxxxxxxxxx",
|
540
|
+
* "thumbprint": "Eo+eUi3UM3XIMkFFtdVK3yJ5vO9f7YZdasdasdad",
|
541
|
+
* "loginType": "idp",
|
542
|
+
* "provider": "okta.com"
|
543
|
+
* },
|
544
|
+
* "defaultRedirectUrl": "https://hoppscotch.io/",
|
545
|
+
* "redirectUrl": ["https://hoppscotch.io/"],
|
546
|
+
* "tenant": "hoppscotch.io",
|
547
|
+
* "product": "API Engine",
|
548
|
+
* "name": "Hoppscotch-SP",
|
549
|
+
* "description": "SP for hoppscotch.io",
|
550
|
+
* "clientID": "Xq8AJt3yYAxmXizsCWmUBDRiVP1iTC8Y/otnvFIMitk",
|
551
|
+
* "clientSecret": "00e3e11a3426f97d8000000738300009130cd45419c5943",
|
552
|
+
* "certs": {
|
553
|
+
* "publicKey": "-----BEGIN CERTIFICATE-----.......-----END CERTIFICATE-----",
|
554
|
+
* "privateKey": "-----BEGIN PRIVATE KEY-----......-----END PRIVATE KEY-----"
|
555
|
+
* }
|
556
|
+
* }
|
557
|
+
* '400':
|
558
|
+
* $ref: '#/responses/400Get'
|
559
|
+
* '401':
|
560
|
+
* $ref: '#/responses/401Get'
|
411
561
|
*/
|
412
562
|
getConfig(body) {
|
413
563
|
return __awaiter(this, void 0, void 0, function* () {
|
414
|
-
const
|
415
|
-
|
564
|
+
const clientID = 'clientID' in body ? body.clientID : undefined;
|
565
|
+
const tenant = 'tenant' in body ? body.tenant : undefined;
|
566
|
+
const product = 'product' in body ? body.product : undefined;
|
567
|
+
metrics.increment('getConnections');
|
416
568
|
if (clientID) {
|
417
|
-
const samlConfig = yield this.
|
569
|
+
const samlConfig = yield this.connectionStore.get(clientID);
|
418
570
|
return samlConfig || {};
|
419
571
|
}
|
420
572
|
if (tenant && product) {
|
421
|
-
const samlConfigs = yield this.
|
573
|
+
const samlConfigs = yield this.connectionStore.getByIndex({
|
422
574
|
name: utils_1.IndexNames.TenantProduct,
|
423
575
|
value: dbutils.keyFromParts(tenant, product),
|
424
576
|
});
|
@@ -432,52 +584,90 @@ class APIController {
|
|
432
584
|
}
|
433
585
|
/**
|
434
586
|
* @swagger
|
587
|
+
* parameters:
|
588
|
+
* clientIDDel:
|
589
|
+
* name: clientID
|
590
|
+
* in: formData
|
591
|
+
* type: string
|
592
|
+
* description: Client ID
|
593
|
+
* clientSecretDel:
|
594
|
+
* name: clientSecret
|
595
|
+
* in: formData
|
596
|
+
* type: string
|
597
|
+
* description: Client Secret
|
598
|
+
* tenantDel:
|
599
|
+
* name: tenant
|
600
|
+
* in: formData
|
601
|
+
* type: string
|
602
|
+
* description: Tenant
|
603
|
+
* productDel:
|
604
|
+
* name: product
|
605
|
+
* in: formData
|
606
|
+
* type: string
|
607
|
+
* description: Product
|
608
|
+
* strategyDel:
|
609
|
+
* name: strategy
|
610
|
+
* in: formData
|
611
|
+
* type: string
|
612
|
+
* description: Strategy which can help to filter connections with tenant/product query
|
613
|
+
* /api/v1/connections:
|
614
|
+
* delete:
|
615
|
+
* parameters:
|
616
|
+
* - $ref: '#/parameters/clientIDDel'
|
617
|
+
* - $ref: '#/parameters/clientSecretDel'
|
618
|
+
* - $ref: '#/parameters/tenantDel'
|
619
|
+
* - $ref: '#/parameters/productDel'
|
620
|
+
* - $ref: '#/parameters/strategyDel'
|
621
|
+
* summary: Delete SSO Connections
|
622
|
+
* operationId: delete-sso-connection
|
623
|
+
* tags: [Connections]
|
624
|
+
* consumes:
|
625
|
+
* - application/x-www-form-urlencoded
|
626
|
+
* - application/json
|
627
|
+
* responses:
|
628
|
+
* '200':
|
629
|
+
* description: Success
|
630
|
+
* '400':
|
631
|
+
* description: clientSecret mismatch | Please provide `clientID` and `clientSecret` or `tenant` and `product`.
|
632
|
+
* '401':
|
633
|
+
* description: Unauthorized
|
435
634
|
* /api/v1/saml/config:
|
436
635
|
* delete:
|
437
|
-
* summary: Delete SAML
|
636
|
+
* summary: Delete SAML Config
|
438
637
|
* operationId: delete-saml-config
|
439
|
-
* tags:
|
440
|
-
*
|
638
|
+
* tags: [SAML Config - Deprecated]
|
639
|
+
* deprecated: true
|
441
640
|
* consumes:
|
442
641
|
* - application/x-www-form-urlencoded
|
642
|
+
* - application/json
|
443
643
|
* parameters:
|
444
|
-
*
|
445
|
-
*
|
446
|
-
*
|
447
|
-
*
|
448
|
-
* description: Client ID
|
449
|
-
* - name: clientSecret
|
450
|
-
* in: formData
|
451
|
-
* type: string
|
452
|
-
* required: true
|
453
|
-
* description: Client Secret
|
454
|
-
* - name: tenant
|
455
|
-
* in: formData
|
456
|
-
* type: string
|
457
|
-
* description: Tenant
|
458
|
-
* - name: product
|
459
|
-
* in: formData
|
460
|
-
* type: string
|
461
|
-
* description: Product
|
644
|
+
* - $ref: '#/parameters/clientIDDel'
|
645
|
+
* - $ref: '#/parameters/clientSecretDel'
|
646
|
+
* - $ref: '#/parameters/tenantDel'
|
647
|
+
* - $ref: '#/parameters/productDel'
|
462
648
|
* responses:
|
463
649
|
* '200':
|
464
650
|
* description: Success
|
465
651
|
* '400':
|
466
|
-
* description: clientSecret mismatch | Please provide `clientID` and `clientSecret` or `tenant` and `product`.
|
652
|
+
* description: clientSecret mismatch | Please provide `clientID` and `clientSecret` or `tenant` and `product`.
|
467
653
|
* '401':
|
468
654
|
* description: Unauthorized
|
469
655
|
*/
|
470
|
-
|
656
|
+
deleteConnections(body) {
|
471
657
|
return __awaiter(this, void 0, void 0, function* () {
|
472
|
-
const
|
473
|
-
|
658
|
+
const clientID = 'clientID' in body ? body.clientID : undefined;
|
659
|
+
const clientSecret = 'clientSecret' in body ? body.clientSecret : undefined;
|
660
|
+
const tenant = 'tenant' in body ? body.tenant : undefined;
|
661
|
+
const product = 'product' in body ? body.product : undefined;
|
662
|
+
const strategy = 'strategy' in body ? body.strategy : undefined;
|
663
|
+
metrics.increment('deleteConnections');
|
474
664
|
if (clientID && clientSecret) {
|
475
|
-
const
|
476
|
-
if (!
|
665
|
+
const connection = yield this.connectionStore.get(clientID);
|
666
|
+
if (!connection) {
|
477
667
|
return;
|
478
668
|
}
|
479
|
-
if (
|
480
|
-
yield this.
|
669
|
+
if (connection.clientSecret === clientSecret) {
|
670
|
+
yield this.connectionStore.delete(clientID);
|
481
671
|
}
|
482
672
|
else {
|
483
673
|
throw new error_1.JacksonError('clientSecret mismatch', 400);
|
@@ -485,47 +675,41 @@ class APIController {
|
|
485
675
|
return;
|
486
676
|
}
|
487
677
|
if (tenant && product) {
|
488
|
-
const
|
678
|
+
const connections = yield this.connectionStore.getByIndex({
|
489
679
|
name: utils_1.IndexNames.TenantProduct,
|
490
680
|
value: dbutils.keyFromParts(tenant, product),
|
491
681
|
});
|
492
|
-
if (!
|
682
|
+
if (!connections || !connections.length) {
|
493
683
|
return;
|
494
684
|
}
|
495
|
-
|
496
|
-
|
685
|
+
// filter if strategy is passed
|
686
|
+
const filteredConnections = strategy
|
687
|
+
? connections.filter((connection) => {
|
688
|
+
if (strategy === 'saml') {
|
689
|
+
if (connection.idpMetadata) {
|
690
|
+
return true;
|
691
|
+
}
|
692
|
+
}
|
693
|
+
if (strategy === 'oidc') {
|
694
|
+
if (connection.oidcProvider) {
|
695
|
+
return true;
|
696
|
+
}
|
697
|
+
}
|
698
|
+
return false;
|
699
|
+
})
|
700
|
+
: connections;
|
701
|
+
for (const conf of filteredConnections) {
|
702
|
+
yield this.connectionStore.delete(conf.clientID);
|
497
703
|
}
|
498
704
|
return;
|
499
705
|
}
|
500
706
|
throw new error_1.JacksonError('Please provide `clientID` and `clientSecret` or `tenant` and `product`.', 400);
|
501
707
|
});
|
502
708
|
}
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
const pUrl = new URL(url);
|
508
|
-
if (pUrl.hostname.startsWith('www.')) {
|
509
|
-
return pUrl.hostname.substring(4);
|
510
|
-
}
|
511
|
-
return pUrl.hostname;
|
512
|
-
}
|
513
|
-
catch (err) {
|
514
|
-
return null;
|
515
|
-
}
|
516
|
-
};
|
517
|
-
const extractRedirectUrls = (urls) => {
|
518
|
-
if (!urls) {
|
519
|
-
return [];
|
520
|
-
}
|
521
|
-
if (typeof urls === 'string') {
|
522
|
-
if (urls.startsWith('[')) {
|
523
|
-
// redirectUrl is a stringified array
|
524
|
-
return JSON.parse(urls);
|
525
|
-
}
|
526
|
-
// redirectUrl is a single URL
|
527
|
-
return [urls];
|
709
|
+
deleteConfig(body) {
|
710
|
+
return __awaiter(this, void 0, void 0, function* () {
|
711
|
+
yield this.deleteConnections(Object.assign(Object.assign({}, body), { strategy: 'saml' }));
|
712
|
+
});
|
528
713
|
}
|
529
|
-
|
530
|
-
|
531
|
-
};
|
714
|
+
}
|
715
|
+
exports.ConnectionAPIController = ConnectionAPIController;
|