@bigid/apps-infrastructure-node-js 0.1.0 → 1.180.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/.github/workflows/bigid_config +3 -0
  2. package/.github/workflows/npmjs_config +3 -0
  3. package/.github/workflows/private-registry-publish.yml +16 -0
  4. package/.github/workflows/public-registry-publish.yml +14 -0
  5. package/CODEOWNERS +1 -0
  6. package/README.md +31 -2
  7. package/jsdoc.json +14 -0
  8. package/lib/abstractProviders/configureProvider.d.ts +10 -0
  9. package/lib/{routes/router.js → abstractProviders/configureProvider.js} +7 -3
  10. package/lib/abstractProviders/executionProvider.d.ts +3 -2
  11. package/lib/abstractProviders/executionProvider.js +5 -10
  12. package/lib/abstractProviders/index.d.ts +1 -0
  13. package/lib/abstractProviders/index.js +3 -1
  14. package/lib/abstractProviders/logsProvider.js +9 -1
  15. package/lib/abstractProviders/manifestProvider.d.ts +2 -1
  16. package/lib/dto/actionResponseDetails.d.ts +3 -1
  17. package/lib/dto/actionResponseDetails.js +2 -1
  18. package/lib/dto/executionContext.d.ts +8 -5
  19. package/lib/dto/executionContext.js +0 -14
  20. package/lib/dto/index.d.ts +1 -1
  21. package/lib/dto/index.js +1 -3
  22. package/lib/dto/subExecutionItem.d.ts +7 -0
  23. package/lib/dto/subExecutionItem.js +12 -0
  24. package/lib/dto/tenantRegistration.d.ts +5 -0
  25. package/lib/index.d.ts +1 -1
  26. package/lib/index.js +16 -2
  27. package/lib/server.d.ts +11 -7
  28. package/lib/server.js +16 -12
  29. package/lib/services/actionsHubService.d.ts +45 -0
  30. package/lib/services/actionsHubService.js +105 -0
  31. package/lib/services/batchProcessManager.d.ts +2 -0
  32. package/lib/services/batchProcessManager.js +45 -0
  33. package/lib/services/bigidProxyService.d.ts +28 -13
  34. package/lib/services/bigidProxyService.js +67 -55
  35. package/lib/services/dataSourceService.d.ts +4 -0
  36. package/lib/services/dataSourceService.js +26 -0
  37. package/lib/services/encryptionService.d.ts +1 -0
  38. package/lib/services/encryptionService.js +67 -0
  39. package/lib/services/index.d.ts +3 -0
  40. package/lib/services/index.js +12 -1
  41. package/lib/services/schedulerService.d.ts +11 -0
  42. package/lib/services/schedulerService.js +41 -0
  43. package/lib/utils/appLogger.d.ts +10 -1
  44. package/lib/utils/appLogger.js +38 -7
  45. package/lib/utils/index.d.ts +1 -1
  46. package/lib/utils/index.js +15 -3
  47. package/lib/utils/tokenUtil.d.ts +3 -0
  48. package/lib/utils/tokenUtil.js +62 -0
  49. package/package.json +11 -4
  50. package/src/abstractProviders/configureProvider.ts +15 -0
  51. package/src/abstractProviders/executionProvider.ts +5 -7
  52. package/src/abstractProviders/index.ts +1 -0
  53. package/src/abstractProviders/logsProvider.ts +11 -3
  54. package/src/abstractProviders/manifestProvider.ts +3 -1
  55. package/src/dto/actionResponseDetails.ts +5 -1
  56. package/src/dto/executionContext.ts +8 -23
  57. package/src/dto/index.ts +2 -2
  58. package/src/dto/subExecutionItem.ts +13 -0
  59. package/src/dto/tenantRegistration.ts +5 -0
  60. package/src/index.ts +17 -1
  61. package/src/server.ts +33 -20
  62. package/src/services/actionsHubService.ts +141 -0
  63. package/src/services/batchProcessManager.ts +39 -0
  64. package/src/services/bigidProxyService.ts +84 -62
  65. package/src/services/dataSourceService.ts +20 -0
  66. package/src/services/encryptionService.ts +44 -0
  67. package/src/services/index.ts +5 -1
  68. package/src/services/schedulerService.ts +39 -0
  69. package/src/utils/appLogger.ts +44 -6
  70. package/src/utils/index.ts +1 -1
  71. package/src/utils/tokenUtil.ts +65 -0
  72. package/.dcignore +0 -1547
  73. package/.idea/apps-infrastructure-node-js.iml +0 -9
  74. package/.idea/misc.xml +0 -6
  75. package/.idea/modules.xml +0 -8
  76. package/.idea/prettier.xml +0 -7
  77. package/.idea/runConfigurations.xml +0 -10
  78. package/.idea/snyk.project.settings.xml +0 -6
  79. package/.idea/vcs.xml +0 -6
  80. package/lib/appTypes/actionResponseDetails.d.ts +0 -6
  81. package/lib/appTypes/executionContext.d.ts +0 -10
  82. package/lib/appTypes/executionContext.js +0 -2
  83. package/lib/appTypes/index.d.ts +0 -2
  84. package/lib/appTypes/index.js +0 -2
  85. package/lib/dto/keysValuesToStore.d.ts +0 -5
  86. package/lib/dto/keysValuesToStore.js +0 -19
  87. package/lib/routes/router.d.ts +0 -1
  88. /package/lib/{appTypes/actionResponseDetails.js → dto/tenantRegistration.js} +0 -0
@@ -1,34 +1,39 @@
1
1
  import { createReadStream } from 'fs';
2
2
  import { Agent } from 'https';
3
- import { ExecutionContext } from '../dto';
3
+ import { ActionResponseDetails, ExecutionContext } from '../dto';
4
4
  import FormData from 'form-data';
5
5
 
6
6
  import axios from 'axios';
7
- import { ActionResponseDetails } from '../dto/actionResponseDetails';
8
- import { appLogger } from '../utils';
9
-
10
- const RequestMethod = {
11
- POST: 'post',
12
- GET: 'get',
13
- PUT: 'put',
14
- PATCH: 'patch',
15
- DELETE: 'delete',
16
- };
17
-
18
- let bigidUrl: string;
19
- let bigidUpdateStatusUrl: string;
20
- let bigidToken: string;
21
- let proxyTpaId: string;
7
+ import { logError, logInfo } from '../utils';
8
+ import { TenantRegistration } from '../dto/tenantRegistration';
9
+
10
+ export enum RequestMethod {
11
+ POST = 'post',
12
+ GET = 'get',
13
+ PUT = 'put',
14
+ PATCH = 'patch',
15
+ DELETE = 'delete',
16
+ }
22
17
 
23
- export const initBigIDProxy = (bigIdUrl: string, callBackUrl: string, bigIdToken: string, tpaId: string) => {
24
- bigidUrl = bigIdUrl;
25
- bigidUpdateStatusUrl = callBackUrl;
26
- bigidToken = bigIdToken;
27
- proxyTpaId = tpaId;
18
+ export const getTenantRegistrations = async (bigidToken: string): Promise<TenantRegistration[]> => {
19
+ const {
20
+ data: {
21
+ data: { tenants },
22
+ },
23
+ } = await doCallToUrl(
24
+ bigidToken,
25
+ RequestMethod.GET,
26
+ `${process.env.BIGID_BASE_URL}/api/v1/tenant-service/applications/registrations`,
27
+ );
28
+ return tenants;
28
29
  };
29
-
30
- const doCallToUrl = async (requestMethod: string, endpoint: string, bodyJson?: ActionResponseDetails) => {
31
- appLogger.info('--> bigid-proxy::callBigIdApi: [%s] %s', requestMethod, endpoint);
30
+ export const doCallToUrl = async (
31
+ bigidToken: string,
32
+ requestMethod: RequestMethod,
33
+ endpoint: string,
34
+ bodyJson?: Record<string, any>,
35
+ ) => {
36
+ logInfo(`--> bigid-proxy::callBigIdApi: [${requestMethod}] endpoint: ${endpoint}`);
32
37
  try {
33
38
  const headers = {
34
39
  Accept: 'application/json, text/plain, */*',
@@ -51,63 +56,82 @@ const doCallToUrl = async (requestMethod: string, endpoint: string, bodyJson?: A
51
56
 
52
57
  const res = await axios(requestObj);
53
58
 
54
- appLogger.info('<-- bigid-proxy::callBigIdApi: %s success', endpoint);
59
+ logInfo(`<-- bigid-proxy::callBigIdApi: ${endpoint} success`);
55
60
  return res;
56
61
  } catch (error: any) {
57
- appLogger.info('<-- bigid-proxy::callBigIdApi: error calling bigID on %s %o', endpoint, error);
58
- appLogger.error(error);
62
+ logInfo(`<-- bigid-proxy::callBigIdApi: error calling bigID on endpoint: ${endpoint}, error: ${error}`);
63
+ logError(error.message);
59
64
  return error?.message;
60
65
  }
61
66
  };
62
67
 
63
68
  async function callBigIdApi(
64
- requestMethod: string,
69
+ executionContext: ExecutionContext,
70
+ requestMethod: RequestMethod,
65
71
  endpoint: string,
66
72
  bodyJson?: ActionResponseDetails,
67
73
  useEndpointWithoutBigIdBasePath?: boolean,
68
74
  ) {
69
- const url = useEndpointWithoutBigIdBasePath ? endpoint : bigidUrl + endpoint;
70
- return await doCallToUrl(requestMethod, url, bodyJson);
75
+ const url = useEndpointWithoutBigIdBasePath ? endpoint : executionContext.bigidBaseUrl + endpoint;
76
+ return await doCallToUrl(executionContext.bigidToken, requestMethod, url, bodyJson);
71
77
  }
72
78
 
73
79
  /**
74
80
  * This method receives a message object to update BigID regarding the current state of the action execution
75
81
  * (should be used in case of an async actions)
76
- * @param ActionResponseDetails
82
+ * @param executionContext
83
+ * @param actionResponseDetails
77
84
  */
78
- export const updateActionStatusToBigID = async (actionResponseDetails: ActionResponseDetails) =>
79
- await callBigIdApi(RequestMethod.PUT, `${bigidUpdateStatusUrl}`, actionResponseDetails, true);
85
+ export const updateActionStatusToBigID = async (
86
+ executionContext: ExecutionContext,
87
+ actionResponseDetails: ActionResponseDetails,
88
+ ) =>
89
+ await callBigIdApi(
90
+ executionContext,
91
+ RequestMethod.PUT,
92
+ executionContext.updateResultCallback,
93
+ actionResponseDetails,
94
+ true,
95
+ );
80
96
 
81
97
  /**
82
98
  *
99
+ * @param executionContext
83
100
  * @param endpoint - the endpoint in BigID, used for GET request. e.g - {BigIDBaseUrl}/ds_connections
84
101
  * @return - String containing the response from BigID
85
102
  */
86
- export const executeHttpGet = async (endpoint: string) => await callBigIdApi(RequestMethod.GET, endpoint);
103
+ export const executeHttpGet = async (executionContext: ExecutionContext, endpoint: string) =>
104
+ await callBigIdApi(executionContext, RequestMethod.GET, endpoint);
87
105
 
88
106
  /**
89
107
  * the endpoint in BigID, used for POST requests. e.g - {BigIDBaseUrl}/scan
90
108
  */
91
- export const executeHttpPost = async (endpoint: string, actionResponseDetails: ActionResponseDetails) =>
92
- await callBigIdApi(RequestMethod.POST, endpoint, actionResponseDetails);
109
+ export const executeHttpPost = async (executionContext: ExecutionContext, endpoint: string, obj: any) =>
110
+ await callBigIdApi(executionContext, RequestMethod.POST, endpoint, obj);
93
111
 
94
112
  /**
95
113
  * the endpoint in BigID, used for POST requests. e.g - {BigIDBaseUrl}/scan
96
114
  */
97
- export const executeHttpPut = async (endpoint: string, obj: any) =>
98
- await callBigIdApi(RequestMethod.PUT, endpoint, obj);
115
+ export const executeHttpPut = async (executionContext: ExecutionContext, endpoint: string, obj: any) =>
116
+ await callBigIdApi(executionContext, RequestMethod.PUT, endpoint, obj);
99
117
 
100
- export const uploadAttachment = (filePathToUpload: string) => {
118
+ /**
119
+ * the endpoint in BigID, used for DELETE requests.
120
+ */
121
+ export const executeHttpDelete = async (executionContext: ExecutionContext, endpoint: string) =>
122
+ await callBigIdApi(executionContext, RequestMethod.DELETE, endpoint);
123
+
124
+ export const uploadAttachment = (executionContext: ExecutionContext, filePathToUpload: string) => {
101
125
  const formData = new FormData();
102
126
  formData.append('file', createReadStream(filePathToUpload));
103
127
 
104
128
  const headers = {
105
129
  'Content-Type': `multipart/form-data; boundary=${formData.getBoundary()}`,
106
- Authorization: bigidToken,
130
+ Authorization: executionContext.bigidToken,
107
131
  };
108
132
  const requestObj: Record<string, any> = {
109
133
  method: RequestMethod.POST,
110
- url: `${bigidUpdateStatusUrl}/attachment`,
134
+ url: `${executionContext.updateResultCallback}/attachment`,
111
135
  headers: headers,
112
136
  httpsAgent: new Agent({
113
137
  rejectUnauthorized: false,
@@ -117,34 +141,32 @@ export const uploadAttachment = (filePathToUpload: string) => {
117
141
  return axios(requestObj);
118
142
  };
119
143
 
120
- export const getAppStorage = () => executeHttpGet(`tpa/${proxyTpaId}/storage`);
144
+ export const getAppStorage = (executionContext: ExecutionContext) =>
145
+ executeHttpGet(executionContext, `tpa/${executionContext.tpaId}/storage`);
121
146
 
122
- export const getValueFromAppStorage = async (key: string) => {
123
- const { data } = await executeHttpGet(`tpa/${proxyTpaId}/storage/key/${key}`);
147
+ export const getValueFromAppStorage = async (executionContext: ExecutionContext, key: string): Promise<string> => {
148
+ const { data } = await executeHttpGet(executionContext, `tpa/${executionContext.tpaId}/storage/key/${key}`);
124
149
  return data === 'Key not found' ? null : data.value;
125
150
  };
126
151
 
127
- export const saveInStorage = async (keyToStore: any, valueToStore: any) =>
128
- await executeHttpPut(`/tpa/${proxyTpaId}/storage`, {
152
+ export const deleteKeyFromAppStorage = async (executionContext: ExecutionContext, key: string) => {
153
+ await executeHttpDelete(executionContext, `tpa/${executionContext.tpaId}/storage/key/${key}`);
154
+ };
155
+
156
+ export const sendBiEvent = async (executionContext: ExecutionContext, eventType: string, data: Object) => {
157
+ return executeHttpPost(executionContext, 'bi-events', { event_type: eventType, data: data });
158
+ };
159
+
160
+ export const saveInStorage = async (
161
+ executionContext: ExecutionContext,
162
+ keyToStore: any,
163
+ valueToStore: any,
164
+ ): Promise<void> =>
165
+ await executeHttpPut(executionContext, `/tpa/${executionContext.tpaId}/storage`, {
129
166
  keysValues: [
130
167
  {
131
168
  key: keyToStore,
132
169
  value: valueToStore,
133
170
  },
134
171
  ],
135
- });
136
-
137
- export const setValuesForBigIDProxy = (executionContext: ExecutionContext) => {
138
- if (!executionContext.bigidBaseUrl || !executionContext.bigidToken) {
139
- appLogger.error(
140
- `Missing bigidUrl and/or bigidToken. bigidUrl=${executionContext.bigidBaseUrl}, bigidToken=${executionContext.bigidToken}`,
141
- );
142
- return;
143
- }
144
- initBigIDProxy(
145
- executionContext.bigidBaseUrl,
146
- executionContext.updateResultCallback,
147
- executionContext.bigidToken,
148
- executionContext.tpaId,
149
- );
150
- };
172
+ });
@@ -0,0 +1,20 @@
1
+ import { decrypt } from './encryptionService';
2
+ import { ExecutionContext } from '../dto';
3
+ import { executeHttpGet } from './bigidProxyService';
4
+
5
+ export const fetchDataSourceCredentials = async (
6
+ executionContext: ExecutionContext,
7
+ dataSourceName: string,
8
+ ): Promise<{ [key: string]: string }> => {
9
+ const res = await executeHttpGet(
10
+ executionContext,
11
+ '/tpa/' + executionContext.tpaId + '/credentials/' + dataSourceName.replace(' ', '%20'),
12
+ );
13
+ const resData = res.data;
14
+ return Object.keys(resData).reduce((acc: { [key: string]: string }, key) => {
15
+ const credentialObject = resData[key];
16
+ const credentialValue = credentialObject.value?.toString();
17
+ acc[key] = credentialObject.encrypted ? decrypt(credentialValue) : credentialValue;
18
+ return acc;
19
+ }, {});
20
+ };
@@ -0,0 +1,44 @@
1
+ import * as crypto from 'crypto';
2
+
3
+ type IvAndText = { iv: string | Buffer; cleanText: string | NodeJS.ArrayBufferView };
4
+
5
+ enum Defaults {
6
+ SHA_ALGORITHM = 'sha256',
7
+ AES_ALGORITHM = 'aes-256-cbc',
8
+ IV = '4e5Wa71fYoT7MFEX',
9
+ BASE64_ENC = 'base64',
10
+ UTF8_ENC = 'utf8',
11
+ DOLLAR_DEL = '$',
12
+ SECRET_KEY = 'SECRET_KEY',
13
+ }
14
+
15
+ export const decrypt = (encryptedText: string): string => {
16
+ const ivAndText = getAndUseOldIvOrNew(encryptedText);
17
+ const decipher = crypto.createDecipheriv(Defaults.AES_ALGORITHM, makeKey(), ivAndText.iv);
18
+ let decryptedData = decipher.update(ivAndText.cleanText as string, Defaults.BASE64_ENC, Defaults.UTF8_ENC);
19
+ decryptedData += decipher.final(Defaults.UTF8_ENC);
20
+ return decryptedData;
21
+ };
22
+
23
+ const makeKey = (): Buffer => {
24
+ const md = crypto.createHash(Defaults.SHA_ALGORITHM);
25
+ try {
26
+ const secretKey = process.env.APPLICATION_CREDENTIALS_KEY ?? '';
27
+ const key = md.update(secretKey).digest();
28
+ return key;
29
+ } catch (error) {
30
+ throw new Error("Can't create a key. Check for APPLICATION_CREDENTIALS_KEY in your environment variables.");
31
+ }
32
+ };
33
+
34
+ const getAndUseOldIvOrNew = (text: string | Buffer): IvAndText => {
35
+ const ivAndText: IvAndText = { iv: Defaults.IV, cleanText: text };
36
+ if (text.includes(Defaults.DOLLAR_DEL)) {
37
+ const [cipher_blob, ...cipher_blob2] = (text as string).split(Defaults.DOLLAR_DEL);
38
+ const cipherBlobPartTwo = cipher_blob2.join(Defaults.DOLLAR_DEL);
39
+ ivAndText.iv = Buffer.from(cipher_blob, Defaults.BASE64_ENC);
40
+ ivAndText.cleanText = Buffer.from(cipherBlobPartTwo, Defaults.BASE64_ENC);
41
+ }
42
+
43
+ return ivAndText;
44
+ };
@@ -1 +1,5 @@
1
- export * from './bigidProxyService';
1
+ export * from './bigidProxyService';
2
+ export * from './dataSourceService';
3
+ export * from './actionsHubService';
4
+
5
+ export { scheduleFunction, unscheduleAllFunctions, unscheduleFunction } from './schedulerService';
@@ -0,0 +1,39 @@
1
+ import { BatchFunction, handleBatchProcess } from './batchProcessManager';
2
+ import { Job, scheduleJob, scheduledJobs } from 'node-schedule';
3
+ import { getAccessTokenFromRefreshToken } from '../utils/tokenUtil';
4
+
5
+ const scheduleSingleTenantProcess = async (
6
+ batchUN: string,
7
+ cronExpression: string,
8
+ callback: BatchFunction,
9
+ ): Promise<void> => {
10
+ if (!process.env.BIGID_BASE_URL || !process.env.BIGID_REFRESH_TOKEN)
11
+ throw new Error('Please make sure to fill out BIGID_BASE_URL && BIGID_REFRESH_TOKEN environment variables.');
12
+
13
+ const bigidAccessToken = await getAccessTokenFromRefreshToken(process.env.BIGID_REFRESH_TOKEN);
14
+
15
+ scheduleJob(batchUN, cronExpression, () =>
16
+ callback('SINGLE_TENANT', process.env.BIGID_BASE_URL as string, bigidAccessToken),
17
+ );
18
+ };
19
+
20
+ /**
21
+ * use this method to call a function execution according to a cron expression.
22
+ *
23
+ * @param batchUN - name for the job.
24
+ * @param cronExpression - the cron expression for the function call.
25
+ * @param callback - the function that will be called.
26
+ */
27
+ export const scheduleFunction = (batchUN: string, cronExpression: string, callback: BatchFunction): void => {
28
+ process.env.MULTI_TENANT_MODE
29
+ ? scheduleJob(batchUN, cronExpression, () => handleBatchProcess(callback))
30
+ : scheduleSingleTenantProcess(batchUN, cronExpression, callback);
31
+ };
32
+
33
+ export const unscheduleFunction = (batchUN: string): void => {
34
+ const jobToCancel: Job = scheduledJobs[batchUN];
35
+ jobToCancel.cancel();
36
+ };
37
+
38
+ export const unscheduleAllFunctions = (): void =>
39
+ Object.keys(scheduledJobs).forEach(jobName => scheduledJobs[jobName].cancel());
@@ -1,6 +1,14 @@
1
1
  import { configure, getLogger } from 'log4js';
2
2
  import { LOGS_PATH } from './constants';
3
3
 
4
+ type LogMetadata = {
5
+ tenantId: string;
6
+ functionName: string;
7
+ scriptName: string;
8
+ };
9
+ const USER_LOG_BACKUPS = parseInt(process.env.LOG_BACKUPS + "") || 3;
10
+ const MAX_BACKUPS = 10;
11
+
4
12
  configure({
5
13
  appenders: {
6
14
  console: { type: 'stdout', layout: { type: 'colored' } },
@@ -9,13 +17,43 @@ configure({
9
17
  layout: { type: 'basic' },
10
18
  filename: LOGS_PATH,
11
19
  compress: true,
12
- daysToKeep: 14,
13
- keepFileExt: true
14
- }
20
+ numBackups: USER_LOG_BACKUPS > MAX_BACKUPS ? MAX_BACKUPS : USER_LOG_BACKUPS,
21
+ keepFileExt: true,
22
+ },
15
23
  },
16
24
  categories: {
17
- default: { appenders: ['console', 'dateFile'], level: process.env.LOG_LEVEL || 'info' }
18
- }
25
+ default: { appenders: ['console', 'dateFile'], level: process.env.LOG_LEVEL || 'info' },
26
+ },
19
27
  });
20
28
 
21
- export const appLogger = getLogger();
29
+ const appLogger = getLogger();
30
+
31
+ const formatLog = (message: string, logMetadata?: LogMetadata): string => {
32
+ if (!logMetadata) return message;
33
+
34
+ const params = Object.entries(logMetadata)
35
+ .filter(([value]) => value)
36
+ .map(([key, value]) => `[${key}: ${value}]`)
37
+ .join(' ');
38
+ return `${params} ${message}`;
39
+ };
40
+
41
+ export const logInfo = (message: string, logMetadata?: LogMetadata): void => {
42
+ const logMessage = formatLog(message, logMetadata);
43
+ appLogger.info(logMessage);
44
+ };
45
+
46
+ export const logError = (message: string, logMetadata?: LogMetadata): void => {
47
+ const logMessage = formatLog(message, logMetadata);
48
+ appLogger.error(logMessage);
49
+ };
50
+
51
+ export const logWarn = (message: string, logMetadata?: LogMetadata): void => {
52
+ const logMessage = formatLog(message, logMetadata);
53
+ appLogger.warn(logMessage);
54
+ };
55
+
56
+ export const logDebug = (message: string, logMetadata?: LogMetadata): void => {
57
+ const logMessage = formatLog(message, logMetadata);
58
+ appLogger.debug(logMessage);
59
+ };
@@ -1 +1 @@
1
- export { appLogger } from './appLogger'
1
+ export * from './appLogger';
@@ -0,0 +1,65 @@
1
+ import axios from 'axios';
2
+ import { Agent } from 'https';
3
+ import { doCallToUrl, RequestMethod } from '../services';
4
+
5
+ const auth0Payload = {
6
+ client_id: process.env.CLIENT_ID,
7
+ client_secret: process.env.CLIENT_SECRET,
8
+ audience: process.env.AUTH0_AUDIENCE || 'bigid-api-v1',
9
+ grant_type: 'client_credentials',
10
+ };
11
+
12
+ let auth0Token: string;
13
+ let accessToken: string;
14
+
15
+ export const getAccessTokenFromRefreshToken = async (refreshToken: string) => {
16
+ if (canUseLocalToken(accessToken)) return accessToken;
17
+ const bigidBaseUrl = process.env.BIGID_BASE_URL;
18
+ const {
19
+ data: { systemToken },
20
+ } = await doCallToUrl(
21
+ refreshToken,
22
+ RequestMethod.GET,
23
+ new URL('api/v1/refresh-access-token', bigidBaseUrl).toString(),
24
+ );
25
+ accessToken = systemToken;
26
+
27
+ return accessToken;
28
+ };
29
+
30
+ export const getAuth0Token = async (): Promise<string> => {
31
+ if (canUseLocalToken(auth0Token)) return auth0Token;
32
+ const auth0Domain = process.env.AUTH0_DOMAIN?.replace(/\/$/, '');
33
+ const {
34
+ data: { access_token },
35
+ } = await axios.post(`${auth0Domain}/oauth/token`, auth0Payload);
36
+ auth0Token = access_token;
37
+
38
+ return access_token;
39
+ };
40
+
41
+ export const tokenExchange = async (auth0Token: string, tenantId?: string): Promise<string> => {
42
+ const {
43
+ data: { data },
44
+ } = await axios.post(
45
+ `${process.env.BIGID_BASE_URL}/api/v1/token-exchange`,
46
+ { tenantId },
47
+ {
48
+ headers: { authorization: auth0Token },
49
+ httpsAgent: new Agent({
50
+ rejectUnauthorized: false,
51
+ }),
52
+ },
53
+ );
54
+ return data[0];
55
+ };
56
+
57
+ const getTokenPayloadAsJson = (token: string): Record<string, any> =>
58
+ JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString());
59
+
60
+ const canUseLocalToken = (token: string): boolean => {
61
+ if (!token) return false;
62
+
63
+ const { exp } = getTokenPayloadAsJson(token);
64
+ return Date.now() < exp * 1000;
65
+ };