mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 04:04:06 -08:00
🐛 Fix digest-auth (#2577)
* 🚢 Added digest-header package to get auth * ⚡ Fix type issue and digest auth header request * ⚡ Removed auth details from first request * Added diest to authorization header * ⚡ fixed typo in url * ⚡ Removed broken package and addded auth implimentation * ⚡ Added check for www header * 👕 Moved digestAuth to a specific function * 👕 Code restructuring * ⚡ Added seperate promise for digest-auth * 👕 Fix formatting * 👕 renamed digestPromise to axiosPromise * 👕 Removed redundant silce function
This commit is contained in:
parent
755af2e41f
commit
5c11eb5230
|
@ -59,6 +59,8 @@ import { stringify } from 'qs';
|
|||
import * as clientOAuth1 from 'oauth-1.0a';
|
||||
import { Token } from 'oauth-1.0a';
|
||||
import * as clientOAuth2 from 'client-oauth2';
|
||||
import * as crypto from 'crypto';
|
||||
import * as url from 'url';
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import { get } from 'lodash';
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
|
@ -71,7 +73,13 @@ import { createHmac } from 'crypto';
|
|||
import { fromBuffer } from 'file-type';
|
||||
import { lookup } from 'mime-types';
|
||||
|
||||
import axios, { AxiosProxyConfig, AxiosRequestConfig, Method } from 'axios';
|
||||
import axios, {
|
||||
AxiosPromise,
|
||||
AxiosProxyConfig,
|
||||
AxiosRequestConfig,
|
||||
AxiosResponse,
|
||||
Method,
|
||||
} from 'axios';
|
||||
import { URL, URLSearchParams } from 'url';
|
||||
import { BinaryDataManager } from './BinaryDataManager';
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
|
@ -470,6 +478,49 @@ async function parseRequestObject(requestObject: IDataObject) {
|
|||
return axiosConfig;
|
||||
}
|
||||
|
||||
function digestAuthAxiosConfig(
|
||||
axiosConfig: AxiosRequestConfig,
|
||||
response: AxiosResponse,
|
||||
auth: AxiosRequestConfig['auth'],
|
||||
): AxiosRequestConfig {
|
||||
const authDetails = response.headers['www-authenticate']
|
||||
.split(',')
|
||||
.map((v: string) => v.split('='));
|
||||
if (authDetails) {
|
||||
const nonceCount = `000000001`;
|
||||
const cnonce = crypto.randomBytes(24).toString('hex');
|
||||
const realm: string = authDetails
|
||||
.find((el: any) => el[0].toLowerCase().indexOf('realm') > -1)[1]
|
||||
.replace(/"/g, '');
|
||||
const nonce: string = authDetails
|
||||
.find((el: any) => el[0].toLowerCase().indexOf('nonce') > -1)[1]
|
||||
.replace(/"/g, '');
|
||||
const ha1 = crypto
|
||||
.createHash('md5')
|
||||
.update(`${auth?.username as string}:${realm}:${auth?.password as string}`)
|
||||
.digest('hex');
|
||||
const path = new url.URL(axiosConfig.url!).pathname;
|
||||
const ha2 = crypto
|
||||
.createHash('md5')
|
||||
.update(`${axiosConfig.method ?? 'GET'}:${path}`)
|
||||
.digest('hex');
|
||||
const response = crypto
|
||||
.createHash('md5')
|
||||
.update(`${ha1}:${nonce}:${nonceCount}:${cnonce}:auth:${ha2}`)
|
||||
.digest('hex');
|
||||
const authorization =
|
||||
`Digest username="${auth?.username as string}",realm="${realm}",` +
|
||||
`nonce="${nonce}",uri="${path}",qop="auth",algorithm="MD5",` +
|
||||
`response="${response}",nc="${nonceCount}",cnonce="${cnonce}"`;
|
||||
if (axiosConfig.headers) {
|
||||
axiosConfig.headers.authorization = authorization;
|
||||
} else {
|
||||
axiosConfig.headers = { authorization };
|
||||
}
|
||||
}
|
||||
return axiosConfig;
|
||||
}
|
||||
|
||||
async function proxyRequestToAxios(
|
||||
uriOrObject: string | IDataObject,
|
||||
options?: IDataObject,
|
||||
|
@ -483,8 +534,13 @@ async function proxyRequestToAxios(
|
|||
}
|
||||
|
||||
let axiosConfig: AxiosRequestConfig = {};
|
||||
|
||||
let configObject: IDataObject;
|
||||
let axiosPromise: AxiosPromise;
|
||||
type ConfigObject = {
|
||||
auth?: { sendImmediately: boolean };
|
||||
resolveWithFullResponse?: boolean;
|
||||
simple?: boolean;
|
||||
};
|
||||
let configObject: ConfigObject;
|
||||
if (uriOrObject !== undefined && typeof uriOrObject === 'string') {
|
||||
axiosConfig.url = uriOrObject;
|
||||
}
|
||||
|
@ -501,8 +557,33 @@ async function proxyRequestToAxios(
|
|||
parsedConfig: axiosConfig,
|
||||
});
|
||||
|
||||
if (configObject.auth?.sendImmediately === false) {
|
||||
// for digest-auth
|
||||
const { auth } = axiosConfig;
|
||||
delete axiosConfig.auth;
|
||||
// eslint-disable-next-line no-async-promise-executor
|
||||
axiosPromise = new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const result = await axios(axiosConfig);
|
||||
resolve(result);
|
||||
} catch (resp: any) {
|
||||
if (
|
||||
resp.response === undefined ||
|
||||
resp.response.status !== 401 ||
|
||||
!resp.response.headers['www-authenticate']?.includes('nonce')
|
||||
) {
|
||||
reject(resp);
|
||||
}
|
||||
axiosConfig = digestAuthAxiosConfig(axiosConfig, resp.response, auth);
|
||||
resolve(axios(axiosConfig));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
axiosPromise = axios(axiosConfig);
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
axios(axiosConfig)
|
||||
axiosPromise
|
||||
.then((response) => {
|
||||
if (configObject.resolveWithFullResponse === true) {
|
||||
let body = response.data;
|
||||
|
|
Loading…
Reference in a new issue