feat: Add support for preAuthentication and add Metabase credentials (#3399)

*  Add preAuthentication method to credentials

* Improvements

*  Improvements

*  Add feedback

* 🔥 Remove comments

*  Add generic type to autheticate method

*  Fix typo

*  Remove console.log and fix indentation

*  Minor improvements

*  Expire credentials in every credential test run

Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
This commit is contained in:
Ricardo Espinoza
2022-07-19 04:09:06 -04:00
committed by GitHub
parent f958e6ffab
commit 994c89a6c6
9 changed files with 290 additions and 7 deletions

View File

@@ -1182,6 +1182,7 @@ export async function httpRequestWithAuthentication(
additionalData: IWorkflowExecuteAdditionalData,
additionalCredentialOptions?: IAdditionalCredentialOptions,
) {
let credentialsDecrypted: ICredentialDataDecryptedObject | undefined;
try {
const parentTypes = additionalData.credentialsHelper.getParentTypes(credentialsType);
if (parentTypes.includes('oAuth1Api')) {
@@ -1199,7 +1200,6 @@ export async function httpRequestWithAuthentication(
);
}
let credentialsDecrypted: ICredentialDataDecryptedObject | undefined;
if (additionalCredentialOptions?.credentialsDecrypted) {
credentialsDecrypted = additionalCredentialOptions.credentialsDecrypted.data;
} else {
@@ -1213,6 +1213,20 @@ export async function httpRequestWithAuthentication(
);
}
const data = await additionalData.credentialsHelper.preAuthentication(
{ helpers: { httpRequest: this.helpers.httpRequest } },
credentialsDecrypted,
credentialsType,
node,
false,
);
if (data) {
// make the updated property in the credentials
// available to the authenticate method
Object.assign(credentialsDecrypted, data);
}
requestOptions = await additionalData.credentialsHelper.authenticate(
credentialsDecrypted,
credentialsType,
@@ -1223,6 +1237,45 @@ export async function httpRequestWithAuthentication(
);
return await httpRequest(requestOptions);
} catch (error) {
// if there is a pre authorization method defined and
// the method failed due to unathorized request
if (
error.response?.status === 401 &&
additionalData.credentialsHelper.preAuthentication !== undefined
) {
try {
if (credentialsDecrypted !== undefined) {
// try to refresh the credentials
const data = await additionalData.credentialsHelper.preAuthentication(
{ helpers: { httpRequest: this.helpers.httpRequest } },
credentialsDecrypted,
credentialsType,
node,
true,
);
if (data) {
// make the updated property in the credentials
// available to the authenticate method
Object.assign(credentialsDecrypted, data);
}
requestOptions = await additionalData.credentialsHelper.authenticate(
credentialsDecrypted,
credentialsType,
requestOptions,
workflow,
node,
additionalData.timezone,
);
}
// retry the request
return await httpRequest(requestOptions);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
}
throw new NodeApiError(this.getNode(), error);
}
}
@@ -1303,6 +1356,8 @@ export async function requestWithAuthentication(
additionalData: IWorkflowExecuteAdditionalData,
additionalCredentialOptions?: IAdditionalCredentialOptions,
) {
let credentialsDecrypted: ICredentialDataDecryptedObject | undefined;
try {
const parentTypes = additionalData.credentialsHelper.getParentTypes(credentialsType);
@@ -1321,7 +1376,6 @@ export async function requestWithAuthentication(
);
}
let credentialsDecrypted: ICredentialDataDecryptedObject | undefined;
if (additionalCredentialOptions?.credentialsDecrypted) {
credentialsDecrypted = additionalCredentialOptions.credentialsDecrypted.data;
} else {
@@ -1335,6 +1389,20 @@ export async function requestWithAuthentication(
);
}
const data = await additionalData.credentialsHelper.preAuthentication(
{ helpers: { httpRequest: this.helpers.httpRequest } },
credentialsDecrypted,
credentialsType,
node,
false,
);
if (data) {
// make the updated property in the credentials
// available to the authenticate method
Object.assign(credentialsDecrypted, data);
}
requestOptions = await additionalData.credentialsHelper.authenticate(
credentialsDecrypted,
credentialsType,
@@ -1346,7 +1414,37 @@ export async function requestWithAuthentication(
return await proxyRequestToAxios(requestOptions as IDataObject);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
try {
if (credentialsDecrypted !== undefined) {
// try to refresh the credentials
const data = await additionalData.credentialsHelper.preAuthentication(
{ helpers: { httpRequest: this.helpers.httpRequest } },
credentialsDecrypted,
credentialsType,
node,
true,
);
if (data) {
// make the updated property in the credentials
// available to the authenticate method
Object.assign(credentialsDecrypted, data);
}
requestOptions = await additionalData.credentialsHelper.authenticate(
credentialsDecrypted,
credentialsType,
requestOptions as IHttpRequestOptions,
workflow,
node,
additionalData.timezone,
);
}
// retry the request
return await proxyRequestToAxios(requestOptions as IDataObject);
} catch (error) {
throw new NodeApiError(this.getNode(), error);
}
}
}