mirror of https://github.com/boxyhq/jackson.git
727 lines
24 KiB
TypeScript
727 lines
24 KiB
TypeScript
import * as dbutils from '../db/utils';
|
|
import * as metrics from '../opentelemetry/metrics';
|
|
import {
|
|
GetConfigQuery,
|
|
GetConnectionsQuery,
|
|
DelConnectionsQuery,
|
|
IConnectionAPIController,
|
|
Storable,
|
|
SAMLSSOConnectionWithEncodedMetadata,
|
|
SAMLSSOConnectionWithRawMetadata,
|
|
OIDCSSOConnection,
|
|
JacksonOption,
|
|
SAMLSSORecord,
|
|
OIDCSSORecord,
|
|
} from '../typings';
|
|
import { JacksonError } from './error';
|
|
import { IndexNames } from './utils';
|
|
import oidcConnection from './connection/oidc';
|
|
import samlConnection from './connection/saml';
|
|
|
|
export class ConnectionAPIController implements IConnectionAPIController {
|
|
private connectionStore: Storable;
|
|
private opts: JacksonOption;
|
|
|
|
constructor({ connectionStore, opts }) {
|
|
this.connectionStore = connectionStore;
|
|
this.opts = opts;
|
|
}
|
|
|
|
/**
|
|
* @swagger
|
|
* definitions:
|
|
* Connection:
|
|
* type: object
|
|
* example:
|
|
* {
|
|
* "idpMetadata": {
|
|
* "sso": {
|
|
* "postUrl": "https://dev-20901260.okta.com/app/dev-20901260_jacksonnext_1/xxxxxxxxxxxsso/saml",
|
|
* "redirectUrl": "https://dev-20901260.okta.com/app/dev-20901260_jacksonnext_1/xxxxxxxxxxxsso/saml"
|
|
* },
|
|
* "entityID": "http://www.okta.com/xxxxxxxxxxxxx",
|
|
* "thumbprint": "Eo+eUi3UM3XIMkFFtdVK3yJ5vO9f7YZdasdasdad",
|
|
* "loginType": "idp",
|
|
* "provider": "okta.com"
|
|
* },
|
|
* "defaultRedirectUrl": "https://hoppscotch.io/",
|
|
* "redirectUrl": ["https://hoppscotch.io/"],
|
|
* "tenant": "hoppscotch.io",
|
|
* "product": "API Engine",
|
|
* "name": "Hoppscotch-SP",
|
|
* "description": "SP for hoppscotch.io",
|
|
* "clientID": "Xq8AJt3yYAxmXizsCWmUBDRiVP1iTC8Y/otnvFIMitk",
|
|
* "clientSecret": "00e3e11a3426f97d8000000738300009130cd45419c5943",
|
|
* "certs": {
|
|
* "publicKey": "-----BEGIN CERTIFICATE-----.......-----END CERTIFICATE-----",
|
|
* "privateKey": "-----BEGIN PRIVATE KEY-----......-----END PRIVATE KEY-----"
|
|
* }
|
|
* }
|
|
* validationErrorsPost:
|
|
* 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
|
|
*
|
|
* parameters:
|
|
* nameParamPost:
|
|
* name: name
|
|
* description: Name/identifier for the connection
|
|
* type: string
|
|
* in: formData
|
|
* descriptionParamPost:
|
|
* name: description
|
|
* description: A short description for the connection not more than 100 characters
|
|
* type: string
|
|
* in: formData
|
|
* encodedRawMetadataParamPost:
|
|
* name: encodedRawMetadata
|
|
* description: Base64 encoding of the XML metadata
|
|
* in: formData
|
|
* type: string
|
|
* rawMetadataParamPost:
|
|
* name: rawMetadata
|
|
* description: Raw XML metadata
|
|
* in: formData
|
|
* type: string
|
|
* defaultRedirectUrlParamPost:
|
|
* name: defaultRedirectUrl
|
|
* description: The redirect URL to use in the IdP login flow
|
|
* in: formData
|
|
* required: true
|
|
* type: string
|
|
* redirectUrlParamPost:
|
|
* name: redirectUrl
|
|
* description: JSON encoded array containing a list of allowed redirect URLs
|
|
* in: formData
|
|
* required: true
|
|
* type: string
|
|
* tenantParamPost:
|
|
* name: tenant
|
|
* description: Tenant
|
|
* in: formData
|
|
* required: true
|
|
* type: string
|
|
* productParamPost:
|
|
* name: product
|
|
* description: Product
|
|
* in: formData
|
|
* required: true
|
|
* type: string
|
|
* oidcDiscoveryUrlPost:
|
|
* name: oidcDiscoveryUrl
|
|
* description: well-known URL where the OpenID Provider configuration is exposed
|
|
* in: formData
|
|
* type: string
|
|
* oidcClientIdPost:
|
|
* name: oidcClientId
|
|
* description: clientId of the application set up on the OpenID Provider
|
|
* in: formData
|
|
* type: string
|
|
* oidcClientSecretPost:
|
|
* name: oidcClientSecret
|
|
* description: clientSecret of the application set up on the OpenID Provider
|
|
* in: formData
|
|
* type: string
|
|
* /api/v1/saml/config:
|
|
* post:
|
|
* summary: Create SAML config
|
|
* operationId: create-saml-config
|
|
* deprecated: true
|
|
* tags: [SAML Config - Deprecated]
|
|
* produces:
|
|
* - application/json
|
|
* consumes:
|
|
* - application/x-www-form-urlencoded
|
|
* - application/json
|
|
* parameters:
|
|
* - $ref: '#/parameters/nameParamPost'
|
|
* - $ref: '#/parameters/descriptionParamPost'
|
|
* - $ref: '#/parameters/encodedRawMetadataParamPost'
|
|
* - $ref: '#/parameters/rawMetadataParamPost'
|
|
* - $ref: '#/parameters/defaultRedirectUrlParamPost'
|
|
* - $ref: '#/parameters/redirectUrlParamPost'
|
|
* - $ref: '#/parameters/tenantParamPost'
|
|
* - $ref: '#/parameters/productParamPost'
|
|
* responses:
|
|
* 200:
|
|
* description: Success
|
|
* schema:
|
|
* $ref: '#/definitions/Connection'
|
|
* 400:
|
|
* $ref: '#/definitions/validationErrorsPost'
|
|
* 401:
|
|
* description: Unauthorized
|
|
* 500:
|
|
* description: Please set OpenID response handler path (oidcPath) on Jackson
|
|
* /api/v1/connections:
|
|
* post:
|
|
* summary: Create SSO connection
|
|
* operationId: create-sso-connection
|
|
* tags: [Connections]
|
|
* produces:
|
|
* - application/json
|
|
* consumes:
|
|
* - application/x-www-form-urlencoded
|
|
* - application/json
|
|
* parameters:
|
|
* - $ref: '#/parameters/nameParamPost'
|
|
* - $ref: '#/parameters/descriptionParamPost'
|
|
* - $ref: '#/parameters/encodedRawMetadataParamPost'
|
|
* - $ref: '#/parameters/rawMetadataParamPost'
|
|
* - $ref: '#/parameters/defaultRedirectUrlParamPost'
|
|
* - $ref: '#/parameters/redirectUrlParamPost'
|
|
* - $ref: '#/parameters/tenantParamPost'
|
|
* - $ref: '#/parameters/productParamPost'
|
|
* - $ref: '#/parameters/oidcDiscoveryUrlPost'
|
|
* - $ref: '#/parameters/oidcClientIdPost'
|
|
* - $ref: '#/parameters/oidcClientSecretPost'
|
|
* responses:
|
|
* 200:
|
|
* description: Success
|
|
* schema:
|
|
* $ref: '#/definitions/Connection'
|
|
* 400:
|
|
* $ref: '#/definitions/validationErrorsPost'
|
|
* 401:
|
|
* description: Unauthorized
|
|
*/
|
|
public async createSAMLConnection(
|
|
body: SAMLSSOConnectionWithEncodedMetadata | SAMLSSOConnectionWithRawMetadata
|
|
): Promise<SAMLSSORecord> {
|
|
metrics.increment('createConnection');
|
|
|
|
return await samlConnection.create(body, this.connectionStore);
|
|
}
|
|
|
|
// For backwards compatibility
|
|
public async config(
|
|
...args: Parameters<ConnectionAPIController['createSAMLConnection']>
|
|
): Promise<SAMLSSORecord> {
|
|
return this.createSAMLConnection(...args);
|
|
}
|
|
|
|
public async createOIDCConnection(body: OIDCSSOConnection): Promise<OIDCSSORecord> {
|
|
metrics.increment('createConnection');
|
|
|
|
if (!this.opts.oidcPath) {
|
|
throw new JacksonError('Please set OpenID response handler path (oidcPath) on Jackson', 500);
|
|
}
|
|
|
|
return await oidcConnection.create(body, this.connectionStore);
|
|
}
|
|
|
|
/**
|
|
* @swagger
|
|
* definitions:
|
|
* validationErrorsPatch:
|
|
* 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
|
|
* parameters:
|
|
* clientIDParamPatch:
|
|
* name: clientID
|
|
* description: Client ID for the connection
|
|
* type: string
|
|
* in: formData
|
|
* required: true
|
|
* clientSecretParamPatch:
|
|
* name: clientSecret
|
|
* description: Client Secret for the connection
|
|
* type: string
|
|
* in: formData
|
|
* required: true
|
|
* nameParamPatch:
|
|
* name: name
|
|
* description: Name/identifier for the connection
|
|
* type: string
|
|
* in: formData
|
|
* descriptionParamPatch:
|
|
* name: description
|
|
* description: A short description for the connection not more than 100 characters
|
|
* type: string
|
|
* in: formData
|
|
* encodedRawMetadataParamPatch:
|
|
* name: encodedRawMetadata
|
|
* description: Base64 encoding of the XML metadata
|
|
* in: formData
|
|
* type: string
|
|
* rawMetadataParamPatch:
|
|
* name: rawMetadata
|
|
* description: Raw XML metadata
|
|
* in: formData
|
|
* type: string
|
|
* oidcDiscoveryUrlPatch:
|
|
* name: oidcDiscoveryUrl
|
|
* description: well-known URL where the OpenID Provider configuration is exposed
|
|
* in: formData
|
|
* type: string
|
|
* oidcClientIdPatch:
|
|
* name: oidcClientId
|
|
* description: clientId of the application set up on the OpenID Provider
|
|
* in: formData
|
|
* type: string
|
|
* oidcClientSecretPatch:
|
|
* name: oidcClientSecret
|
|
* description: clientSecret of the application set up on the OpenID Provider
|
|
* in: formData
|
|
* type: string
|
|
* defaultRedirectUrlParamPatch:
|
|
* name: defaultRedirectUrl
|
|
* description: The redirect URL to use in the IdP login flow
|
|
* in: formData
|
|
* type: string
|
|
* redirectUrlParamPatch:
|
|
* name: redirectUrl
|
|
* description: JSON encoded array containing a list of allowed redirect URLs
|
|
* in: formData
|
|
* type: string
|
|
* tenantParamPatch:
|
|
* name: tenant
|
|
* description: Tenant
|
|
* in: formData
|
|
* required: true
|
|
* type: string
|
|
* productParamPatch:
|
|
* name: product
|
|
* description: Product
|
|
* in: formData
|
|
* required: true
|
|
* type: string
|
|
* /api/v1/saml/config:
|
|
* patch:
|
|
* summary: Update SAML Config
|
|
* operationId: update-saml-config
|
|
* tags: [SAML Config - Deprecated]
|
|
* deprecated: true
|
|
* consumes:
|
|
* - application/json
|
|
* - application/x-www-form-urlencoded
|
|
* parameters:
|
|
* - $ref: '#/parameters/clientIDParamPatch'
|
|
* - $ref: '#/parameters/clientSecretParamPatch'
|
|
* - $ref: '#/parameters/nameParamPatch'
|
|
* - $ref: '#/parameters/descriptionParamPatch'
|
|
* - $ref: '#/parameters/encodedRawMetadataParamPatch'
|
|
* - $ref: '#/parameters/rawMetadataParamPatch'
|
|
* - $ref: '#/parameters/defaultRedirectUrlParamPatch'
|
|
* - $ref: '#/parameters/redirectUrlParamPatch'
|
|
* - $ref: '#/parameters/tenantParamPatch'
|
|
* - $ref: '#/parameters/productParamPatch'
|
|
* responses:
|
|
* 204:
|
|
* description: Success
|
|
* 400:
|
|
* $ref: '#/definitions/validationErrorsPatch'
|
|
* 401:
|
|
* description: Unauthorized
|
|
* /api/v1/connections:
|
|
* patch:
|
|
* summary: Update SSO Connection
|
|
* operationId: update-sso-connection
|
|
* tags: [Connections]
|
|
* consumes:
|
|
* - application/json
|
|
* - application/x-www-form-urlencoded
|
|
* parameters:
|
|
* - $ref: '#/parameters/clientIDParamPatch'
|
|
* - $ref: '#/parameters/clientSecretParamPatch'
|
|
* - $ref: '#/parameters/nameParamPatch'
|
|
* - $ref: '#/parameters/descriptionParamPatch'
|
|
* - $ref: '#/parameters/encodedRawMetadataParamPatch'
|
|
* - $ref: '#/parameters/rawMetadataParamPatch'
|
|
* - $ref: '#/parameters/oidcDiscoveryUrlPatch'
|
|
* - $ref: '#/parameters/oidcClientIdPatch'
|
|
* - $ref: '#/parameters/oidcClientSecretPatch'
|
|
* - $ref: '#/parameters/defaultRedirectUrlParamPatch'
|
|
* - $ref: '#/parameters/redirectUrlParamPatch'
|
|
* - $ref: '#/parameters/tenantParamPatch'
|
|
* - $ref: '#/parameters/productParamPatch'
|
|
* responses:
|
|
* 204:
|
|
* description: Success
|
|
* 400:
|
|
* $ref: '#/definitions/validationErrorsPatch'
|
|
* 401:
|
|
* description: Unauthorized
|
|
* 500:
|
|
* description: Please set OpenID response handler path (oidcPath) on Jackson
|
|
*/
|
|
public async updateSAMLConnection(
|
|
body: (SAMLSSOConnectionWithEncodedMetadata | SAMLSSOConnectionWithRawMetadata) & {
|
|
clientID: string;
|
|
clientSecret: string;
|
|
}
|
|
): Promise<void> {
|
|
await samlConnection.update(body, this.connectionStore, this.getConnections.bind(this));
|
|
}
|
|
|
|
// For backwards compatibility
|
|
public async updateConfig(
|
|
...args: Parameters<ConnectionAPIController['updateSAMLConnection']>
|
|
): Promise<void> {
|
|
await this.updateSAMLConnection(...args);
|
|
}
|
|
|
|
public async updateOIDCConnection(
|
|
body: OIDCSSOConnection & { clientID: string; clientSecret: string }
|
|
): Promise<void> {
|
|
if (!this.opts.oidcPath) {
|
|
throw new JacksonError('Please set OpenID response handler path (oidcPath) on Jackson', 500);
|
|
}
|
|
|
|
await oidcConnection.update(body, this.connectionStore, this.getConnections.bind(this));
|
|
}
|
|
|
|
/**
|
|
* @swagger
|
|
* parameters:
|
|
* tenantParamGet:
|
|
* in: query
|
|
* name: tenant
|
|
* type: string
|
|
* description: Tenant
|
|
* productParamGet:
|
|
* in: query
|
|
* name: product
|
|
* type: string
|
|
* description: Product
|
|
* clientIDParamGet:
|
|
* in: query
|
|
* name: clientID
|
|
* type: string
|
|
* description: Client ID
|
|
* strategyParamGet:
|
|
* in: query
|
|
* name: strategy
|
|
* type: string
|
|
* description: Strategy which can help to filter connections with tenant/product query
|
|
* definitions:
|
|
* Connection:
|
|
* type: object
|
|
* properties:
|
|
* clientID:
|
|
* type: string
|
|
* description: Connection clientID
|
|
* clientSecret:
|
|
* type: string
|
|
* description: Connection clientSecret
|
|
* name:
|
|
* type: string
|
|
* description: Connection name
|
|
* description:
|
|
* type: string
|
|
* description: Connection description
|
|
* redirectUrl:
|
|
* type: string
|
|
* description: A list of allowed redirect URLs
|
|
* defaultRedirectUrl:
|
|
* type: string
|
|
* description: The redirect URL to use in the IdP login flow
|
|
* tenant:
|
|
* type: string
|
|
* description: Connection tenant
|
|
* product:
|
|
* type: string
|
|
* description: Connection product
|
|
* idpMetadata:
|
|
* type: object
|
|
* description: SAML IdP metadata
|
|
* certs:
|
|
* type: object
|
|
* description: Certs generated for SAML connection
|
|
* oidcProvider:
|
|
* type: object
|
|
* description: OIDC IdP metadata
|
|
* responses:
|
|
* '200Get':
|
|
* description: Success
|
|
* schema:
|
|
* type: array
|
|
* items:
|
|
* $ref: '#/definitions/Connection'
|
|
* '400Get':
|
|
* description: Please provide `clientID` or `tenant` and `product`.
|
|
* '401Get':
|
|
* description: Unauthorized
|
|
* /api/v1/connections:
|
|
* get:
|
|
* summary: Get SSO Connections
|
|
* parameters:
|
|
* - $ref: '#/parameters/tenantParamGet'
|
|
* - $ref: '#/parameters/productParamGet'
|
|
* - $ref: '#/parameters/clientIDParamGet'
|
|
* - $ref: '#/parameters/strategyParamGet'
|
|
* operationId: get-connections
|
|
* tags: [Connections]
|
|
* responses:
|
|
* '200':
|
|
* $ref: '#/responses/200Get'
|
|
* '400':
|
|
* $ref: '#/responses/400Get'
|
|
* '401':
|
|
* $ref: '#/responses/401Get'
|
|
*/
|
|
public async getConnections(body: GetConnectionsQuery): Promise<Array<SAMLSSORecord | OIDCSSORecord>> {
|
|
const clientID = 'clientID' in body ? body.clientID : undefined;
|
|
const tenant = 'tenant' in body ? body.tenant : undefined;
|
|
const product = 'product' in body ? body.product : undefined;
|
|
const strategy = 'strategy' in body ? body.strategy : undefined;
|
|
|
|
metrics.increment('getConnections');
|
|
|
|
if (clientID) {
|
|
const connection = await this.connectionStore.get(clientID);
|
|
|
|
if (!connection || typeof connection !== 'object') {
|
|
return [];
|
|
}
|
|
|
|
return [connection];
|
|
}
|
|
|
|
if (tenant && product) {
|
|
const connections = await this.connectionStore.getByIndex({
|
|
name: IndexNames.TenantProduct,
|
|
value: dbutils.keyFromParts(tenant, product),
|
|
});
|
|
|
|
if (!connections || !connections.length) {
|
|
return [];
|
|
}
|
|
// filter if strategy is passed
|
|
const filteredConnections = strategy
|
|
? connections.filter((connection) => {
|
|
if (strategy === 'saml') {
|
|
if (connection.idpMetadata) {
|
|
return true;
|
|
}
|
|
}
|
|
if (strategy === 'oidc') {
|
|
if (connection.oidcProvider) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
})
|
|
: connections;
|
|
|
|
if (!filteredConnections.length) {
|
|
return [];
|
|
}
|
|
|
|
return filteredConnections;
|
|
}
|
|
|
|
throw new JacksonError('Please provide `clientID` or `tenant` and `product`.', 400);
|
|
}
|
|
|
|
/**
|
|
* @swagger
|
|
* /api/v1/saml/config:
|
|
* get:
|
|
* summary: Get SAML Config
|
|
* operationId: get-saml-config
|
|
* tags: [SAML Config - Deprecated]
|
|
* deprecated: true
|
|
* parameters:
|
|
* - $ref: '#/parameters/tenantParamGet'
|
|
* - $ref: '#/parameters/productParamGet'
|
|
* - $ref: '#/parameters/clientIDParamGet'
|
|
* responses:
|
|
* '200':
|
|
* description: Success
|
|
* schema:
|
|
* type: object
|
|
* example:
|
|
* {
|
|
* "idpMetadata": {
|
|
* "sso": {
|
|
* "postUrl": "https://dev-20901260.okta.com/app/dev-20901260_jacksonnext_1/xxxxxxxxxxxxx/sso/saml",
|
|
* "redirectUrl": "https://dev-20901260.okta.com/app/dev-20901260_jacksonnext_1/xxxxxxxxxxxxx/sso/saml"
|
|
* },
|
|
* "entityID": "http://www.okta.com/xxxxxxxxxxxxx",
|
|
* "thumbprint": "Eo+eUi3UM3XIMkFFtdVK3yJ5vO9f7YZdasdasdad",
|
|
* "loginType": "idp",
|
|
* "provider": "okta.com"
|
|
* },
|
|
* "defaultRedirectUrl": "https://hoppscotch.io/",
|
|
* "redirectUrl": ["https://hoppscotch.io/"],
|
|
* "tenant": "hoppscotch.io",
|
|
* "product": "API Engine",
|
|
* "name": "Hoppscotch-SP",
|
|
* "description": "SP for hoppscotch.io",
|
|
* "clientID": "Xq8AJt3yYAxmXizsCWmUBDRiVP1iTC8Y/otnvFIMitk",
|
|
* "clientSecret": "00e3e11a3426f97d8000000738300009130cd45419c5943",
|
|
* "certs": {
|
|
* "publicKey": "-----BEGIN CERTIFICATE-----.......-----END CERTIFICATE-----",
|
|
* "privateKey": "-----BEGIN PRIVATE KEY-----......-----END PRIVATE KEY-----"
|
|
* }
|
|
* }
|
|
* '400':
|
|
* $ref: '#/responses/400Get'
|
|
* '401':
|
|
* $ref: '#/responses/401Get'
|
|
*/
|
|
public async getConfig(body: GetConfigQuery): Promise<SAMLSSORecord | Record<string, never>> {
|
|
const clientID = 'clientID' in body ? body.clientID : undefined;
|
|
const tenant = 'tenant' in body ? body.tenant : undefined;
|
|
const product = 'product' in body ? body.product : undefined;
|
|
|
|
metrics.increment('getConnections');
|
|
|
|
if (clientID) {
|
|
const samlConfig = await this.connectionStore.get(clientID);
|
|
|
|
return samlConfig || {};
|
|
}
|
|
|
|
if (tenant && product) {
|
|
const samlConfigs = await this.connectionStore.getByIndex({
|
|
name: IndexNames.TenantProduct,
|
|
value: dbutils.keyFromParts(tenant, product),
|
|
});
|
|
|
|
if (!samlConfigs || !samlConfigs.length) {
|
|
return {};
|
|
}
|
|
|
|
return { ...samlConfigs[0] };
|
|
}
|
|
|
|
throw new JacksonError('Please provide `clientID` or `tenant` and `product`.', 400);
|
|
}
|
|
|
|
/**
|
|
* @swagger
|
|
* parameters:
|
|
* clientIDDel:
|
|
* name: clientID
|
|
* in: formData
|
|
* type: string
|
|
* description: Client ID
|
|
* clientSecretDel:
|
|
* name: clientSecret
|
|
* in: formData
|
|
* type: string
|
|
* description: Client Secret
|
|
* tenantDel:
|
|
* name: tenant
|
|
* in: formData
|
|
* type: string
|
|
* description: Tenant
|
|
* productDel:
|
|
* name: product
|
|
* in: formData
|
|
* type: string
|
|
* description: Product
|
|
* strategyDel:
|
|
* name: strategy
|
|
* in: formData
|
|
* type: string
|
|
* description: Strategy which can help to filter connections with tenant/product query
|
|
* /api/v1/connections:
|
|
* delete:
|
|
* parameters:
|
|
* - $ref: '#/parameters/clientIDDel'
|
|
* - $ref: '#/parameters/clientSecretDel'
|
|
* - $ref: '#/parameters/tenantDel'
|
|
* - $ref: '#/parameters/productDel'
|
|
* - $ref: '#/parameters/strategyDel'
|
|
* summary: Delete SSO Connections
|
|
* operationId: delete-sso-connection
|
|
* tags: [Connections]
|
|
* consumes:
|
|
* - application/x-www-form-urlencoded
|
|
* - application/json
|
|
* responses:
|
|
* '200':
|
|
* description: Success
|
|
* '400':
|
|
* description: clientSecret mismatch | Please provide `clientID` and `clientSecret` or `tenant` and `product`.
|
|
* '401':
|
|
* description: Unauthorized
|
|
* /api/v1/saml/config:
|
|
* delete:
|
|
* summary: Delete SAML Config
|
|
* operationId: delete-saml-config
|
|
* tags: [SAML Config - Deprecated]
|
|
* deprecated: true
|
|
* consumes:
|
|
* - application/x-www-form-urlencoded
|
|
* - application/json
|
|
* parameters:
|
|
* - $ref: '#/parameters/clientIDDel'
|
|
* - $ref: '#/parameters/clientSecretDel'
|
|
* - $ref: '#/parameters/tenantDel'
|
|
* - $ref: '#/parameters/productDel'
|
|
* responses:
|
|
* '200':
|
|
* description: Success
|
|
* '400':
|
|
* description: clientSecret mismatch | Please provide `clientID` and `clientSecret` or `tenant` and `product`.
|
|
* '401':
|
|
* description: Unauthorized
|
|
*/
|
|
public async deleteConnections(body: DelConnectionsQuery): Promise<void> {
|
|
const clientID = 'clientID' in body ? body.clientID : undefined;
|
|
const clientSecret = 'clientSecret' in body ? body.clientSecret : undefined;
|
|
const tenant = 'tenant' in body ? body.tenant : undefined;
|
|
const product = 'product' in body ? body.product : undefined;
|
|
const strategy = 'strategy' in body ? body.strategy : undefined;
|
|
|
|
metrics.increment('deleteConnections');
|
|
|
|
if (clientID && clientSecret) {
|
|
const connection = await this.connectionStore.get(clientID);
|
|
|
|
if (!connection) {
|
|
return;
|
|
}
|
|
|
|
if (connection.clientSecret === clientSecret) {
|
|
await this.connectionStore.delete(clientID);
|
|
} else {
|
|
throw new JacksonError('clientSecret mismatch', 400);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (tenant && product) {
|
|
const connections = await this.connectionStore.getByIndex({
|
|
name: IndexNames.TenantProduct,
|
|
value: dbutils.keyFromParts(tenant, product),
|
|
});
|
|
|
|
if (!connections || !connections.length) {
|
|
return;
|
|
}
|
|
|
|
// filter if strategy is passed
|
|
const filteredConnections = strategy
|
|
? connections.filter((connection) => {
|
|
if (strategy === 'saml') {
|
|
if (connection.idpMetadata) {
|
|
return true;
|
|
}
|
|
}
|
|
if (strategy === 'oidc') {
|
|
if (connection.oidcProvider) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
})
|
|
: connections;
|
|
|
|
for (const conf of filteredConnections) {
|
|
await this.connectionStore.delete(conf.clientID);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
throw new JacksonError('Please provide `clientID` and `clientSecret` or `tenant` and `product`.', 400);
|
|
}
|
|
|
|
public async deleteConfig(body: DelConnectionsQuery): Promise<void> {
|
|
await this.deleteConnections({ ...body, strategy: 'saml' });
|
|
}
|
|
}
|