Skip to content

Commit

Permalink
feat: added xero oauth endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
oberoi-gaurav committed Jun 17, 2024
1 parent d4541b1 commit ef85633
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 3 deletions.
4 changes: 3 additions & 1 deletion integrationos-platform-oauth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
"dependencies": {
"axios": "^1.7.2",
"dotenv": "^16.4.5",
"express": "^4.19.2"
"express": "^4.19.2",
"jsonwebtoken": "^9.0.2"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/jsonwebtoken": "^9.0.6",
"ts-node": "^10.9.2",
"typescript": "^5.4.5"
}
Expand Down
2 changes: 0 additions & 2 deletions integrationos-platform-oauth/src/connections/slack/refresh.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import axios from "axios";
import qs from "qs";
import { DataObject, OAuthResponse } from "../../lib/types";

export const refresh = async ({ body }: DataObject): Promise<OAuthResponse> => {
Expand Down
80 changes: 80 additions & 0 deletions integrationos-platform-oauth/src/connections/xero/init.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
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",
};
};

export const init = async ({ body }: DataObject): Promise<OAuthResponse> => {
try {
const requestBody = {
grant_type: "authorization_code",
code: body.metadata?.code,
redirect_uri: body.metadata?.redirectUri,
};

const response = await axios.post(
`https://identity.xero.com/connect/token`,
requestBody,
{
headers: generateXeroHeaders(body.clientId, body.clientSecret),
}
);

const {
access_token: accessToken,
refresh_token: refreshToken,
expires_in: expiresIn,
token_type: tokenType,
} = response.data;

// Get tenant id details
const decodedToken = jwt.decode(accessToken) as {
authentication_event_id: string;
};

const tenantId = await axios.get("https://api.xero.com/connections", {
headers: {
authorization: "Bearer " + accessToken,
"Content-Type": "application/json",
},
});

if (!tenantId.data.length) {
throw new Error(`Failed to fetch tenantId from Xero API`);
}

const extractedTenantId = tenantId.data.find(
(tenant: any) =>
tenant.authEventId === decodedToken.authentication_event_id
)?.tenantId;

if (!extractedTenantId) {
throw new Error(`Failed to extract tenantId from Xero API response`);
}

const newMetadata = {
...body?.metadata,
tenantId: extractedTenantId,
};

return {
accessToken,
refreshToken,
expiresIn,
tokenType,
meta: {
...newMetadata,
},
};
} catch (error) {
throw new Error(`Error fetching access token for xero: ${error}`);
}
};
56 changes: 56 additions & 0 deletions integrationos-platform-oauth/src/connections/xero/refresh.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
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",
};
};

export const refresh = async ({ body }: DataObject): Promise<OAuthResponse> => {
try {
const {
OAUTH_CLIENT_ID: client_id,
OAUTH_CLIENT_SECRET: client_secret,
OAUTH_REFRESH_TOKEN: refresh_token,
OAUTH_REQUEST_PAYLOAD: { redirectUri: redirect_uri },
} = body;

const requestBody = {
grant_type: "refresh_token",
client_id,
refresh_token,
};

const response = await axios.post(
"https://identity.xero.com/connect/token",
requestBody,
{
headers: generateXeroHeaders(client_id, client_secret),
}
);

const {
access_token: accessToken,
refresh_token: refreshToken,
expires_in: expiresIn,
token_type: tokenType,
} = response.data;

return {
accessToken,
refreshToken,
expiresIn,
tokenType,
meta: {
...body?.OAUTH_METADATA?.meta,
},
};
} catch (error) {
throw new Error(`Error fetching refresh token for xero: ${error}`);
}
};

0 comments on commit ef85633

Please sign in to comment.