diff --git a/integrationos-platform-oauth/src/connections/front/init.ts b/integrationos-platform-oauth/src/connections/front/init.ts index 98fbe906..9474e6c2 100644 --- a/integrationos-platform-oauth/src/connections/front/init.ts +++ b/integrationos-platform-oauth/src/connections/front/init.ts @@ -1,16 +1,6 @@ import axios from "axios"; import { DataObject, OAuthResponse } from "../../lib/types"; -import { differenceInSeconds } from "../../lib/helpers"; - -const generateHeaders = (clientId: string, clientSecret: string) => { - const credentials = clientId + ":" + clientSecret; - const encodedCredentials = Buffer.from(credentials).toString("base64"); - - return { - authorization: "Basic " + encodedCredentials, - "Content-Type": "application/x-www-form-urlencoded", - }; -}; +import { differenceInSeconds, generateBasicHeaders } from "../../lib/helpers"; export const init = async ({ body }: DataObject): Promise => { try { @@ -24,7 +14,7 @@ export const init = async ({ body }: DataObject): Promise => { "https://app.frontapp.com/oauth/token", requestBody, { - headers: generateHeaders(body.clientId, body.clientSecret), + headers: generateBasicHeaders(body.clientId, body.clientSecret), } ); diff --git a/integrationos-platform-oauth/src/connections/front/refresh.ts b/integrationos-platform-oauth/src/connections/front/refresh.ts index 88891a61..ddc80826 100644 --- a/integrationos-platform-oauth/src/connections/front/refresh.ts +++ b/integrationos-platform-oauth/src/connections/front/refresh.ts @@ -1,16 +1,6 @@ import axios from "axios"; import { DataObject, OAuthResponse } from "../../lib/types"; -import { differenceInSeconds } from "../../lib/helpers"; - -const generateHeaders = (clientId: string, clientSecret: string) => { - const credentials = clientId + ":" + clientSecret; - const encodedCredentials = Buffer.from(credentials).toString("base64"); - - return { - authorization: "Basic " + encodedCredentials, - "Content-Type": "application/x-www-form-urlencoded", - }; -}; +import { differenceInSeconds, generateBasicHeaders } from "../../lib/helpers"; export const refresh = async ({ body }: DataObject): Promise => { try { @@ -29,7 +19,7 @@ export const refresh = async ({ body }: DataObject): Promise => { "https://app.frontapp.com/oauth/token", requestBody, { - headers: generateHeaders(client_id, client_secret), + headers: generateBasicHeaders(client_id, client_secret), } ); diff --git a/integrationos-platform-oauth/src/connections/pipedrive/init.ts b/integrationos-platform-oauth/src/connections/pipedrive/init.ts index 1b65dc6a..33e1e241 100644 --- a/integrationos-platform-oauth/src/connections/pipedrive/init.ts +++ b/integrationos-platform-oauth/src/connections/pipedrive/init.ts @@ -1,15 +1,6 @@ import axios from "axios"; import { DataObject, OAuthResponse } from "../../lib/types"; - -const generateHeaders = (clientId: string, clientSecret: string) => { - const credentials = clientId + ":" + clientSecret; - const encodedCredentials = Buffer.from(credentials).toString("base64"); - - return { - authorization: "Basic " + encodedCredentials, - "Content-Type": "application/x-www-form-urlencoded", - }; -}; +import { generateBasicHeaders } from "../../lib/helpers"; export const init = async ({ body }: DataObject): Promise => { try { @@ -23,7 +14,7 @@ export const init = async ({ body }: DataObject): Promise => { "https://oauth.pipedrive.com/oauth/token", requestBody, { - headers: generateHeaders(body.clientId, body.clientSecret), + headers: generateBasicHeaders(body.clientId, body.clientSecret), } ); diff --git a/integrationos-platform-oauth/src/connections/pipedrive/refresh.ts b/integrationos-platform-oauth/src/connections/pipedrive/refresh.ts index 808ee155..2203d3d2 100644 --- a/integrationos-platform-oauth/src/connections/pipedrive/refresh.ts +++ b/integrationos-platform-oauth/src/connections/pipedrive/refresh.ts @@ -1,15 +1,6 @@ import axios from "axios"; import { DataObject, OAuthResponse } from "../../lib/types"; - -const generateHeaders = (clientId: string, clientSecret: string) => { - const credentials = clientId + ":" + clientSecret; - const encodedCredentials = Buffer.from(credentials).toString("base64"); - - return { - authorization: "Basic " + encodedCredentials, - "Content-Type": "application/x-www-form-urlencoded", - }; -}; +import { generateBasicHeaders } from "../../lib/helpers"; export const refresh = async ({ body }: DataObject): Promise => { try { @@ -28,7 +19,7 @@ export const refresh = async ({ body }: DataObject): Promise => { "https://oauth.pipedrive.com/oauth/token", requestBody, { - headers: generateHeaders(client_id, client_secret), + headers: generateBasicHeaders(client_id, client_secret), } ); diff --git a/integrationos-platform-oauth/src/connections/quickbooks/init.ts b/integrationos-platform-oauth/src/connections/quickbooks/init.ts index 6f1be027..6a20abf6 100644 --- a/integrationos-platform-oauth/src/connections/quickbooks/init.ts +++ b/integrationos-platform-oauth/src/connections/quickbooks/init.ts @@ -1,6 +1,6 @@ import axios from "axios"; import { DataObject, OAuthResponse } from "../../lib/types"; -import { base64encode } from "../../lib/helpers"; +import { generateBasicHeaders } from "../../lib/helpers"; export const init = async ({ body }: DataObject): Promise => { try { @@ -15,9 +15,7 @@ export const init = async ({ body }: DataObject): Promise => { requestBody, { headers: { - Authorization: - "Basic " + base64encode(body.clientId + ":" + body.clientSecret), - "Content-Type": "application/x-www-form-urlencoded", + ...generateBasicHeaders(body.clientId, body.clientSecret), Accept: "application/json", }, } diff --git a/integrationos-platform-oauth/src/connections/quickbooks/refresh.ts b/integrationos-platform-oauth/src/connections/quickbooks/refresh.ts index 44faeb62..13c18ff1 100644 --- a/integrationos-platform-oauth/src/connections/quickbooks/refresh.ts +++ b/integrationos-platform-oauth/src/connections/quickbooks/refresh.ts @@ -1,6 +1,6 @@ import axios from "axios"; import { DataObject, OAuthResponse } from "../../lib/types"; -import { base64encode } from "../../lib/helpers"; +import { generateBasicHeaders } from "../../lib/helpers"; export const refresh = async ({ body }: DataObject): Promise => { try { @@ -20,9 +20,7 @@ export const refresh = async ({ body }: DataObject): Promise => { requestBody, { headers: { - Authorization: - "Basic " + base64encode(client_id + ":" + client_secret), - "Content-Type": "application/x-www-form-urlencoded", + ...generateBasicHeaders(client_id, client_secret), Accept: "application/json", }, } diff --git a/integrationos-platform-oauth/src/connections/salesforce/init.ts b/integrationos-platform-oauth/src/connections/salesforce/init.ts new file mode 100644 index 00000000..bc00ec4d --- /dev/null +++ b/integrationos-platform-oauth/src/connections/salesforce/init.ts @@ -0,0 +1,108 @@ +import axios from "axios"; +import qs from "qs"; +import { DataObject, OAuthResponse } from "../../lib/types"; +import { differenceInSeconds } from "../../lib/helpers"; + +const getListAllId = async (accessToken: string, url: string) => { + const response = await axios.get(url, { + headers: { + Authorization: `Bearer ${accessToken}`, + }, + }); + const { + data: { listviews }, + } = response; + + if (listviews?.length) { + const filteredListviews = listviews.filter((lv: any) => + lv.label.startsWith("All") + ); + if (filteredListviews.length) { + return filteredListviews[0].id; + } + } + + return null; +}; + +export const init = async ({ body }: DataObject): Promise => { + try { + const { + clientId, + clientSecret, + metadata: { + code, + formData: { SALESFORCE_DOMAIN }, // Example: https://flow-fun-2719.my.salesforce.com + redirectUri, + }, + } = body; + const baseUrl = `${SALESFORCE_DOMAIN}/services/oauth2`; + + const requestBody = { + grant_type: "authorization_code", + code, + redirect_uri: redirectUri, + client_id: body.clientId, + client_secret: body.clientSecret, + }; + const response = await axios({ + url: `${baseUrl}/token`, + method: "POST", + headers: { "Content-Type": "application/x-www-form-urlencoded" }, + data: qs.stringify(requestBody), + }); + + const { + data: { + access_token: accessToken, + refresh_token: refreshToken, + token_type: tokenType, + }, + } = response; + + // Get expiry time through introspection + const introspection = await axios({ + url: `${baseUrl}/introspect`, + method: "POST", + headers: { "Content-Type": "application/x-www-form-urlencoded" }, + data: qs.stringify({ + client_id: clientId, + client_secret: clientSecret, + token: accessToken, + token_type_hint: "access_token", + }), + }); + const { + data: { exp: expiresAt }, + } = introspection; + // Converting expiresAt to date object and getting difference in seconds + const expiresIn = differenceInSeconds(new Date(expiresAt * 1000)); + + // Get all listview ids and save in meta for getMany + const listViewBaseUrl = `${SALESFORCE_DOMAIN}/services/data/v61.0/sobjects`; + const contactListView = `${listViewBaseUrl}/contact/listviews`; + const opportunityListView = `${listViewBaseUrl}/opportunity/listviews`; + const leadListView = `${listViewBaseUrl}/lead/listviews`; + + const contactListId = await getListAllId(accessToken, contactListView); + const opportunityListId = await getListAllId( + accessToken, + opportunityListView + ); + const leadListId = await getListAllId(accessToken, leadListView); + + return { + accessToken, + refreshToken, + expiresIn, + tokenType, + meta: { + contactListId, + opportunityListId, + leadListId, + }, + }; + } catch (error) { + throw new Error(`Error fetching access token for Salesforce: ${error}`); + } +}; diff --git a/integrationos-platform-oauth/src/connections/salesforce/refresh.ts b/integrationos-platform-oauth/src/connections/salesforce/refresh.ts new file mode 100644 index 00000000..e51604df --- /dev/null +++ b/integrationos-platform-oauth/src/connections/salesforce/refresh.ts @@ -0,0 +1,64 @@ +import axios from "axios"; +import qs from "qs"; +import { DataObject, OAuthResponse } from "../../lib/types"; +import { differenceInSeconds, generateBasicHeaders } from "../../lib/helpers"; + +export const refresh = async ({ body }: DataObject): Promise => { + try { + const { + OAUTH_CLIENT_ID: clientId, + OAUTH_CLIENT_SECRET: clientSecret, + OAUTH_REFRESH_TOKEN: refresh_token, + OAUTH_REQUEST_PAYLOAD: { + formData: { SALESFORCE_DOMAIN }, + }, + OAUTH_METADATA, + } = body; + const baseUrl = `${SALESFORCE_DOMAIN}/services/oauth2`; + + const requestBody = { + grant_type: "refresh_token", + refresh_token, + }; + const response = await axios({ + url: `${baseUrl}/token`, + method: "POST", + headers: generateBasicHeaders(clientId, clientSecret), + data: qs.stringify(requestBody), + }); + + const { + data: { access_token: accessToken, token_type: tokenType }, + } = response; + + // Get expiry time through introspection + const introspection = await axios({ + url: `${baseUrl}/introspect`, + method: "POST", + headers: { "Content-Type": "application/x-www-form-urlencoded" }, + data: qs.stringify({ + client_id: clientId, + client_secret: clientSecret, + token: accessToken, + token_type_hint: "access_token", + }), + }); + const { + data: { exp: expiresAt }, + } = introspection; + // Converting expiresAt to date object and getting difference in seconds + const expiresIn = differenceInSeconds(new Date(expiresAt * 1000)); + + return { + accessToken, + refreshToken: refresh_token, + expiresIn, + tokenType, + meta: { + ...OAUTH_METADATA?.meta, + }, + }; + } catch (error) { + throw new Error(`Error fetching refresh token for Salesforce: ${error}`); + } +}; diff --git a/integrationos-platform-oauth/src/connections/xero/init.ts b/integrationos-platform-oauth/src/connections/xero/init.ts index a9f6b632..d121ee4f 100644 --- a/integrationos-platform-oauth/src/connections/xero/init.ts +++ b/integrationos-platform-oauth/src/connections/xero/init.ts @@ -1,16 +1,7 @@ import axios from "axios"; import jwt from "jsonwebtoken"; import { DataObject, OAuthResponse } from "../../lib/types"; - -const generateXeroHeaders = (clientId: string, clientSecret: string) => { - const credentials = clientId + ":" + clientSecret; - const encodedCredentials = Buffer.from(credentials).toString("base64"); - - return { - authorization: "Basic " + encodedCredentials, - "Content-Type": "application/x-www-form-urlencoded", - }; -}; +import { generateBasicHeaders } from "../../lib/helpers"; export const init = async ({ body }: DataObject): Promise => { try { @@ -24,7 +15,7 @@ export const init = async ({ body }: DataObject): Promise => { `https://identity.xero.com/connect/token`, requestBody, { - headers: generateXeroHeaders(body.clientId, body.clientSecret), + headers: generateBasicHeaders(body.clientId, body.clientSecret), } ); diff --git a/integrationos-platform-oauth/src/connections/xero/refresh.ts b/integrationos-platform-oauth/src/connections/xero/refresh.ts index 34e3b7c8..5a69e688 100644 --- a/integrationos-platform-oauth/src/connections/xero/refresh.ts +++ b/integrationos-platform-oauth/src/connections/xero/refresh.ts @@ -1,15 +1,6 @@ import axios from "axios"; import { DataObject, OAuthResponse } from "../../lib/types"; - -const generateXeroHeaders = (clientId: string, clientSecret: string) => { - const credentials = clientId + ":" + clientSecret; - const encodedCredentials = Buffer.from(credentials).toString("base64"); - - return { - authorization: "Basic " + encodedCredentials, - "Content-Type": "application/x-www-form-urlencoded", - }; -}; +import { generateBasicHeaders } from "../../lib/helpers"; export const refresh = async ({ body }: DataObject): Promise => { try { @@ -29,7 +20,7 @@ export const refresh = async ({ body }: DataObject): Promise => { "https://identity.xero.com/connect/token", requestBody, { - headers: generateXeroHeaders(client_id, client_secret), + headers: generateBasicHeaders(client_id, client_secret), } ); diff --git a/integrationos-platform-oauth/src/lib/helpers.ts b/integrationos-platform-oauth/src/lib/helpers.ts index 5d7eec3c..bbe49630 100644 --- a/integrationos-platform-oauth/src/lib/helpers.ts +++ b/integrationos-platform-oauth/src/lib/helpers.ts @@ -42,3 +42,16 @@ export const differenceInSeconds = (argDate: Date) => { return Math.floor(differenceInSeconds); }; + +export const generateBasicHeaders = ( + clientId: string, + clientSecret: string +) => { + const credentials = clientId + ":" + clientSecret; + const encodedCredentials = Buffer.from(credentials).toString("base64"); + + return { + Authorization: "Basic " + encodedCredentials, + "Content-Type": "application/x-www-form-urlencoded", + }; +};