From f88f67252a5c1a447f831e2aeea62fe48129ee86 Mon Sep 17 00:00:00 2001 From: Thomas Bonnin <233326+TBonnin@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:06:32 -0400 Subject: [PATCH] feat: make connectionId optional when creating a new connection --- packages/frontend/lib/index.ts | 46 +++++++++++----- .../lib/controllers/apiAuth.controller.ts | 32 +++++------ .../lib/controllers/appAuth.controller.ts | 15 ++---- .../controllers/appStoreAuth.controller.ts | 16 +++--- .../lib/controllers/auth/postTableau.ts | 12 +++-- .../server/lib/controllers/auth/postTba.ts | 8 +-- .../controllers/auth/postUnauthenticated.ts | 10 ++-- .../lib/controllers/connection.controller.ts | 28 +++++----- .../lib/controllers/oauth.controller.ts | 53 ++++++++----------- packages/server/lib/utils/hmac.ts | 4 +- .../shared/lib/services/connection.service.ts | 5 ++ packages/shared/lib/services/hmac.service.ts | 5 +- packages/types/lib/auth/http.api.ts | 6 +-- .../webapp/src/pages/Connection/Create.tsx | 11 ++-- 14 files changed, 130 insertions(+), 121 deletions(-) diff --git a/packages/frontend/lib/index.ts b/packages/frontend/lib/index.ts index dae20d77c42..fa749200f85 100644 --- a/packages/frontend/lib/index.ts +++ b/packages/frontend/lib/index.ts @@ -27,9 +27,9 @@ export interface AuthResult { isPending?: boolean; } -interface AuthOptions { +type AuthOptions = { detectClosedAuthWindow?: boolean; // If true, `nango.auth()` would fail if the login window is closed before the authorization flow is completed -} +} & (ConnectionConfig | OAuth2ClientCredentials | OAuthCredentialsOverride | BasicApiCredentials | ApiKeyCredentials | AppStoreCredentials); export default class Nango { private hostBaseUrl: string; @@ -82,11 +82,24 @@ export default class Nango { /** * Creates a new unauthenticated connection using the specified provider configuration key and connection ID * @param providerConfigKey - The key identifying the provider configuration on Nango - * @param connectionId - The ID of the connection + * @param connectionId - Optional. The ID of the connection * @param connectionConfig - Optional. Additional configuration for the connection * @returns A promise that resolves with the authentication result */ - public async create(providerConfigKey: string, connectionId: string, connectionConfig?: ConnectionConfig): Promise { + public async create(providerConfigKey: string, connectionConfig?: ConnectionConfig): Promise; + public async create(providerConfigKey: string, connectionId: string, connectionConfig?: ConnectionConfig): Promise; + public async create( + providerConfigKey: string, + connectionIdOrConnectionConfig?: string | ConnectionConfig, + moreConnectionConfig?: ConnectionConfig + ): Promise { + let connectionId: string | null = null; + let connectionConfig: ConnectionConfig | undefined = moreConnectionConfig; + if (typeof connectionIdOrConnectionConfig === 'string') { + connectionId = connectionIdOrConnectionConfig; + } else { + connectionConfig = connectionIdOrConnectionConfig; + } const url = this.hostBaseUrl + `/auth/unauthenticated/${providerConfigKey}${this.toQueryString(connectionId, connectionConfig)}`; const res = await fetch(url, { @@ -107,16 +120,23 @@ export default class Nango { /** * Initiates the authorization process for a connection * @param providerConfigKey - The key identifying the provider configuration on Nango - * @param connectionId - The ID of the connection for which to authorize + * @param connectionId - Optional. The ID of the connection for which to authorize * @param options - Optional. Additional options for authorization * @returns A promise that resolves with the authorization result */ - public auth( - providerConfigKey: string, - connectionId: string, - options?: (ConnectionConfig | OAuth2ClientCredentials | OAuthCredentialsOverride | BasicApiCredentials | ApiKeyCredentials | AppStoreCredentials) & - AuthOptions - ): Promise { + public auth(providerConfigKey: string, options?: AuthOptions): Promise; + public auth(providerConfigKey: string, connectionId: string, options?: AuthOptions): Promise; + public auth(providerConfigKey: string, connectionIdOrOptions?: string | AuthOptions, moreOptions?: AuthOptions): Promise { + let connectionId: string | null = null; + let options: AuthOptions | undefined = moreOptions; + if (typeof connectionIdOrOptions === 'string') { + connectionId = connectionIdOrOptions; + } else { + options = { + ...options, + ...connectionIdOrOptions + }; + } if ( options && 'credentials' in options && @@ -286,7 +306,7 @@ export default class Nango { */ private async customAuth( providerConfigKey: string, - connectionId: string, + connectionId: string | null, connectionConfigWithCredentials: ConnectionConfig, connectionConfig?: ConnectionConfig ): Promise { @@ -430,7 +450,7 @@ export default class Nango { * @param connectionConfig - Optional. Additional configuration for the connection * @returns The generated query string */ - private toQueryString(connectionId: string, connectionConfig?: ConnectionConfig): string { + private toQueryString(connectionId: string | null, connectionConfig?: ConnectionConfig): string { const query: string[] = []; if (connectionId) { diff --git a/packages/server/lib/controllers/apiAuth.controller.ts b/packages/server/lib/controllers/apiAuth.controller.ts index 412d1cbf32f..db424a95a25 100644 --- a/packages/server/lib/controllers/apiAuth.controller.ts +++ b/packages/server/lib/controllers/apiAuth.controller.ts @@ -27,7 +27,7 @@ class ApiAuthController { async apiKey(req: Request, res: Response>, next: NextFunction) { const { account, environment } = res.locals; const { providerConfigKey } = req.params; - const connectionId = req.query['connection_id'] as string | undefined; + const receivedConnectionId = req.query['connection_id'] as string | undefined; const connectionConfig = req.query['params'] != null ? getConnectionConfig(req.query['params']) : {}; let logCtx: LogContext | undefined; @@ -48,12 +48,6 @@ class ApiAuthController { return; } - if (!connectionId) { - errorManager.errRes(res, 'missing_connection_id'); - - return; - } - const hmacEnabled = await hmacService.isEnabled(environment.id); if (hmacEnabled) { const hmac = req.query['hmac'] as string | undefined; @@ -65,7 +59,7 @@ class ApiAuthController { return; } - const verified = await hmacService.verify(hmac, environment.id, providerConfigKey, connectionId); + const verified = await hmacService.verify(hmac, environment.id, providerConfigKey, receivedConnectionId); if (!verified) { await logCtx.error('Invalid HMAC'); await logCtx.failed(); @@ -76,6 +70,8 @@ class ApiAuthController { } } + const connectionId = receivedConnectionId || connectionService.generateConnectionId(); + const config = await configService.getProviderConfig(providerConfigKey, environment.id); if (config == null) { @@ -176,7 +172,7 @@ class ApiAuthController { if (logCtx) { void connectionCreationFailedHook( { - connection: { connection_id: connectionId!, provider_config_key: providerConfigKey! }, + connection: { connection_id: receivedConnectionId!, provider_config_key: providerConfigKey! }, environment, account, auth_mode: 'API_KEY', @@ -199,7 +195,7 @@ class ApiAuthController { environmentId: environment.id, metadata: { providerConfigKey, - connectionId + receivedConnectionId } }); @@ -210,7 +206,7 @@ class ApiAuthController { async basic(req: Request, res: Response>, next: NextFunction) { const { account, environment } = res.locals; const { providerConfigKey } = req.params; - const connectionId = req.query['connection_id'] as string | undefined; + const receivedConnectionId = req.query['connection_id'] as string | undefined; const connectionConfig = req.query['params'] != null ? getConnectionConfig(req.query['params']) : {}; let logCtx: LogContext | undefined; @@ -232,12 +228,6 @@ class ApiAuthController { return; } - if (!connectionId) { - errorManager.errRes(res, 'missing_connection_id'); - - return; - } - const hmacEnabled = await hmacService.isEnabled(environment.id); if (hmacEnabled) { const hmac = req.query['hmac'] as string | undefined; @@ -249,7 +239,7 @@ class ApiAuthController { return; } - const verified = await hmacService.verify(hmac, environment.id, providerConfigKey, connectionId); + const verified = await hmacService.verify(hmac, environment.id, providerConfigKey, receivedConnectionId); if (!verified) { await logCtx.error('Invalid HMAC'); await logCtx.failed(); @@ -259,6 +249,8 @@ class ApiAuthController { } } + const connectionId = receivedConnectionId || connectionService.generateConnectionId(); + const { username = '', password = '' } = req.body; const config = await configService.getProviderConfig(providerConfigKey, environment.id); @@ -354,7 +346,7 @@ class ApiAuthController { if (logCtx) { void connectionCreationFailedHook( { - connection: { connection_id: connectionId!, provider_config_key: providerConfigKey! }, + connection: { connection_id: receivedConnectionId!, provider_config_key: providerConfigKey! }, environment, account, auth_mode: 'API_KEY', @@ -377,7 +369,7 @@ class ApiAuthController { environmentId: environment.id, metadata: { providerConfigKey, - connectionId + connectionId: receivedConnectionId } }); diff --git a/packages/server/lib/controllers/appAuth.controller.ts b/packages/server/lib/controllers/appAuth.controller.ts index 83a318ea81d..6cc011bfe55 100644 --- a/packages/server/lib/controllers/appAuth.controller.ts +++ b/packages/server/lib/controllers/appAuth.controller.ts @@ -58,21 +58,16 @@ class AppAuthController { void analytics.track(AnalyticsTypes.PRE_APP_AUTH, account.id); - const { providerConfigKey, connectionId, webSocketClientId: wsClientId } = session; + const { providerConfigKey, connectionId: receivedConnectionId, webSocketClientId: wsClientId } = session; const logCtx = await logContextGetter.get({ id: session.activityLogId }); try { if (!providerConfigKey) { errorManager.errRes(res, 'missing_connection'); - return; } - if (!connectionId) { - errorManager.errRes(res, 'missing_connection_id'); - - return; - } + const connectionId = receivedConnectionId || connectionService.generateConnectionId(); const config = await configService.getProviderConfig(providerConfigKey, environment.id); @@ -226,12 +221,12 @@ class AppAuthController { await telemetry.log(LogTypes.AUTH_TOKEN_REQUEST_FAILURE, `App auth request process failed ${content}`, LogActionEnum.AUTH, { environmentId: String(environment.id), providerConfigKey: String(providerConfigKey), - connectionId: String(connectionId) + connectionId: String(receivedConnectionId) }); void connectionCreationFailedHook( { - connection: { connection_id: connectionId, provider_config_key: providerConfigKey }, + connection: { connection_id: receivedConnectionId, provider_config_key: providerConfigKey }, environment, account, auth_mode: 'APP', @@ -245,7 +240,7 @@ class AppAuthController { logCtx ); - return publisher.notifyErr(res, wsClientId, providerConfigKey, connectionId, WSErrBuilder.UnknownError(prettyError)); + return publisher.notifyErr(res, wsClientId, providerConfigKey, receivedConnectionId, WSErrBuilder.UnknownError(prettyError)); } } } diff --git a/packages/server/lib/controllers/appStoreAuth.controller.ts b/packages/server/lib/controllers/appStoreAuth.controller.ts index b0fc621fcc9..c006f86e1f6 100644 --- a/packages/server/lib/controllers/appStoreAuth.controller.ts +++ b/packages/server/lib/controllers/appStoreAuth.controller.ts @@ -21,7 +21,7 @@ class AppStoreAuthController { async auth(req: Request, res: Response>, next: NextFunction) { const { environment, account } = res.locals; const { providerConfigKey } = req.params; - const connectionId = req.query['connection_id'] as string | undefined; + const receivedConnectionId = req.query['connection_id'] as string | undefined; let logCtx: LogContext | undefined; @@ -42,12 +42,6 @@ class AppStoreAuthController { return; } - if (!connectionId) { - errorManager.errRes(res, 'missing_connection_id'); - - return; - } - const hmacEnabled = await hmacService.isEnabled(environment.id); if (hmacEnabled) { const hmac = req.query['hmac'] as string | undefined; @@ -59,7 +53,7 @@ class AppStoreAuthController { return; } - const verified = await hmacService.verify(hmac, environment.id, providerConfigKey, connectionId); + const verified = await hmacService.verify(hmac, environment.id, providerConfigKey, receivedConnectionId); if (!verified) { await logCtx.error('Invalid HMAC'); await logCtx.failed(); @@ -70,6 +64,8 @@ class AppStoreAuthController { } } + const connectionId = receivedConnectionId || connectionService.generateConnectionId(); + const config = await configService.getProviderConfig(providerConfigKey, environment.id); if (config == null) { @@ -185,7 +181,7 @@ class AppStoreAuthController { void connectionCreationFailedHook( { - connection: { connection_id: connectionId!, provider_config_key: providerConfigKey! }, + connection: { connection_id: receivedConnectionId!, provider_config_key: providerConfigKey! }, environment, account, auth_mode: 'APP_STORE', @@ -209,7 +205,7 @@ class AppStoreAuthController { environmentId: environment.id, metadata: { providerConfigKey, - connectionId + connectionId: receivedConnectionId } }); diff --git a/packages/server/lib/controllers/auth/postTableau.ts b/packages/server/lib/controllers/auth/postTableau.ts index 7e524f06498..39a9522656e 100644 --- a/packages/server/lib/controllers/auth/postTableau.ts +++ b/packages/server/lib/controllers/auth/postTableau.ts @@ -30,7 +30,7 @@ const bodyValidation = z const queryStringValidation = z .object({ - connection_id: connectionIdSchema, + connection_id: connectionIdSchema.optional(), params: z.record(z.any()).optional(), public_key: z.string().uuid(), hmac: z.string().optional() @@ -70,7 +70,7 @@ export const postPublicTableauAuthorization = asyncWrapper>, next: NextFunction) { try { const { environment, account } = res.locals; - const { connection_id, provider_config_key, metadata, connection_config } = req.body; + const { provider_config_key, metadata, connection_config } = req.body; - if (!connection_id) { - errorManager.errRes(res, 'missing_connection'); - return; - } + const connectionId = (req.body['connection_id'] as string) || connectionService.generateConnectionId(); if (!provider_config_key) { errorManager.errRes(res, 'missing_provider_config'); @@ -359,7 +356,7 @@ class ConnectionController { }; const [imported] = await connectionService.importOAuthConnection({ - connectionId: connection_id, + connectionId, providerConfigKey: provider_config_key, provider: providerName, metadata, @@ -422,7 +419,7 @@ class ConnectionController { }; const [imported] = await connectionService.importOAuthConnection({ - connectionId: connection_id, + connectionId, providerConfigKey: provider_config_key, provider: providerName, metadata, @@ -471,7 +468,7 @@ class ConnectionController { }; const [imported] = await connectionService.importOAuthConnection({ - connectionId: connection_id, + connectionId, providerConfigKey: provider_config_key, provider: providerName, metadata, @@ -513,7 +510,7 @@ class ConnectionController { ); }; const [imported] = await connectionService.importApiAuthConnection({ - connectionId: connection_id, + connectionId, providerConfigKey: provider_config_key, provider: providerName, metadata, @@ -555,7 +552,7 @@ class ConnectionController { }; const [imported] = await connectionService.importApiAuthConnection({ - connectionId: connection_id, + connectionId, providerConfigKey: provider_config_key, provider: providerName, metadata, @@ -602,7 +599,7 @@ class ConnectionController { } const [imported] = await connectionService.upsertConnection({ - connectionId: connection_id, + connectionId, providerConfigKey: provider_config_key, provider: providerName, parsedRawCredentials: credentials as unknown as AuthCredentials, @@ -650,7 +647,7 @@ class ConnectionController { } const [imported] = await connectionService.upsertTbaConnection({ - connectionId: connection_id, + connectionId, providerConfigKey: provider_config_key, credentials: tbaCredentials, connectionConfig: { @@ -670,7 +667,7 @@ class ConnectionController { } } else if (provider.auth_mode === 'NONE') { const [imported] = await connectionService.upsertUnauthConnection({ - connectionId: connection_id, + connectionId, providerConfigKey: provider_config_key, provider: providerName, environment, @@ -702,7 +699,10 @@ class ConnectionController { ); } - res.status(201).send(req.body); + res.status(201).send({ + ...req.body, + connection_id: connectionId + }); } catch (err) { next(err); } diff --git a/packages/server/lib/controllers/oauth.controller.ts b/packages/server/lib/controllers/oauth.controller.ts index 4631a82ce2c..c8e46ef97bc 100644 --- a/packages/server/lib/controllers/oauth.controller.ts +++ b/packages/server/lib/controllers/oauth.controller.ts @@ -54,7 +54,7 @@ class OAuthController { const accountId = account.id; const environmentId = environment.id; const { providerConfigKey } = req.params; - let connectionId = req.query['connection_id'] as string | undefined; + const receivedConnectionId = req.query['connection_id'] as string | undefined; const wsClientId = req.query['ws_client_id'] as string | undefined; const userScope = req.query['user_scope'] as string | undefined; @@ -77,7 +77,7 @@ class OAuthController { environmentId: String(environmentId), accountId: String(accountId), providerConfigKey: String(providerConfigKey), - connectionId: String(connectionId) + connectionId: String(receivedConnectionId) }); const callbackUrl = await getOauthCallbackUrl(environmentId); @@ -85,22 +85,13 @@ class OAuthController { const authorizationParams = req.query['authorization_params'] != null ? getAdditionalAuthorizationParams(req.query['authorization_params']) : {}; const overrideCredentials = req.query['credentials'] != null ? getAdditionalAuthorizationParams(req.query['credentials']) : {}; - if (connectionId == null) { - const error = WSErrBuilder.MissingConnectionId(); - await logCtx.error(error.message); - await logCtx.failed(); - - return publisher.notifyErr(res, wsClientId, providerConfigKey, connectionId, error); - } else if (providerConfigKey == null) { + if (providerConfigKey == null) { const error = WSErrBuilder.MissingProviderConfigKey(); await logCtx.error(error.message); await logCtx.failed(); - return publisher.notifyErr(res, wsClientId, providerConfigKey, connectionId, error); + return publisher.notifyErr(res, wsClientId, providerConfigKey, receivedConnectionId, error); } - - connectionId = connectionId.toString(); - const hmacEnabled = await hmacService.isEnabled(environmentId); if (hmacEnabled) { const hmac = req.query['hmac'] as string | undefined; @@ -109,19 +100,21 @@ class OAuthController { await logCtx.error(error.message); await logCtx.failed(); - return publisher.notifyErr(res, wsClientId, providerConfigKey, connectionId, error); + return publisher.notifyErr(res, wsClientId, providerConfigKey, receivedConnectionId, error); } - const verified = await hmacService.verify(hmac, environmentId, providerConfigKey, connectionId); + const verified = await hmacService.verify(hmac, environmentId, providerConfigKey, receivedConnectionId); if (!verified) { const error = WSErrBuilder.InvalidHmac(); await logCtx.error(error.message); await logCtx.failed(); - return publisher.notifyErr(res, wsClientId, providerConfigKey, connectionId, error); + return publisher.notifyErr(res, wsClientId, providerConfigKey, receivedConnectionId, error); } } + const connectionId = receivedConnectionId || connectionService.generateConnectionId(); + await logCtx.info('Authorization URL request from the client'); const config = await configService.getProviderConfig(providerConfigKey, environmentId); @@ -240,18 +233,18 @@ class OAuthController { environmentId, metadata: { providerConfigKey, - connectionId + connectionId: receivedConnectionId } }); - return publisher.notifyErr(res, wsClientId, providerConfigKey, connectionId, WSErrBuilder.UnknownError(prettyError)); + return publisher.notifyErr(res, wsClientId, providerConfigKey, receivedConnectionId, WSErrBuilder.UnknownError(prettyError)); } } public async oauth2RequestCC(req: Request, res: Response>, next: NextFunction) { const { environment, account } = res.locals; const { providerConfigKey } = req.params; - const connectionId = req.query['connection_id'] as string | undefined; + const receivedConnectionId = req.query['connection_id'] as string | undefined; const connectionConfig = req.query['params'] != null ? getConnectionConfig(req.query['params']) : {}; const body = req.body; @@ -288,12 +281,6 @@ class OAuthController { return; } - if (!connectionId) { - errorManager.errRes(res, 'missing_connection_id'); - - return; - } - const hmacEnabled = await hmacService.isEnabled(environment.id); if (hmacEnabled) { const hmac = req.query['hmac'] as string | undefined; @@ -305,7 +292,7 @@ class OAuthController { return; } - const verified = await hmacService.verify(hmac, environment.id, providerConfigKey, connectionId); + const verified = await hmacService.verify(hmac, environment.id, providerConfigKey, receivedConnectionId); if (!verified) { await logCtx.error('Invalid HMAC'); await logCtx.failed(); @@ -316,6 +303,8 @@ class OAuthController { } } + const connectionId = receivedConnectionId || connectionService.generateConnectionId(); + const config = await configService.getProviderConfig(providerConfigKey, environment.id); if (!config) { @@ -408,7 +397,7 @@ class OAuthController { void connectionCreationFailedHook( { - connection: { connection_id: connectionId!, provider_config_key: providerConfigKey! }, + connection: { connection_id: receivedConnectionId!, provider_config_key: providerConfigKey! }, environment, account, auth_mode: 'OAUTH2_CC', @@ -432,7 +421,7 @@ class OAuthController { environmentId: environment.id, metadata: { providerConfigKey, - connectionId + connectionId: receivedConnectionId } }); @@ -712,8 +701,8 @@ class OAuthController { const redirectUrl = oAuth1Client.getAuthorizationURL(tokenResult, oAuth1CallbackURL); await logCtx.info('Successfully requested token. Redirecting...', { - providerConfigKey: session.providerConfigKey, - connectionId: session.connectionId, + providerConfigKey, + connectionId, redirectUrl }); @@ -1158,8 +1147,8 @@ class OAuthController { operation: LogActionEnum.AUTH, environmentId: session.environmentId, metadata: { - providerConfigKey: session.providerConfigKey, - connectionId: session.connectionId + providerConfigKey, + connectionId } }); diff --git a/packages/server/lib/utils/hmac.ts b/packages/server/lib/utils/hmac.ts index 95a5ada4304..24efb0ecb1c 100644 --- a/packages/server/lib/utils/hmac.ts +++ b/packages/server/lib/utils/hmac.ts @@ -14,7 +14,7 @@ export async function hmacCheck({ environment: DBEnvironment; logCtx: LogContext; providerConfigKey: string; - connectionId: string; + connectionId: string | undefined; hmac: string | undefined; res: Response; }) { @@ -28,7 +28,7 @@ export async function hmacCheck({ return; } - const verified = await hmacService.verify(hmac, environment.id, providerConfigKey, connectionId); + const verified = await hmacService.verify(hmac, environment.id, providerConfigKey, ...(connectionId ? [connectionId] : [])); if (!verified) { await logCtx.error('Invalid HMAC'); await logCtx.failed(); diff --git a/packages/shared/lib/services/connection.service.ts b/packages/shared/lib/services/connection.service.ts index c5e991c23e2..8e0b596432e 100644 --- a/packages/shared/lib/services/connection.service.ts +++ b/packages/shared/lib/services/connection.service.ts @@ -55,6 +55,7 @@ import { CONNECTIONS_WITH_SCRIPTS_CAP_LIMIT } from '../constants.js'; import type { Orchestrator } from '../clients/orchestrator.js'; import { SlackService } from './notification/slack.service.js'; import { getProvider } from './providers.js'; +import { v4 as uuidv4 } from 'uuid'; const logger = getLogger('Connection'); const ACTIVE_LOG_TABLE = dbNamespace + 'active_logs'; @@ -69,6 +70,10 @@ class ConnectionService { this.locking = locking; } + public generateConnectionId(): string { + return uuidv4(); + } + public async upsertConnection({ connectionId, providerConfigKey, diff --git a/packages/shared/lib/services/hmac.service.ts b/packages/shared/lib/services/hmac.service.ts index a2a190151d4..5b2cf6f8c6b 100644 --- a/packages/shared/lib/services/hmac.service.ts +++ b/packages/shared/lib/services/hmac.service.ts @@ -21,8 +21,9 @@ class HmacService { return key; } - async verify(expectedDigest: string, id: number, ...values: string[]): Promise { - const actualDigest = await this.digest(id, ...values); + async verify(expectedDigest: string, id: number, ...values: (string | undefined)[]): Promise { + const definedValues: string[] = values.flatMap((v) => (v === undefined ? [] : [v])); + const actualDigest = await this.digest(id, ...definedValues); return expectedDigest === actualDigest; } diff --git a/packages/types/lib/auth/http.api.ts b/packages/types/lib/auth/http.api.ts index 27c9b1f4629..9b8048b2310 100644 --- a/packages/types/lib/auth/http.api.ts +++ b/packages/types/lib/auth/http.api.ts @@ -9,7 +9,7 @@ export type PostPublicTbaAuthorization = Endpoint<{ oauth_client_secret_override?: string | undefined; }; Querystring: { - connection_id: string; + connection_id?: string | undefined; public_key: string; params?: Record | undefined; hmac?: string | undefined; @@ -39,7 +39,7 @@ export type PostPublicTableauAuthorization = Endpoint<{ content_url?: string | undefined; }; Querystring: { - connection_id: string; + connection_id?: string | undefined; public_key: string; params?: Record | undefined; hmac?: string | undefined; @@ -64,7 +64,7 @@ export type PostPublicTableauAuthorization = Endpoint<{ export type PostPublicUnauthenticatedAuthorization = Endpoint<{ Method: 'POST'; Querystring: { - connection_id: string; + connection_id?: string | undefined; hmac?: string | undefined; }; Params: { diff --git a/packages/webapp/src/pages/Connection/Create.tsx b/packages/webapp/src/pages/Connection/Create.tsx index 9d658722d39..8005e713c57 100644 --- a/packages/webapp/src/pages/Connection/Create.tsx +++ b/packages/webapp/src/pages/Connection/Create.tsx @@ -205,14 +205,19 @@ export default function IntegrationCreate() { content_url: contentUrl }; } - - nango[authMode === 'NONE' ? 'create' : 'auth'](target.integration_unique_key.value, target.connection_id.value, { + const connectionConfig = { user_scope: authMode === 'NONE' ? undefined : selectedScopes || [], params, authorization_params: authorizationParams || {}, hmac: hmacDigest || '', credentials - }) + }; + const getConnection = + authMode === 'NONE' + ? nango.create(target.integration_unique_key.value, target.connection_id.value, connectionConfig) + : nango.auth(target.integration_unique_key.value, target.connection_id.value, connectionConfig); + + getConnection .then(() => { toast.success('Connection created!', { position: toast.POSITION.BOTTOM_CENTER }); analyticsTrack('web:connection_created', { provider: integration?.provider || 'unknown' });