feat(core): Replace client-oauth2 with an in-repo package (#6266)

Co-authored-by: Marcus <marcus@n8n.io>
This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™
2023-05-17 14:40:53 +00:00
committed by GitHub
parent 16fade7d41
commit a1b1f24ddf
30 changed files with 992 additions and 166 deletions

View File

@@ -82,7 +82,12 @@ import { IncomingMessage } from 'http';
import { stringify } from 'qs';
import type { Token } from 'oauth-1.0a';
import clientOAuth1 from 'oauth-1.0a';
import clientOAuth2 from 'client-oauth2';
import type {
ClientOAuth2Options,
ClientOAuth2RequestObject,
ClientOAuth2TokenData,
} from '@n8n/client-oauth2';
import { ClientOAuth2 } from '@n8n/client-oauth2';
import crypto, { createHmac } from 'crypto';
import get from 'lodash.get';
import type { Request, Response } from 'express';
@@ -1081,14 +1086,14 @@ export async function requestOAuth2(
throw new Error('OAuth credentials not connected!');
}
const oAuthClient = new clientOAuth2({
const oAuthClient = new ClientOAuth2({
clientId: credentials.clientId as string,
clientSecret: credentials.clientSecret as string,
accessTokenUri: credentials.accessTokenUrl as string,
scopes: (credentials.scope as string).split(' '),
});
let oauthTokenData = credentials.oauthTokenData as clientOAuth2.Data;
let oauthTokenData = credentials.oauthTokenData as ClientOAuth2TokenData;
// if it's the first time using the credentials, get the access token and save it into the DB.
if (
@@ -1116,15 +1121,20 @@ export async function requestOAuth2(
oauthTokenData = data;
}
const accessToken =
get(oauthTokenData, oAuth2Options?.property as string) || oauthTokenData.accessToken;
const refreshToken = oauthTokenData.refreshToken;
const token = oAuthClient.createToken(
get(oauthTokenData, oAuth2Options?.property as string) || oauthTokenData.accessToken,
oauthTokenData.refreshToken,
{
...oauthTokenData,
...(accessToken ? { access_token: accessToken } : {}),
...(refreshToken ? { refresh_token: refreshToken } : {}),
},
oAuth2Options?.tokenType || oauthTokenData.tokenType,
oauthTokenData,
);
// Signs the request by adding authorization headers or query parameters depending
// on the token-type used.
const newRequestOptions = token.sign(requestOptions as clientOAuth2.RequestObject);
const newRequestOptions = token.sign(requestOptions as ClientOAuth2RequestObject);
const newRequestHeaders = (newRequestOptions.headers = newRequestOptions.headers ?? {});
// If keep bearer is false remove the it from the authorization header
if (oAuth2Options?.keepBearer === false && typeof newRequestHeaders.Authorization === 'string') {
@@ -1164,7 +1174,7 @@ export async function requestOAuth2(
if (OAuth2GrantType.clientCredentials === credentials.grantType) {
newToken = await getClientCredentialsToken(token.client, credentials);
} else {
newToken = await token.refresh(tokenRefreshOptions);
newToken = await token.refresh(tokenRefreshOptions as unknown as ClientOAuth2Options);
}
Logger.debug(
@@ -1184,7 +1194,7 @@ export async function requestOAuth2(
credentialsType,
credentials,
);
const refreshedRequestOption = newToken.sign(requestOptions as clientOAuth2.RequestObject);
const refreshedRequestOption = newToken.sign(requestOptions as ClientOAuth2RequestObject);
if (oAuth2Options?.keyToIncludeInAccessTokenHeader) {
Object.assign(newRequestHeaders, {
@@ -1197,6 +1207,11 @@ export async function requestOAuth2(
throw error;
});
}
const tokenExpiredStatusCode =
oAuth2Options?.tokenExpiredStatusCode === undefined
? 401
: oAuth2Options?.tokenExpiredStatusCode;
return this.helpers
.request(newRequestOptions)
.then((response) => {
@@ -1204,21 +1219,14 @@ export async function requestOAuth2(
if (
requestOptions.resolveWithFullResponse === true &&
requestOptions.simple === false &&
response.statusCode ===
(oAuth2Options?.tokenExpiredStatusCode === undefined
? 401
: oAuth2Options?.tokenExpiredStatusCode)
response.statusCode === tokenExpiredStatusCode
) {
throw response;
}
return response;
})
.catch(async (error: IResponseError) => {
const statusCodeReturned =
oAuth2Options?.tokenExpiredStatusCode === undefined
? 401
: oAuth2Options?.tokenExpiredStatusCode;
if (error.statusCode === statusCodeReturned) {
if (error.statusCode === tokenExpiredStatusCode) {
// Token is probably not valid anymore. So try refresh it.
const tokenRefreshOptions: IDataObject = {};
if (oAuth2Options?.includeCredentialsOnRefreshOnBody) {
@@ -1243,7 +1251,7 @@ export async function requestOAuth2(
if (OAuth2GrantType.clientCredentials === credentials.grantType) {
newToken = await getClientCredentialsToken(token.client, credentials);
} else {
newToken = await token.refresh(tokenRefreshOptions);
newToken = await token.refresh(tokenRefreshOptions as unknown as ClientOAuth2Options);
}
Logger.debug(
`OAuth2 token for "${credentialsType}" used by node "${node.name}" has been renewed.`,
@@ -1271,7 +1279,7 @@ export async function requestOAuth2(
);
// Make the request again with the new token
const newRequestOptions = newToken.sign(requestOptions as clientOAuth2.RequestObject);
const newRequestOptions = newToken.sign(requestOptions as ClientOAuth2RequestObject);
newRequestOptions.headers = newRequestOptions.headers ?? {};
if (oAuth2Options?.keyToIncludeInAccessTokenHeader) {