Files
infisical/backend/src/integrations/exchange.ts
T
2023-07-21 20:49:41 +07:00

409 lines
11 KiB
TypeScript

import { standardRequest } from "../config/request";
import {
INTEGRATION_AZURE_KEY_VAULT,
INTEGRATION_AZURE_TOKEN_URL,
INTEGRATION_BITBUCKET,
INTEGRATION_BITBUCKET_TOKEN_URL,
INTEGRATION_GITHUB,
INTEGRATION_GITHUB_TOKEN_URL,
INTEGRATION_GITLAB,
INTEGRATION_GITLAB_TOKEN_URL,
INTEGRATION_HEROKU,
INTEGRATION_HEROKU_TOKEN_URL,
INTEGRATION_NETLIFY,
INTEGRATION_NETLIFY_TOKEN_URL,
INTEGRATION_VERCEL,
INTEGRATION_VERCEL_TOKEN_URL,
} from "../variables";
import {
getClientIdAzure,
getClientIdBitBucket,
getClientIdGitHub,
getClientIdGitLab,
getClientIdNetlify,
getClientIdVercel,
getClientSecretAzure,
getClientSecretBitBucket,
getClientSecretGitHub,
getClientSecretGitLab,
getClientSecretHeroku,
getClientSecretNetlify,
getClientSecretVercel,
getSiteURL,
} from "../config";
interface ExchangeCodeAzureResponse {
token_type: string;
scope: string;
expires_in: number;
ext_expires_in: number;
access_token: string;
refresh_token: string;
id_token: string;
}
interface ExchangeCodeHerokuResponse {
token_type: string;
access_token: string;
expires_in: number;
refresh_token: string;
user_id: string;
session_nonce?: string;
}
interface ExchangeCodeVercelResponse {
token_type: string;
access_token: string;
installation_id: string;
user_id: string;
team_id?: string;
}
interface ExchangeCodeNetlifyResponse {
access_token: string;
token_type: string;
refresh_token: string;
scope: string;
created_at: number;
}
interface ExchangeCodeGithubResponse {
access_token: string;
scope: string;
token_type: string;
}
interface ExchangeCodeGitlabResponse {
access_token: string;
token_type: string;
expires_in: number;
refresh_token: string;
scope: string;
created_at: number;
}
interface ExchangeCodeBitBucketResponse {
access_token: string;
token_type: string;
expires_in: number;
refresh_token: string;
scopes: string;
state: string;
}
/**
* Return [accessToken], [accessExpiresAt], and [refreshToken] for OAuth2
* code-token exchange for integration named [integration]
* @param {Object} obj1
* @param {String} obj1.integration - name of integration
* @param {String} obj1.code - code for code-token exchange
* @returns {Object} obj
* @returns {String} obj.accessToken - access token for integration
* @returns {String} obj.refreshToken - refresh token for integration
* @returns {Date} obj.accessExpiresAt - date of expiration for access token
* @returns {String} obj.action - integration action for bot sequence
*/
const exchangeCode = async ({
integration,
code,
}: {
integration: string;
code: string;
}) => {
let obj = {} as any;
switch (integration) {
case INTEGRATION_AZURE_KEY_VAULT:
obj = await exchangeCodeAzure({
code,
});
break;
case INTEGRATION_HEROKU:
obj = await exchangeCodeHeroku({
code,
});
break;
case INTEGRATION_VERCEL:
obj = await exchangeCodeVercel({
code,
});
break;
case INTEGRATION_NETLIFY:
obj = await exchangeCodeNetlify({
code,
});
break;
case INTEGRATION_GITHUB:
obj = await exchangeCodeGithub({
code,
});
break;
case INTEGRATION_GITLAB:
obj = await exchangeCodeGitlab({
code,
});
break;
case INTEGRATION_BITBUCKET:
obj = await exchangeCodeBitBucket({
code,
});
break;
}
return obj;
};
/**
* Return [accessToken] for Azure OAuth2 code-token exchange
* @param param0
*/
const exchangeCodeAzure = async ({ code }: { code: string }) => {
const accessExpiresAt = new Date();
const res: ExchangeCodeAzureResponse = (
await standardRequest.post(
INTEGRATION_AZURE_TOKEN_URL,
new URLSearchParams({
grant_type: "authorization_code",
code: code,
scope: "https://vault.azure.net/.default openid offline_access",
client_id: await getClientIdAzure(),
client_secret: await getClientSecretAzure(),
redirect_uri: `${await getSiteURL()}/integrations/azure-key-vault/oauth2/callback`,
} as any)
)
).data;
accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + res.expires_in);
return {
accessToken: res.access_token,
refreshToken: res.refresh_token,
accessExpiresAt,
};
};
/**
* Return [accessToken], [accessExpiresAt], and [refreshToken] for Heroku
* OAuth2 code-token exchange
* @param {Object} obj1
* @param {Object} obj1.code - code for code-token exchange
* @returns {Object} obj2
* @returns {String} obj2.accessToken - access token for Heroku API
* @returns {String} obj2.refreshToken - refresh token for Heroku API
* @returns {Date} obj2.accessExpiresAt - date of expiration for access token
*/
const exchangeCodeHeroku = async ({ code }: { code: string }) => {
const accessExpiresAt = new Date();
const res: ExchangeCodeHerokuResponse = (
await standardRequest.post(
INTEGRATION_HEROKU_TOKEN_URL,
new URLSearchParams({
grant_type: "authorization_code",
code: code,
client_secret: await getClientSecretHeroku(),
} as any)
)
).data;
accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + res.expires_in);
return {
accessToken: res.access_token,
refreshToken: res.refresh_token,
accessExpiresAt,
};
};
/**
* Return [accessToken], [accessExpiresAt], and [refreshToken] for Vercel
* code-token exchange
* @param {Object} obj1
* @param {Object} obj1.code - code for code-token exchange
* @returns {Object} obj2
* @returns {String} obj2.accessToken - access token for Heroku API
* @returns {String} obj2.refreshToken - refresh token for Heroku API
* @returns {Date} obj2.accessExpiresAt - date of expiration for access token
*/
const exchangeCodeVercel = async ({ code }: { code: string }) => {
const res: ExchangeCodeVercelResponse = (
await standardRequest.post(
INTEGRATION_VERCEL_TOKEN_URL,
new URLSearchParams({
code: code,
client_id: await getClientIdVercel(),
client_secret: await getClientSecretVercel(),
redirect_uri: `${await getSiteURL()}/integrations/vercel/oauth2/callback`,
} as any)
)
).data;
return {
accessToken: res.access_token,
refreshToken: null,
accessExpiresAt: null,
teamId: res.team_id,
};
};
/**
* Return [accessToken], [accessExpiresAt], and [refreshToken] for Vercel
* code-token exchange
* @param {Object} obj1
* @param {Object} obj1.code - code for code-token exchange
* @returns {Object} obj2
* @returns {String} obj2.accessToken - access token for Heroku API
* @returns {String} obj2.refreshToken - refresh token for Heroku API
* @returns {Date} obj2.accessExpiresAt - date of expiration for access token
*/
const exchangeCodeNetlify = async ({ code }: { code: string }) => {
const res: ExchangeCodeNetlifyResponse = (
await standardRequest.post(
INTEGRATION_NETLIFY_TOKEN_URL,
new URLSearchParams({
grant_type: "authorization_code",
code: code,
client_id: await getClientIdNetlify(),
client_secret: await getClientSecretNetlify(),
redirect_uri: `${await getSiteURL()}/integrations/netlify/oauth2/callback`,
} as any)
)
).data;
const res2 = await standardRequest.get("https://api.netlify.com/api/v1/sites", {
headers: {
Authorization: `Bearer ${res.access_token}`,
},
});
const res3 = (
await standardRequest.get("https://api.netlify.com/api/v1/accounts", {
headers: {
Authorization: `Bearer ${res.access_token}`,
},
})
).data;
const accountId = res3[0].id;
return {
accessToken: res.access_token,
refreshToken: res.refresh_token,
accountId,
};
};
/**
* Return [accessToken], [accessExpiresAt], and [refreshToken] for Github
* code-token exchange
* @param {Object} obj1
* @param {Object} obj1.code - code for code-token exchange
* @returns {Object} obj2
* @returns {String} obj2.accessToken - access token for Github API
* @returns {String} obj2.refreshToken - refresh token for Github API
* @returns {Date} obj2.accessExpiresAt - date of expiration for access token
*/
const exchangeCodeGithub = async ({ code }: { code: string }) => {
const res: ExchangeCodeGithubResponse = (
await standardRequest.get(INTEGRATION_GITHUB_TOKEN_URL, {
params: {
client_id: await getClientIdGitHub(),
client_secret: await getClientSecretGitHub(),
code: code,
redirect_uri: `${await getSiteURL()}/integrations/github/oauth2/callback`,
},
headers: {
Accept: "application/json",
"Accept-Encoding": "application/json",
},
})
).data;
return {
accessToken: res.access_token,
refreshToken: null,
accessExpiresAt: null,
};
};
/**
* Return [accessToken], [accessExpiresAt], and [refreshToken] for Gitlab
* code-token exchange
* @param {Object} obj1
* @param {Object} obj1.code - code for code-token exchange
* @returns {Object} obj2
* @returns {String} obj2.accessToken - access token for Gitlab API
* @returns {String} obj2.refreshToken - refresh token for Gitlab API
* @returns {Date} obj2.accessExpiresAt - date of expiration for access token
*/
const exchangeCodeGitlab = async ({ code }: { code: string }) => {
const accessExpiresAt = new Date();
const res: ExchangeCodeGitlabResponse = (
await standardRequest.post(
INTEGRATION_GITLAB_TOKEN_URL,
new URLSearchParams({
grant_type: "authorization_code",
code: code,
client_id: await getClientIdGitLab(),
client_secret: await getClientSecretGitLab(),
redirect_uri: `${await getSiteURL()}/integrations/gitlab/oauth2/callback`,
} as any),
{
headers: {
"Accept-Encoding": "application/json",
},
}
)
).data;
accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + res.expires_in);
return {
accessToken: res.access_token,
refreshToken: res.refresh_token,
accessExpiresAt,
};
};
/**
* Return [accessToken], [accessExpiresAt], and [refreshToken] for BitBucket
* code-token exchange
* @param {Object} obj1
* @param {Object} obj1.code - code for code-token exchange
* @returns {Object} obj2
* @returns {String} obj2.accessToken - access token for BitBucket API
* @returns {String} obj2.refreshToken - refresh token for BitBucket API
* @returns {Date} obj2.accessExpiresAt - date of expiration for access token
*/
const exchangeCodeBitBucket = async ({ code }: { code: string }) => {
const accessExpiresAt = new Date();
const res: ExchangeCodeBitBucketResponse = (
await standardRequest.post(
INTEGRATION_BITBUCKET_TOKEN_URL,
new URLSearchParams({
grant_type: "authorization_code",
code: code,
client_id: await getClientIdBitBucket(),
client_secret: await getClientSecretBitBucket(),
redirect_uri: `${await getSiteURL()}/integrations/bitbucket/oauth2/callback`,
} as any),
{
headers: {
"Accept-Encoding": "application/json",
},
}
)
).data;
accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + res.expires_in);
return {
accessToken: res.access_token,
refreshToken: res.refresh_token,
accessExpiresAt,
};
};
export { exchangeCode };