mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-25 04:34:06 -08:00
feat(core): Support for google service account in HTTP node
This commit is contained in:
parent
49d838f628
commit
0b48088296
|
@ -1,9 +1,22 @@
|
||||||
import type { ICredentialType, INodeProperties } from 'n8n-workflow';
|
import type {
|
||||||
|
ICredentialDataDecryptedObject,
|
||||||
|
ICredentialType,
|
||||||
|
IHttpRequestOptions,
|
||||||
|
INodeProperties,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
import moment from 'moment-timezone';
|
||||||
|
|
||||||
|
import jwt from 'jsonwebtoken';
|
||||||
|
|
||||||
|
import type { AxiosRequestConfig } from 'axios';
|
||||||
|
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
export class GoogleApi implements ICredentialType {
|
export class GoogleApi implements ICredentialType {
|
||||||
name = 'googleApi';
|
name = 'googleApi';
|
||||||
|
|
||||||
displayName = 'Google API';
|
displayName = 'Google Service Account API';
|
||||||
|
|
||||||
documentationUrl = 'google/service-account';
|
documentationUrl = 'google/service-account';
|
||||||
|
|
||||||
|
@ -52,5 +65,101 @@ export class GoogleApi implements ICredentialType {
|
||||||
description:
|
description:
|
||||||
'The email address of the user for which the application is requesting delegated access',
|
'The email address of the user for which the application is requesting delegated access',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Set up for use in HTTP Request node',
|
||||||
|
name: 'httpNode',
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName:
|
||||||
|
"When using the HTTP Request node, you must specify the scopes you want to send. In other nodes, they're added automatically",
|
||||||
|
name: 'httpWarning',
|
||||||
|
type: 'notice',
|
||||||
|
default: '',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
httpNode: [true],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Scope(s)',
|
||||||
|
name: 'scopes',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description:
|
||||||
|
'You can find the scopes for services <a href="https://developers.google.com/identity/protocols/oauth2/scopes" target="_blank">here</a>',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
httpNode: [true],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
async authenticate(
|
||||||
|
credentials: ICredentialDataDecryptedObject,
|
||||||
|
requestOptions: IHttpRequestOptions,
|
||||||
|
): Promise<IHttpRequestOptions> {
|
||||||
|
if (!credentials.httpNode) return requestOptions;
|
||||||
|
|
||||||
|
const privateKey = (credentials.privateKey as string).replace(/\\n/g, '\n').trim();
|
||||||
|
const credentialsScopes = (credentials.scopes as string).replace(/\\n/g, '\n').trim();
|
||||||
|
credentials.email = (credentials.email as string).trim();
|
||||||
|
|
||||||
|
const regex = /[,\s\n]+/;
|
||||||
|
const scopes = credentialsScopes
|
||||||
|
.split(regex)
|
||||||
|
.filter((scope) => scope)
|
||||||
|
.join(' ');
|
||||||
|
|
||||||
|
const now = moment().unix();
|
||||||
|
|
||||||
|
const signature = jwt.sign(
|
||||||
|
{
|
||||||
|
iss: credentials.email,
|
||||||
|
sub: credentials.delegatedEmail || credentials.email,
|
||||||
|
scope: scopes,
|
||||||
|
aud: 'https://oauth2.googleapis.com/token',
|
||||||
|
iat: now,
|
||||||
|
exp: now + 3600,
|
||||||
|
},
|
||||||
|
privateKey,
|
||||||
|
{
|
||||||
|
algorithm: 'RS256',
|
||||||
|
header: {
|
||||||
|
kid: privateKey,
|
||||||
|
typ: 'JWT',
|
||||||
|
alg: 'RS256',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const axiosRequestConfig: AxiosRequestConfig = {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
},
|
||||||
|
method: 'POST',
|
||||||
|
data: new URLSearchParams({
|
||||||
|
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
|
||||||
|
assertion: signature,
|
||||||
|
}).toString(),
|
||||||
|
url: 'https://oauth2.googleapis.com/token',
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await axios(axiosRequestConfig);
|
||||||
|
|
||||||
|
const { access_token } = result.data;
|
||||||
|
|
||||||
|
const requestOptionsWithAuth: IHttpRequestOptions = {
|
||||||
|
...requestOptions,
|
||||||
|
headers: {
|
||||||
|
...requestOptions.headers,
|
||||||
|
Authorization: `Bearer ${access_token}`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return requestOptionsWithAuth;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,6 +137,18 @@ export class HttpRequestV3 implements INodeType {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
displayName:
|
||||||
|
'Make sure you have specified the scope(s) for the Service Account in the credential',
|
||||||
|
name: 'googleApiWarning',
|
||||||
|
type: 'notice',
|
||||||
|
default: '',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
nodeCredentialType: ['googleApi'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Generic Auth Type',
|
displayName: 'Generic Auth Type',
|
||||||
name: 'genericAuthType',
|
name: 'genericAuthType',
|
||||||
|
|
Loading…
Reference in a new issue