refactor(core): Google service account remove duplicated functions (no-changelog) (#6368)

This commit is contained in:
Michael Kret 2023-06-06 19:19:24 +03:00 committed by GitHub
parent 3a6af3b2a2
commit 05c4229cd7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 134 additions and 719 deletions

View file

@ -8,64 +8,12 @@ import type {
JsonObject,
} from 'n8n-workflow';
import { NodeApiError, NodeOperationError } from 'n8n-workflow';
import moment from 'moment-timezone';
import * as jwt from 'jsonwebtoken';
async function getAccessToken(
this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions,
credentials: IDataObject,
): Promise<IDataObject> {
//https://developers.google.com/identity/protocols/oauth2/service-account#httprest
const privateKey = (credentials.privateKey as string).replace(/\\n/g, '\n').trim();
const scopes = ['https://www.googleapis.com/auth/bigquery'];
const now = moment().unix();
const signature = jwt.sign(
{
iss: credentials.email as string,
sub: credentials.delegatedEmail || (credentials.email as string),
scope: scopes.join(' '),
aud: 'https://oauth2.googleapis.com/token',
iat: now,
exp: now + 3600,
},
privateKey,
{
algorithm: 'RS256',
header: {
kid: privateKey,
typ: 'JWT',
alg: 'RS256',
},
},
);
const options: OptionsWithUri = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
method: 'POST',
form: {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: signature,
},
uri: 'https://oauth2.googleapis.com/token',
json: true,
};
return this.helpers.request(options);
}
import { getGoogleAccessToken } from '../../GenericFunctions';
export async function googleApiRequest(
this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions,
method: string,
resource: string,
body: any = {},
qs: IDataObject = {},
uri?: string,
@ -102,7 +50,7 @@ export async function googleApiRequest(
throw new NodeOperationError(this.getNode(), 'No credentials got returned!');
}
const { access_token } = await getAccessToken.call(this, credentials as IDataObject);
const { access_token } = await getGoogleAccessToken.call(this, credentials, 'bigquery');
options.headers!.Authorization = `Bearer ${access_token}`;
return await this.helpers.request(options);

View file

@ -1,58 +1,9 @@
import type { OptionsWithUri } from 'request';
import moment from 'moment-timezone';
import * as jwt from 'jsonwebtoken';
import type { IExecuteFunctions, IExecuteSingleFunctions, ILoadOptionsFunctions } from 'n8n-core';
import type { IDataObject, JsonObject } from 'n8n-workflow';
import { NodeApiError, NodeOperationError } from 'n8n-workflow';
async function getAccessToken(
this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions,
credentials: IDataObject,
): Promise<IDataObject> {
//https://developers.google.com/identity/protocols/oauth2/service-account#httprest
const privateKey = (credentials.privateKey as string).replace(/\\n/g, '\n').trim();
const scopes = ['https://www.googleapis.com/auth/bigquery'];
const now = moment().unix();
const signature = jwt.sign(
{
iss: credentials.email as string,
sub: credentials.delegatedEmail || (credentials.email as string),
scope: scopes.join(' '),
aud: 'https://oauth2.googleapis.com/token',
iat: now,
exp: now + 3600,
},
privateKey,
{
algorithm: 'RS256',
header: {
kid: privateKey,
typ: 'JWT',
alg: 'RS256',
},
},
);
const options: OptionsWithUri = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
method: 'POST',
form: {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: signature,
},
uri: 'https://oauth2.googleapis.com/token',
json: true,
};
return this.helpers.request(options);
}
import { getGoogleAccessToken } from '../../../GenericFunctions';
export async function googleApiRequest(
this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions,
@ -94,7 +45,7 @@ export async function googleApiRequest(
throw new NodeOperationError(this.getNode(), 'No credentials got returned!');
}
const { access_token } = await getAccessToken.call(this, credentials as IDataObject);
const { access_token } = await getGoogleAccessToken.call(this, credentials, 'bigquery');
options.headers!.Authorization = `Bearer ${access_token}`;
return await this.helpers.request(options);

View file

@ -8,72 +8,12 @@ import type {
JsonObject,
} from 'n8n-workflow';
import { NodeApiError } from 'n8n-workflow';
import moment from 'moment-timezone';
import jwt from 'jsonwebtoken';
interface IGoogleAuthCredentials {
delegatedEmail?: string;
email: string;
inpersonate: boolean;
privateKey: string;
}
async function getAccessToken(
this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions,
credentials: IGoogleAuthCredentials,
): Promise<IDataObject> {
//https://developers.google.com/identity/protocols/oauth2/service-account#httprest
const scopes = ['https://www.googleapis.com/auth/books'];
const now = moment().unix();
credentials.email = credentials.email.trim();
const privateKey = credentials.privateKey.replace(/\\n/g, '\n').trim();
const signature = jwt.sign(
{
iss: credentials.email,
sub: credentials.delegatedEmail || credentials.email,
scope: scopes.join(' '),
aud: 'https://oauth2.googleapis.com/token',
iat: now,
exp: now + 3600,
},
privateKey,
{
algorithm: 'RS256',
header: {
kid: privateKey,
typ: 'JWT',
alg: 'RS256',
},
},
);
const options: OptionsWithUri = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
method: 'POST',
form: {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: signature,
},
uri: 'https://oauth2.googleapis.com/token',
json: true,
};
return this.helpers.request(options);
}
import { getGoogleAccessToken } from '../GenericFunctions';
export async function googleApiRequest(
this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions,
method: string,
resource: string,
body: any = {},
qs: IDataObject = {},
uri?: string,
@ -108,10 +48,7 @@ export async function googleApiRequest(
privateKey: string;
};
const { access_token } = await getAccessToken.call(
this,
credentials as unknown as IGoogleAuthCredentials,
);
const { access_token } = await getGoogleAccessToken.call(this, credentials, 'books');
options.headers!.Authorization = `Bearer ${access_token}`;

View file

@ -1,7 +1,6 @@
import type { OptionsWithUri } from 'request';
import type {
ICredentialTestFunctions,
IDataObject,
IExecuteFunctions,
IExecuteSingleFunctions,
@ -11,69 +10,7 @@ import type {
} from 'n8n-workflow';
import { NodeApiError } from 'n8n-workflow';
import moment from 'moment-timezone';
import jwt from 'jsonwebtoken';
interface IGoogleAuthCredentials {
delegatedEmail?: string;
email: string;
inpersonate: boolean;
privateKey: string;
}
export async function getAccessToken(
this:
| IExecuteFunctions
| IExecuteSingleFunctions
| ILoadOptionsFunctions
| ICredentialTestFunctions,
credentials: IGoogleAuthCredentials,
): Promise<IDataObject> {
//https://developers.google.com/identity/protocols/oauth2/service-account#httprest
const scopes = ['https://www.googleapis.com/auth/chat.bot'];
const now = moment().unix();
credentials.email = credentials.email.trim();
const privateKey = credentials.privateKey.replace(/\\n/g, '\n').trim();
const signature = jwt.sign(
{
iss: credentials.email,
sub: credentials.delegatedEmail || credentials.email,
scope: scopes.join(' '),
aud: 'https://oauth2.googleapis.com/token',
iat: now,
exp: now + 3600,
},
privateKey,
{
algorithm: 'RS256',
header: {
kid: privateKey,
typ: 'JWT',
alg: 'RS256',
},
},
);
const options: OptionsWithUri = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
method: 'POST',
form: {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: signature,
},
uri: 'https://oauth2.googleapis.com/token',
json: true,
};
return this.helpers.request(options);
}
import { getGoogleAccessToken } from '../GenericFunctions';
export async function googleApiRequest(
this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions,
@ -112,10 +49,7 @@ export async function googleApiRequest(
} else {
const credentials = await this.getCredentials('googleApi');
const { access_token } = await getAccessToken.call(
this,
credentials as unknown as IGoogleAuthCredentials,
);
const { access_token } = await getGoogleAccessToken.call(this, credentials, 'chat');
options.headers!.Authorization = `Bearer ${access_token}`;
responseData = await this.helpers.request(options);
}

View file

@ -8,69 +8,7 @@ import type {
} from 'n8n-workflow';
import { NodeApiError } from 'n8n-workflow';
import moment from 'moment-timezone';
import jwt from 'jsonwebtoken';
interface IGoogleAuthCredentials {
delegatedEmail?: string;
email: string;
inpersonate: boolean;
privateKey: string;
}
async function getAccessToken(
this: IExecuteFunctions | ILoadOptionsFunctions,
credentials: IGoogleAuthCredentials,
): Promise<IDataObject> {
//https://developers.google.com/identity/protocols/oauth2/service-account#httprest
const scopes = [
'https://www.googleapis.com/auth/documents',
'https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/drive.file',
];
const now = moment().unix();
credentials.email = credentials.email.trim();
const privateKey = credentials.privateKey.replace(/\\n/g, '\n').trim();
const signature = jwt.sign(
{
iss: credentials.email,
sub: credentials.delegatedEmail || credentials.email,
scope: scopes.join(' '),
aud: 'https://oauth2.googleapis.com/token',
iat: now,
exp: now + 3600,
},
privateKey,
{
algorithm: 'RS256',
header: {
kid: privateKey,
typ: 'JWT',
alg: 'RS256',
},
},
);
const options: OptionsWithUri = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
method: 'POST',
form: {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: signature,
},
uri: 'https://oauth2.googleapis.com/token',
json: true,
};
return this.helpers.request(options);
}
import { getGoogleAccessToken } from '../GenericFunctions';
export async function googleApiRequest(
this: IExecuteFunctions | ILoadOptionsFunctions,
@ -104,10 +42,7 @@ export async function googleApiRequest(
if (authenticationMethod === 'serviceAccount') {
const credentials = await this.getCredentials('googleApi');
const { access_token } = await getAccessToken.call(
this,
credentials as unknown as IGoogleAuthCredentials,
);
const { access_token } = await getGoogleAccessToken.call(this, credentials, 'docs');
options.headers!.Authorization = `Bearer ${access_token}`;
return await this.helpers.request(options);

View file

@ -10,75 +10,12 @@ import type {
} from 'n8n-workflow';
import { NodeApiError } from 'n8n-workflow';
import moment from 'moment-timezone';
import jwt from 'jsonwebtoken';
interface IGoogleAuthCredentials {
delegatedEmail?: string;
email: string;
inpersonate: boolean;
privateKey: string;
}
async function getAccessToken(
this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions | IPollFunctions,
credentials: IGoogleAuthCredentials,
): Promise<IDataObject> {
//https://developers.google.com/identity/protocols/oauth2/service-account#httprest
const scopes = [
'https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/drive.appdata',
'https://www.googleapis.com/auth/drive.photos.readonly',
];
const now = moment().unix();
credentials.email = credentials.email.trim();
const privateKey = credentials.privateKey.replace(/\\n/g, '\n').trim();
const signature = jwt.sign(
{
iss: credentials.email,
sub: credentials.delegatedEmail || credentials.email,
scope: scopes.join(' '),
aud: 'https://oauth2.googleapis.com/token',
iat: now,
exp: now + 3600,
},
privateKey,
{
algorithm: 'RS256',
header: {
kid: privateKey,
typ: 'JWT',
alg: 'RS256',
},
},
);
const options: OptionsWithUri = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
method: 'POST',
form: {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: signature,
},
uri: 'https://oauth2.googleapis.com/token',
json: true,
};
return this.helpers.request(options);
}
import { getGoogleAccessToken } from '../GenericFunctions';
export async function googleApiRequest(
this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions | IPollFunctions,
method: string,
resource: string,
body: any = {},
qs: IDataObject = {},
uri?: string,
@ -111,10 +48,7 @@ export async function googleApiRequest(
if (authenticationMethod === 'serviceAccount') {
const credentials = await this.getCredentials('googleApi');
const { access_token } = await getAccessToken.call(
this,
credentials as unknown as IGoogleAuthCredentials,
);
const { access_token } = await getGoogleAccessToken.call(this, credentials, 'drive');
options.headers!.Authorization = `Bearer ${access_token}`;
return await this.helpers.request(options);

View file

@ -0,0 +1,105 @@
import type { IExecuteFunctions, IExecuteSingleFunctions, ILoadOptionsFunctions } from 'n8n-core';
import type { ICredentialTestFunctions, IDataObject, IPollFunctions } from 'n8n-workflow';
import type { OptionsWithUri } from 'request';
import moment from 'moment-timezone';
import * as jwt from 'jsonwebtoken';
const googleServiceAccountScopes = {
bigquery: ['https://www.googleapis.com/auth/bigquery'],
books: ['https://www.googleapis.com/auth/books'],
chat: ['https://www.googleapis.com/auth/chat.bot'],
docs: [
'https://www.googleapis.com/auth/documents',
'https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/drive.file',
],
drive: [
'https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/drive.appdata',
'https://www.googleapis.com/auth/drive.photos.readonly',
],
gmail: [
'https://www.googleapis.com/auth/gmail.labels',
'https://www.googleapis.com/auth/gmail.addons.current.action.compose',
'https://www.googleapis.com/auth/gmail.addons.current.message.action',
'https://mail.google.com/',
'https://www.googleapis.com/auth/gmail.modify',
'https://www.googleapis.com/auth/gmail.compose',
],
sheetV1: [
'https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/drive.file',
'https://www.googleapis.com/auth/spreadsheets',
],
sheetV2: [
'https://www.googleapis.com/auth/drive.file',
'https://www.googleapis.com/auth/spreadsheets',
'https://www.googleapis.com/auth/drive.metadata',
],
slides: [
'https://www.googleapis.com/auth/drive.file',
'https://www.googleapis.com/auth/presentations',
],
translate: [
'https://www.googleapis.com/auth/cloud-translation',
'https://www.googleapis.com/auth/cloud-platform',
],
};
type GoogleServiceAccount = keyof typeof googleServiceAccountScopes;
export async function getGoogleAccessToken(
this:
| IExecuteFunctions
| IExecuteSingleFunctions
| ILoadOptionsFunctions
| ICredentialTestFunctions
| IPollFunctions,
credentials: IDataObject,
service: GoogleServiceAccount,
): Promise<IDataObject> {
//https://developers.google.com/identity/protocols/oauth2/service-account#httprest
const scopes = googleServiceAccountScopes[service];
const privateKey = (credentials.privateKey as string).replace(/\\n/g, '\n').trim();
credentials.email = ((credentials.email as string) || '').trim();
const now = moment().unix();
const signature = jwt.sign(
{
iss: credentials.email,
sub: credentials.delegatedEmail || credentials.email,
scope: scopes.join(' '),
aud: 'https://oauth2.googleapis.com/token',
iat: now,
exp: now + 3600,
},
privateKey,
{
algorithm: 'RS256',
header: {
kid: privateKey,
typ: 'JWT',
alg: 'RS256',
},
},
);
const options: OptionsWithUri = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
method: 'POST',
form: {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: signature,
},
uri: 'https://oauth2.googleapis.com/token',
json: true,
};
return this.helpers.request(options);
}

View file

@ -4,7 +4,6 @@ import { simpleParser } from 'mailparser';
import type {
IBinaryKeyData,
ICredentialDataDecryptedObject,
IDataObject,
IExecuteFunctions,
IExecuteSingleFunctions,
@ -16,10 +15,6 @@ import type {
} from 'n8n-workflow';
import { NodeApiError, NodeOperationError } from 'n8n-workflow';
import moment from 'moment-timezone';
import jwt from 'jsonwebtoken';
import { DateTime } from 'luxon';
import isEmpty from 'lodash.isempty';
@ -44,62 +39,7 @@ export interface IAttachments {
}
import MailComposer from 'nodemailer/lib/mail-composer';
async function getAccessToken(
this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions | IPollFunctions,
credentials: ICredentialDataDecryptedObject,
): Promise<IDataObject> {
//https://developers.google.com/identity/protocols/oauth2/service-account#httprest
const scopes = [
'https://www.googleapis.com/auth/gmail.labels',
'https://www.googleapis.com/auth/gmail.addons.current.action.compose',
'https://www.googleapis.com/auth/gmail.addons.current.message.action',
'https://mail.google.com/',
'https://www.googleapis.com/auth/gmail.modify',
'https://www.googleapis.com/auth/gmail.compose',
];
const now = moment().unix();
credentials.email = (credentials.email as string).trim();
const privateKey = (credentials.privateKey as string).replace(/\\n/g, '\n').trim();
const signature = jwt.sign(
{
iss: credentials.email,
sub: credentials.delegatedEmail || credentials.email,
scope: scopes.join(' '),
aud: 'https://oauth2.googleapis.com/token',
iat: now,
exp: now + 3600,
},
privateKey,
{
algorithm: 'RS256',
header: {
kid: privateKey,
typ: 'JWT',
alg: 'RS256',
},
},
);
const options: OptionsWithUri = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
method: 'POST',
form: {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: signature,
},
uri: 'https://oauth2.googleapis.com/token',
json: true,
};
return this.helpers.request(options);
}
import { getGoogleAccessToken } from '../GenericFunctions';
export async function googleApiRequest(
this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions | IPollFunctions,
@ -139,7 +79,7 @@ export async function googleApiRequest(
const credentials = await this.getCredentials('googleApi');
credentialType = 'googleApi';
const { access_token } = await getAccessToken.call(this, credentials);
const { access_token } = await getGoogleAccessToken.call(this, credentials, 'gmail');
(options.headers as IDataObject).Authorization = `Bearer ${access_token}`;
}

View file

@ -1,7 +1,6 @@
import type { OptionsWithUri } from 'request';
import type {
ICredentialTestFunctions,
IDataObject,
IExecuteFunctions,
IExecuteSingleFunctions,
@ -9,10 +8,7 @@ import type {
JsonObject,
} from 'n8n-workflow';
import { NodeApiError } from 'n8n-workflow';
import moment from 'moment-timezone';
import jwt from 'jsonwebtoken';
import { getGoogleAccessToken } from '../../GenericFunctions';
export interface IGoogleAuthCredentials {
delegatedEmail?: string;
@ -21,63 +17,6 @@ export interface IGoogleAuthCredentials {
privateKey: string;
}
export async function getAccessToken(
this:
| IExecuteFunctions
| IExecuteSingleFunctions
| ILoadOptionsFunctions
| ICredentialTestFunctions,
credentials: IGoogleAuthCredentials,
): Promise<IDataObject> {
//https://developers.google.com/identity/protocols/oauth2/service-account#httprest
const scopes = [
'https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/drive.file',
'https://www.googleapis.com/auth/spreadsheets',
];
const now = moment().unix();
credentials.email = credentials.email.trim();
const privateKey = credentials.privateKey.replace(/\\n/g, '\n').trim();
const signature = jwt.sign(
{
iss: credentials.email,
sub: credentials.delegatedEmail || credentials.email,
scope: scopes.join(' '),
aud: 'https://oauth2.googleapis.com/token',
iat: now,
exp: now + 3600,
},
privateKey,
{
algorithm: 'RS256',
header: {
kid: privateKey,
typ: 'JWT',
alg: 'RS256',
},
},
);
const options: OptionsWithUri = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
method: 'POST',
form: {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: signature,
},
uri: 'https://oauth2.googleapis.com/token',
json: true,
};
return this.helpers.request(options);
}
export async function googleApiRequest(
this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions,
method: string,
@ -114,10 +53,7 @@ export async function googleApiRequest(
if (authenticationMethod === 'serviceAccount') {
const credentials = await this.getCredentials('googleApi');
const { access_token } = await getAccessToken.call(
this,
credentials as unknown as IGoogleAuthCredentials,
);
const { access_token } = await getGoogleAccessToken.call(this, credentials, 'sheetV1');
options.headers!.Authorization = `Bearer ${access_token}`;
return await this.helpers.request(options);

View file

@ -22,10 +22,10 @@ import type {
} from './GoogleSheet';
import { GoogleSheet } from './GoogleSheet';
import type { IGoogleAuthCredentials } from './GenericFunctions';
import { getAccessToken, googleApiRequest, hexToRgb } from './GenericFunctions';
import { googleApiRequest, hexToRgb } from './GenericFunctions';
import { versionDescription } from './versionDescription';
import { getGoogleAccessToken } from '../../GenericFunctions';
export class GoogleSheetsV1 implements INodeType {
description: INodeTypeDescription;
@ -71,10 +71,8 @@ export class GoogleSheetsV1 implements INodeType {
credential: ICredentialsDecrypted,
): Promise<INodeCredentialTestResult> {
try {
const tokenRequest = await getAccessToken.call(
this,
credential.data! as unknown as IGoogleAuthCredentials,
);
const tokenRequest = await getGoogleAccessToken.call(this, credential.data!, 'sheetV1');
if (!tokenRequest.access_token) {
return {
status: 'Error',

View file

@ -4,18 +4,14 @@ import type {
INodeCredentialTestResult,
} from 'n8n-workflow';
import type { IGoogleAuthCredentials } from '../transport';
import { getAccessToken } from '../transport';
import { getGoogleAccessToken } from '../../../GenericFunctions';
export async function googleApiCredentialTest(
this: ICredentialTestFunctions,
credential: ICredentialsDecrypted,
): Promise<INodeCredentialTestResult> {
try {
const tokenRequest = await getAccessToken.call(
this,
credential.data! as unknown as IGoogleAuthCredentials,
);
const tokenRequest = await getGoogleAccessToken.call(this, credential.data!, 'sheetV2');
if (!tokenRequest.access_token) {
return {
status: 'Error',

View file

@ -1,6 +1,5 @@
import type { OptionsWithUri } from 'request';
import type {
ICredentialTestFunctions,
IDataObject,
IExecuteFunctions,
IExecuteSingleFunctions,
@ -9,73 +8,7 @@ import type {
JsonObject,
} from 'n8n-workflow';
import { NodeApiError } from 'n8n-workflow';
import moment from 'moment-timezone';
import jwt from 'jsonwebtoken';
export interface IGoogleAuthCredentials {
delegatedEmail?: string;
email: string;
inpersonate: boolean;
privateKey: string;
}
export async function getAccessToken(
this:
| IExecuteFunctions
| IExecuteSingleFunctions
| ILoadOptionsFunctions
| ICredentialTestFunctions
| IPollFunctions,
credentials: IGoogleAuthCredentials,
): Promise<IDataObject> {
//https://developers.google.com/identity/protocols/oauth2/service-account#httprest
const scopes = [
'https://www.googleapis.com/auth/drive.file',
'https://www.googleapis.com/auth/spreadsheets',
'https://www.googleapis.com/auth/drive.metadata',
];
const now = moment().unix();
credentials.email = credentials.email.trim();
const privateKey = credentials.privateKey.replace(/\\n/g, '\n').trim();
const signature = jwt.sign(
{
iss: credentials.email,
sub: credentials.delegatedEmail || credentials.email,
scope: scopes.join(' '),
aud: 'https://oauth2.googleapis.com/token',
iat: now,
exp: now + 3600,
},
privateKey,
{
algorithm: 'RS256',
header: {
kid: privateKey,
typ: 'JWT',
alg: 'RS256',
},
},
);
const options: OptionsWithUri = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
method: 'POST',
form: {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: signature,
},
uri: 'https://oauth2.googleapis.com/token',
json: true,
};
return this.helpers.request(options);
}
import { getGoogleAccessToken } from '../../../GenericFunctions';
export async function apiRequest(
this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions | IPollFunctions,
@ -114,10 +47,7 @@ export async function apiRequest(
if (authenticationMethod === 'serviceAccount') {
const credentials = await this.getCredentials('googleApi');
const { access_token } = await getAccessToken.call(
this,
credentials as unknown as IGoogleAuthCredentials,
);
const { access_token } = await getGoogleAccessToken.call(this, credentials, 'sheetV2');
options.headers!.Authorization = `Bearer ${access_token}`;

View file

@ -8,68 +8,7 @@ import type {
} from 'n8n-workflow';
import { NodeApiError } from 'n8n-workflow';
import moment from 'moment-timezone';
import jwt from 'jsonwebtoken';
interface IGoogleAuthCredentials {
delegatedEmail?: string;
email: string;
inpersonate: boolean;
privateKey: string;
}
async function getAccessToken(
this: IExecuteFunctions | ILoadOptionsFunctions,
credentials: IGoogleAuthCredentials,
) {
// https://developers.google.com/identity/protocols/oauth2/service-account#httprest
const scopes = [
'https://www.googleapis.com/auth/drive.file',
'https://www.googleapis.com/auth/presentations',
];
const now = moment().unix();
credentials.email = credentials.email.trim();
const privateKey = credentials.privateKey.replace(/\\n/g, '\n').trim();
const signature = jwt.sign(
{
iss: credentials.email,
sub: credentials.email,
scope: scopes.join(' '),
aud: 'https://oauth2.googleapis.com/token',
iat: now,
exp: now + 3600,
},
privateKey,
{
algorithm: 'RS256',
header: {
kid: privateKey,
typ: 'JWT',
alg: 'RS256',
},
},
);
const options: OptionsWithUri = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
method: 'POST',
form: {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: signature,
},
uri: 'https://oauth2.googleapis.com/token',
json: true,
};
return this.helpers.request(options);
}
import { getGoogleAccessToken } from '../GenericFunctions';
export async function googleApiRequest(
this: IExecuteFunctions | ILoadOptionsFunctions,
@ -106,10 +45,7 @@ export async function googleApiRequest(
if (authenticationMethod === 'serviceAccount') {
const credentials = await this.getCredentials('googleApi');
const { access_token } = await getAccessToken.call(
this,
credentials as unknown as IGoogleAuthCredentials,
);
const { access_token } = await getGoogleAccessToken.call(this, credentials, 'slides');
options.headers.Authorization = `Bearer ${access_token}`;
return await this.helpers.request(options);
} else {

View file

@ -9,68 +9,7 @@ import type {
} from 'n8n-workflow';
import { NodeApiError } from 'n8n-workflow';
import moment from 'moment-timezone';
import jwt from 'jsonwebtoken';
interface IGoogleAuthCredentials {
delegatedEmail?: string;
email: string;
inpersonate: boolean;
privateKey: string;
}
async function getAccessToken(
this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions,
credentials: IGoogleAuthCredentials,
): Promise<IDataObject> {
//https://developers.google.com/identity/protocols/oauth2/service-account#httprest
const scopes = [
'https://www.googleapis.com/auth/cloud-translation',
'https://www.googleapis.com/auth/cloud-platform',
];
const now = moment().unix();
credentials.email = credentials.email.trim();
const privateKey = credentials.privateKey.replace(/\\n/g, '\n').trim();
const signature = jwt.sign(
{
iss: credentials.email,
sub: credentials.email,
scope: scopes.join(' '),
aud: 'https://oauth2.googleapis.com/token',
iat: now,
exp: now + 3600,
},
privateKey,
{
algorithm: 'RS256',
header: {
kid: privateKey,
typ: 'JWT',
alg: 'RS256',
},
},
);
const options: OptionsWithUri = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
method: 'POST',
form: {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: signature,
},
uri: 'https://oauth2.googleapis.com/token',
json: true,
};
return this.helpers.request(options);
}
import { getGoogleAccessToken } from '../GenericFunctions';
export async function googleApiRequest(
this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions,
@ -108,16 +47,12 @@ export async function googleApiRequest(
if (authenticationMethod === 'serviceAccount') {
const credentials = await this.getCredentials('googleApi');
const { access_token } = await getAccessToken.call(
this,
credentials as unknown as IGoogleAuthCredentials,
);
const { access_token } = await getGoogleAccessToken.call(this, credentials, 'translate');
options.headers!.Authorization = `Bearer ${access_token}`;
//@ts-ignore
return await this.helpers.request(options);
} else {
//@ts-ignore
return await this.helpers.requestOAuth2.call(this, 'googleTranslateOAuth2Api', options);
}
} catch (error) {