-
Notifications
You must be signed in to change notification settings - Fork 445
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(connect-ui): enforce session token integrations (#3032)
## Describe your changes Fixes https://linear.app/nango/issue/NAN-1945/enforce-allowed-integrations-in-each-auth-endpoint - Enforce session token's allowed integrations
- Loading branch information
1 parent
1732178
commit 4941f74
Showing
14 changed files
with
160 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
import { seeders } from '@nangohq/shared'; | ||
import { afterAll, beforeAll, describe, expect, it } from 'vitest'; | ||
import { isSuccess, runServer } from '../../utils/tests.js'; | ||
import { isError, isSuccess, runServer } from '../../utils/tests.js'; | ||
|
||
let api: Awaited<ReturnType<typeof runServer>>; | ||
|
||
|
@@ -25,7 +25,7 @@ describe(`GET ${endpoint}`, () => { | |
params: { providerConfigKey: config.unique_key } | ||
}); | ||
|
||
isSuccess(res); | ||
isSuccess(res.json); | ||
expect(res.json).toStrictEqual<typeof res.json>({ | ||
connectionId: 'a', | ||
providerConfigKey: 'unauthenticated' | ||
|
@@ -43,10 +43,59 @@ describe(`GET ${endpoint}`, () => { | |
params: { providerConfigKey: config.unique_key } | ||
}); | ||
|
||
isSuccess(res); | ||
isSuccess(res.json); | ||
expect(res.json).toStrictEqual<typeof res.json>({ | ||
connectionId: expect.any(String), | ||
providerConfigKey: 'unauthenticated' | ||
}); | ||
}); | ||
|
||
it('should create one connection with sessionToken', async () => { | ||
const env = await seeders.createEnvironmentSeed(); | ||
const config = await seeders.createConfigSeed(env, 'unauthenticated', 'unauthenticated'); | ||
|
||
const resSession = await api.fetch('/connect/sessions', { | ||
method: 'POST', | ||
token: env.secret_key, | ||
body: { end_user: { id: '1', email: '[email protected]' } } | ||
}); | ||
isSuccess(resSession.json); | ||
|
||
const res = await api.fetch(endpoint, { | ||
method: 'POST', | ||
token: env.secret_key, | ||
query: { connect_session_token: resSession.json.data.token }, | ||
params: { providerConfigKey: config.unique_key } | ||
}); | ||
|
||
isSuccess(res.json); | ||
expect(res.json).toStrictEqual<typeof res.json>({ | ||
connectionId: expect.any(String), | ||
providerConfigKey: 'unauthenticated' | ||
}); | ||
}); | ||
|
||
it('should not be allowed to create an integration if disallowed by sessionToken', async () => { | ||
const env = await seeders.createEnvironmentSeed(); | ||
const config = await seeders.createConfigSeed(env, 'unauthenticated', 'unauthenticated'); | ||
|
||
const resSession = await api.fetch('/connect/sessions', { | ||
method: 'POST', | ||
token: env.secret_key, | ||
body: { end_user: { id: '1', email: '[email protected]' }, allowed_integrations: ['not_this_one'] } | ||
}); | ||
isSuccess(resSession.json); | ||
|
||
const res = await api.fetch(endpoint, { | ||
method: 'POST', | ||
token: env.secret_key, | ||
query: { connect_session_token: resSession.json.data.token }, | ||
params: { providerConfigKey: config.unique_key } | ||
}); | ||
|
||
isError(res.json); | ||
expect(res.json).toStrictEqual<typeof res.json>({ | ||
error: { code: 'integration_not_allowed' } | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import type { LogContext } from '@nangohq/logs'; | ||
import type { ApiError, IntegrationConfig } from '@nangohq/types'; | ||
|
||
import type { Response } from 'express'; | ||
import type { RequestLocals } from './express'; | ||
|
||
export async function isIntegrationAllowed({ | ||
config, | ||
logCtx, | ||
res | ||
}: { | ||
config: IntegrationConfig; | ||
logCtx: LogContext; | ||
res: Response<ApiError<'integration_not_allowed'>, Required<RequestLocals>>; | ||
}): Promise<boolean> { | ||
if (res.locals['authType'] !== 'connectSession') { | ||
return true; | ||
} | ||
|
||
const session = res.locals['connectSession']; | ||
if (!session.allowedIntegrations || session.allowedIntegrations.includes(config.unique_key)) { | ||
return true; | ||
} | ||
|
||
await logCtx.error('Integration not allowed by this token', { integration: config.unique_key, allowed: session.allowedIntegrations }); | ||
await logCtx.failed(); | ||
res.status(400).send({ error: { code: 'integration_not_allowed' } }); | ||
return false; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.