mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
feat(JWT Node): New node (#9005)
Co-authored-by: Giulio Andreini <andreini@netseven.it>
This commit is contained in:
parent
9403657e46
commit
0a9f6b3de8
|
@ -71,8 +71,7 @@ export class jwtAuth implements ICredentialType {
|
||||||
displayName: 'Key Type',
|
displayName: 'Key Type',
|
||||||
name: 'keyType',
|
name: 'keyType',
|
||||||
type: 'options',
|
type: 'options',
|
||||||
description:
|
description: 'Choose either the secret passphrase or PEM encoded public keys',
|
||||||
'Choose either the secret passphrase for PEM encoded public keys for RSA and ECDSA',
|
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: 'Passphrase',
|
name: 'Passphrase',
|
||||||
|
|
19
packages/nodes-base/nodes/Jwt/Jwt.node.json
Normal file
19
packages/nodes-base/nodes/Jwt/Jwt.node.json
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"node": "n8n-nodes-base.jwt",
|
||||||
|
"nodeVersion": "1.0",
|
||||||
|
"codexVersion": "1.0",
|
||||||
|
"categories": ["Development"],
|
||||||
|
"alias": ["Token", "Key", "JSON", "Payload", "Sign", "Verify", "Decode"],
|
||||||
|
"resources": {
|
||||||
|
"credentialDocumentation": [
|
||||||
|
{
|
||||||
|
"url": "https://docs.n8n.io/credentials/jwt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryDocumentation": [
|
||||||
|
{
|
||||||
|
"url": "https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.jwt/"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
457
packages/nodes-base/nodes/Jwt/Jwt.node.ts
Normal file
457
packages/nodes-base/nodes/Jwt/Jwt.node.ts
Normal file
|
@ -0,0 +1,457 @@
|
||||||
|
import type {
|
||||||
|
IDataObject,
|
||||||
|
IExecuteFunctions,
|
||||||
|
INodeExecutionData,
|
||||||
|
INodeType,
|
||||||
|
INodeTypeDescription,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
import { NodeOperationError } from 'n8n-workflow';
|
||||||
|
|
||||||
|
import jwt from 'jsonwebtoken';
|
||||||
|
|
||||||
|
import { formatPrivateKey } from '../../utils/utilities';
|
||||||
|
import { parseJsonParameter } from '../Set/v2/helpers/utils';
|
||||||
|
|
||||||
|
const prettifyOperation = (operation: string) => {
|
||||||
|
if (operation === 'sign') {
|
||||||
|
return 'Sign a JWT';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation === 'decode') {
|
||||||
|
return 'Decode a JWT';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation === 'verify') {
|
||||||
|
return 'Verify a JWT';
|
||||||
|
}
|
||||||
|
|
||||||
|
return operation;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getToken = (ctx: IExecuteFunctions, itemIndex = 0) => {
|
||||||
|
const token = ctx.getNodeParameter('token', itemIndex) as string;
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
throw new NodeOperationError(ctx.getNode(), 'The JWT token was not provided', {
|
||||||
|
itemIndex,
|
||||||
|
description: "Be sure to add a valid JWT token to the 'Token' parameter",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return token;
|
||||||
|
};
|
||||||
|
|
||||||
|
export class Jwt implements INodeType {
|
||||||
|
description: INodeTypeDescription = {
|
||||||
|
displayName: 'JWT',
|
||||||
|
name: 'jwt',
|
||||||
|
icon: 'file:jwt.svg',
|
||||||
|
group: ['transform'],
|
||||||
|
version: 1,
|
||||||
|
description: 'JWT',
|
||||||
|
subtitle: `={{(${prettifyOperation})($parameter.operation)}}`,
|
||||||
|
defaults: {
|
||||||
|
name: 'JWT',
|
||||||
|
},
|
||||||
|
inputs: ['main'],
|
||||||
|
outputs: ['main'],
|
||||||
|
credentials: [
|
||||||
|
{
|
||||||
|
// eslint-disable-next-line n8n-nodes-base/node-class-description-credentials-name-unsuffixed
|
||||||
|
name: 'jwtAuth',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
displayName: 'Operation',
|
||||||
|
name: 'operation',
|
||||||
|
type: 'options',
|
||||||
|
noDataExpression: true,
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Decode',
|
||||||
|
value: 'decode',
|
||||||
|
action: 'Decode a JWT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Sign',
|
||||||
|
value: 'sign',
|
||||||
|
action: 'Sign a JWT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Verify',
|
||||||
|
value: 'verify',
|
||||||
|
action: 'Verify a JWT',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: 'sign',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Use JSON to Build Payload',
|
||||||
|
name: 'useJson',
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
description: 'Whether to use JSON to build the claims',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: ['sign'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Payload Claims',
|
||||||
|
name: 'claims',
|
||||||
|
type: 'collection',
|
||||||
|
placeholder: 'Add Claim',
|
||||||
|
default: {},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
displayName: 'Audience',
|
||||||
|
name: 'audience',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: 'e.g. https://example.com',
|
||||||
|
default: '',
|
||||||
|
description: 'Identifies the recipients that the JWT is intended for',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Expires In',
|
||||||
|
name: 'expiresIn',
|
||||||
|
type: 'number',
|
||||||
|
placeholder: 'e.g. 3600',
|
||||||
|
default: 3600,
|
||||||
|
description: 'The lifetime of the token in seconds',
|
||||||
|
typeOptions: {
|
||||||
|
minValue: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Issuer',
|
||||||
|
name: 'issuer',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: 'e.g. https://example.com',
|
||||||
|
default: '',
|
||||||
|
description: 'Identifies the principal that issued the JWT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'JWT ID',
|
||||||
|
name: 'jwtid',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: 'e.g. 123456',
|
||||||
|
default: '',
|
||||||
|
description: 'Unique identifier for the JWT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Not Before',
|
||||||
|
name: 'notBefore',
|
||||||
|
type: 'number',
|
||||||
|
default: 0,
|
||||||
|
description: 'The time before which the JWT must not be accepted for processing',
|
||||||
|
typeOptions: {
|
||||||
|
minValue: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Subject',
|
||||||
|
name: 'subject',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'Identifies the principal that is the subject of the JWT',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: ['sign'],
|
||||||
|
useJson: [false],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Payload Claims (JSON)',
|
||||||
|
name: 'claimsJson',
|
||||||
|
type: 'json',
|
||||||
|
description: 'Claims to add to the token in JSON format',
|
||||||
|
default: '{\n "my_field_1": "value 1",\n "my_field_2": "value 2"\n}\n',
|
||||||
|
validateType: 'object',
|
||||||
|
ignoreValidationDuringExecution: true,
|
||||||
|
typeOptions: {
|
||||||
|
rows: 5,
|
||||||
|
},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: ['sign'],
|
||||||
|
useJson: [true],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Token',
|
||||||
|
name: 'token',
|
||||||
|
type: 'string',
|
||||||
|
typeOptions: { password: true },
|
||||||
|
required: true,
|
||||||
|
validateType: 'jwt',
|
||||||
|
default: '',
|
||||||
|
description: 'The token to verify or decode',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: ['verify', 'decode'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
displayName: 'Options',
|
||||||
|
name: 'options',
|
||||||
|
type: 'collection',
|
||||||
|
placeholder: 'Add Option',
|
||||||
|
default: {},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
displayName: 'Return Additional Info',
|
||||||
|
name: 'complete',
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
description:
|
||||||
|
'Whether to return the complete decoded token with information about the header and signature or just the payload',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
'/operation': ['verify', 'decode'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Ignore Expiration',
|
||||||
|
name: 'ignoreExpiration',
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
description: 'Whether to ignore the expiration of the token',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
'/operation': ['verify'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Ignore Not Before Claim',
|
||||||
|
name: 'ignoreNotBefore',
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
description: 'Whether to ignore the not before claim of the token',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
'/operation': ['verify'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Clock Tolerance',
|
||||||
|
name: 'clockTolerance',
|
||||||
|
type: 'number',
|
||||||
|
default: 0,
|
||||||
|
description:
|
||||||
|
'Number of seconds to tolerate when checking the nbf and exp claims, to deal with small clock differences among different servers',
|
||||||
|
typeOptions: {
|
||||||
|
minValue: 0,
|
||||||
|
},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
'/operation': ['verify'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Override Algorithm',
|
||||||
|
name: 'algorithm',
|
||||||
|
type: 'options',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'ES256',
|
||||||
|
value: 'ES256',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'ES384',
|
||||||
|
value: 'ES384',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'ES512',
|
||||||
|
value: 'ES512',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'HS256',
|
||||||
|
value: 'HS256',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'HS384',
|
||||||
|
value: 'HS384',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'HS512',
|
||||||
|
value: 'HS512',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'PS256',
|
||||||
|
value: 'PS256',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'PS384',
|
||||||
|
value: 'PS384',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'PS512',
|
||||||
|
value: 'PS512',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'RS256',
|
||||||
|
value: 'RS256',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'RS384',
|
||||||
|
value: 'RS384',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'RS512',
|
||||||
|
value: 'RS512',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: 'HS256',
|
||||||
|
description:
|
||||||
|
'The algorithm to use for signing or verifying the token, overrides algorithm in credentials',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
'/operation': ['sign', 'verify'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||||
|
const items = this.getInputData();
|
||||||
|
const returnData: INodeExecutionData[] = [];
|
||||||
|
|
||||||
|
const operation = this.getNodeParameter('operation', 0);
|
||||||
|
|
||||||
|
const credentials = (await this.getCredentials('jwtAuth')) as {
|
||||||
|
keyType: 'passphrase' | 'pemKey';
|
||||||
|
publicKey: string;
|
||||||
|
privateKey: string;
|
||||||
|
secret: string;
|
||||||
|
algorithm: jwt.Algorithm;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
|
||||||
|
const options = this.getNodeParameter('options', itemIndex, {}) as {
|
||||||
|
algorithm?: jwt.Algorithm;
|
||||||
|
complete?: boolean;
|
||||||
|
ignoreExpiration?: boolean;
|
||||||
|
ignoreNotBefore?: boolean;
|
||||||
|
clockTolerance?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (operation === 'sign') {
|
||||||
|
const useJson = this.getNodeParameter('useJson', itemIndex) as boolean;
|
||||||
|
|
||||||
|
let payload: IDataObject = {};
|
||||||
|
|
||||||
|
if (useJson) {
|
||||||
|
payload = parseJsonParameter(
|
||||||
|
this.getNodeParameter('claimsJson', itemIndex) as IDataObject,
|
||||||
|
this.getNode(),
|
||||||
|
itemIndex,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
payload = this.getNodeParameter('claims', itemIndex) as IDataObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
let secretOrPrivateKey;
|
||||||
|
|
||||||
|
if (credentials.keyType === 'passphrase') {
|
||||||
|
secretOrPrivateKey = credentials.secret;
|
||||||
|
} else {
|
||||||
|
secretOrPrivateKey = formatPrivateKey(credentials.privateKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
const token = jwt.sign(payload, secretOrPrivateKey, {
|
||||||
|
algorithm: options.algorithm ?? credentials.algorithm,
|
||||||
|
});
|
||||||
|
|
||||||
|
returnData.push({
|
||||||
|
json: { token },
|
||||||
|
pairedItem: itemIndex,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation === 'verify') {
|
||||||
|
const token = getToken(this, itemIndex);
|
||||||
|
|
||||||
|
let secretOrPublicKey;
|
||||||
|
|
||||||
|
if (credentials.keyType === 'passphrase') {
|
||||||
|
secretOrPublicKey = credentials.secret;
|
||||||
|
} else {
|
||||||
|
secretOrPublicKey = formatPrivateKey(credentials.publicKey, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { ignoreExpiration, ignoreNotBefore, clockTolerance, complete } = options;
|
||||||
|
|
||||||
|
const data = jwt.verify(token, secretOrPublicKey, {
|
||||||
|
algorithms: [options.algorithm ?? credentials.algorithm],
|
||||||
|
ignoreExpiration,
|
||||||
|
ignoreNotBefore,
|
||||||
|
clockTolerance,
|
||||||
|
complete,
|
||||||
|
});
|
||||||
|
|
||||||
|
const json = options.complete && data ? (data as IDataObject) : { payload: data };
|
||||||
|
|
||||||
|
returnData.push({
|
||||||
|
json,
|
||||||
|
pairedItem: itemIndex,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation === 'decode') {
|
||||||
|
const token = getToken(this, itemIndex);
|
||||||
|
|
||||||
|
const data = jwt.decode(token, { complete: options.complete });
|
||||||
|
|
||||||
|
const json = options.complete && data ? (data as IDataObject) : { payload: data };
|
||||||
|
|
||||||
|
returnData.push({
|
||||||
|
json,
|
||||||
|
pairedItem: itemIndex,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error.message === 'invalid signature') {
|
||||||
|
error = new NodeOperationError(this.getNode(), "The JWT token can't be verified", {
|
||||||
|
itemIndex,
|
||||||
|
description:
|
||||||
|
'Be sure that the provided JWT token is correctly encoded and matches the selected credentials',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (this.continueOnFail()) {
|
||||||
|
returnData.push({
|
||||||
|
json: this.getInputData(itemIndex)[0].json,
|
||||||
|
error,
|
||||||
|
pairedItem: itemIndex,
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (error.context) {
|
||||||
|
error.context.itemIndex = itemIndex;
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
throw new NodeOperationError(this.getNode(), error, {
|
||||||
|
itemIndex,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [returnData];
|
||||||
|
}
|
||||||
|
}
|
112
packages/nodes-base/nodes/Jwt/jwt.svg
Normal file
112
packages/nodes-base/nodes/Jwt/jwt.svg
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
width="200px"
|
||||||
|
height="200px"
|
||||||
|
viewBox="0 0 200 200"
|
||||||
|
version="1.1"
|
||||||
|
id="svg10"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||||
|
<!-- Generator: Sketch 3.3.2 (12043) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title
|
||||||
|
id="title1">Group</title>
|
||||||
|
<desc
|
||||||
|
id="desc1">Created with Sketch.</desc>
|
||||||
|
<defs
|
||||||
|
id="defs1">
|
||||||
|
<filter
|
||||||
|
style="color-interpolation-filters:sRGB"
|
||||||
|
id="filter11"
|
||||||
|
x="-0.18346753"
|
||||||
|
y="-0.076523014"
|
||||||
|
width="1.3669351"
|
||||||
|
height="1.153046">
|
||||||
|
<feGaussianBlur
|
||||||
|
stdDeviation="1.2230926"
|
||||||
|
id="feGaussianBlur11" />
|
||||||
|
</filter>
|
||||||
|
<filter
|
||||||
|
style="color-interpolation-filters:sRGB"
|
||||||
|
id="filter12"
|
||||||
|
x="-0.18346753"
|
||||||
|
y="-0.076523014"
|
||||||
|
width="1.3669351"
|
||||||
|
height="1.153046">
|
||||||
|
<feGaussianBlur
|
||||||
|
stdDeviation="1.2230926"
|
||||||
|
id="feGaussianBlur12" />
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="layer1" />
|
||||||
|
<g
|
||||||
|
transform="translate(57.626456,48.948311)"
|
||||||
|
id="Shape-6">
|
||||||
|
<g
|
||||||
|
id="g12"
|
||||||
|
transform="matrix(1.8791546,0,0,1.8791546,-51.584186,-42.862227)">
|
||||||
|
<path
|
||||||
|
d="M 42.223544,27.435493 V -0.303311 H 58.223226 V 27.435493 L 50.223385,38.05668 Z"
|
||||||
|
fill="#ffffff"
|
||||||
|
id="path11"
|
||||||
|
style="fill:#ececec;stroke-width:1.04876;filter:url(#filter12)" />
|
||||||
|
<path
|
||||||
|
d="M 57.5,26.9 V 0 h -15 V 26.9 L 50,37.2 Z"
|
||||||
|
fill="#ffffff"
|
||||||
|
id="path1-7" />
|
||||||
|
<path
|
||||||
|
d="M 42.223544,72.517876 V 100.25668 H 58.223226 V 72.517876 L 50.223385,61.896689 Z"
|
||||||
|
fill="#ffffff"
|
||||||
|
id="path10"
|
||||||
|
style="fill:#ececec;stroke-width:1.04876;filter:url(#filter11)" />
|
||||||
|
<path
|
||||||
|
d="m 42.623319,73.156936 v 26.900004 h 15 V 73.156936 l -7.5,-10.3 z"
|
||||||
|
fill="#ffffff"
|
||||||
|
id="path2-5" />
|
||||||
|
<path
|
||||||
|
d="M 57.5,73.1 73.3,94.9 85.5,86 69.6,64.3 57.5,60.3 Z"
|
||||||
|
fill="#00f2e6"
|
||||||
|
id="path3-3" />
|
||||||
|
<path
|
||||||
|
d="M 42.5,26.9 26.7,5.1 14.5,14 l 15.9,21.7 12.1,4 z"
|
||||||
|
fill="#00f2e6"
|
||||||
|
id="path4-5" />
|
||||||
|
<path
|
||||||
|
d="M 30.4,35.7 4.8,27.4 0.1,41.7 25.7,50 37.9,46.1 Z"
|
||||||
|
fill="#00b9f1"
|
||||||
|
id="path5-6" />
|
||||||
|
<path
|
||||||
|
d="M 62.1,53.9 69.6,64.3 95.2,72.6 99.9,58.3 74.3,50 Z"
|
||||||
|
fill="#00b9f1"
|
||||||
|
id="path6-2" />
|
||||||
|
<path
|
||||||
|
d="M 74.3,50 99.9,41.7 95.2,27.4 69.6,35.7 62.1,46.1 Z"
|
||||||
|
fill="#d63aff"
|
||||||
|
id="path7-9" />
|
||||||
|
<path
|
||||||
|
d="M 25.7,50 0.1,58.3 4.8,72.6 30.4,64.3 37.9,53.9 Z"
|
||||||
|
fill="#d63aff"
|
||||||
|
id="path8-1" />
|
||||||
|
<path
|
||||||
|
d="M 30.4,64.3 14.5,86 26.7,94.9 42.5,73.1 V 60.3 Z"
|
||||||
|
fill="#fb015b"
|
||||||
|
id="path9-2" />
|
||||||
|
<path
|
||||||
|
d="M 69.6,35.7 85.5,14 73.3,5.1 57.5,26.9 v 12.8 z"
|
||||||
|
fill="#fb015b"
|
||||||
|
id="path10-7" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<metadata
|
||||||
|
id="metadata12">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:title>Group</dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.2 KiB |
4
packages/nodes-base/nodes/Jwt/test/Jwt.node.test.ts
Normal file
4
packages/nodes-base/nodes/Jwt/test/Jwt.node.test.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers';
|
||||||
|
const workflows = getWorkflowFilenames(__dirname);
|
||||||
|
|
||||||
|
describe('Test Jwt Node', () => testWorkflows(workflows));
|
412
packages/nodes-base/nodes/Jwt/test/jwt.workflow.json
Normal file
412
packages/nodes-base/nodes/Jwt/test/jwt.workflow.json
Normal file
|
@ -0,0 +1,412 @@
|
||||||
|
{
|
||||||
|
"name": "My workflow 31",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"id": "fcc3e9dc-90c9-4b26-9b44-e661e0ebf658",
|
||||||
|
"name": "When clicking \"Test workflow\"",
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [
|
||||||
|
780,
|
||||||
|
380
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"claims": {
|
||||||
|
"audience": "test",
|
||||||
|
"issuer": "test",
|
||||||
|
"jwtid": "123",
|
||||||
|
"subject": "test"
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"id": "6b1ba38f-60d8-482a-a7d4-4fee7054334b",
|
||||||
|
"name": "JWT",
|
||||||
|
"type": "n8n-nodes-base.jwt",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [
|
||||||
|
1000,
|
||||||
|
380
|
||||||
|
],
|
||||||
|
"credentials": {
|
||||||
|
"jwtAuth": {
|
||||||
|
"id": "AosB7WdhmVA3be8t",
|
||||||
|
"name": "JWT Auth test"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"operation": "decode",
|
||||||
|
"token": "={{ $json.token }}",
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"id": "d07b9335-29a0-41bc-a6c4-0232d94a0559",
|
||||||
|
"name": "JWT1",
|
||||||
|
"type": "n8n-nodes-base.jwt",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [
|
||||||
|
1260,
|
||||||
|
220
|
||||||
|
],
|
||||||
|
"credentials": {
|
||||||
|
"jwtAuth": {
|
||||||
|
"id": "AosB7WdhmVA3be8t",
|
||||||
|
"name": "JWT Auth test"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"operation": "verify",
|
||||||
|
"token": "={{ $json.token }}",
|
||||||
|
"options": {
|
||||||
|
"complete": true,
|
||||||
|
"ignoreExpiration": true,
|
||||||
|
"ignoreNotBefore": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": "b6228805-f0c1-479d-bbec-cefcde7298e3",
|
||||||
|
"name": "JWT2",
|
||||||
|
"type": "n8n-nodes-base.jwt",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [
|
||||||
|
1280,
|
||||||
|
440
|
||||||
|
],
|
||||||
|
"credentials": {
|
||||||
|
"jwtAuth": {
|
||||||
|
"id": "AosB7WdhmVA3be8t",
|
||||||
|
"name": "JWT Auth test"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"useJson": true,
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"id": "56ede43f-6771-4341-8c17-ba4b9185711a",
|
||||||
|
"name": "JWT3",
|
||||||
|
"type": "n8n-nodes-base.jwt",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [
|
||||||
|
1000,
|
||||||
|
640
|
||||||
|
],
|
||||||
|
"credentials": {
|
||||||
|
"jwtAuth": {
|
||||||
|
"id": "G45TOKX5kBEraTr1",
|
||||||
|
"name": "JWT Auth test PEM"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"operation": "decode",
|
||||||
|
"token": "={{ $json.token }}",
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"id": "1b57af10-710f-4b86-9020-e1fc43a222cd",
|
||||||
|
"name": "JWT4",
|
||||||
|
"type": "n8n-nodes-base.jwt",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [
|
||||||
|
1280,
|
||||||
|
640
|
||||||
|
],
|
||||||
|
"credentials": {
|
||||||
|
"jwtAuth": {
|
||||||
|
"id": "G45TOKX5kBEraTr1",
|
||||||
|
"name": "JWT Auth test PEM"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"operation": "verify",
|
||||||
|
"token": "={{ $json.token }}",
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"id": "9a658330-ecc3-4007-9524-534ad15a3a40",
|
||||||
|
"name": "JWT5",
|
||||||
|
"type": "n8n-nodes-base.jwt",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [
|
||||||
|
1280,
|
||||||
|
860
|
||||||
|
],
|
||||||
|
"credentials": {
|
||||||
|
"jwtAuth": {
|
||||||
|
"id": "G45TOKX5kBEraTr1",
|
||||||
|
"name": "JWT Auth test PEM"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"assignments": {
|
||||||
|
"assignments": [
|
||||||
|
{
|
||||||
|
"id": "1289f607-d46f-45f5-953a-1492f3b50bbd",
|
||||||
|
"name": "payload.audience",
|
||||||
|
"value": "={{ $json.payload.audience }}",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "e32ae71b-62ca-45e5-8351-2fd9ab7451ef",
|
||||||
|
"name": "payload.jwtid",
|
||||||
|
"value": "={{ $json.payload.jwtid }}",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"id": "51a6c4b9-ebae-4ffa-a870-9915c3304cd5",
|
||||||
|
"name": "Edit Fields",
|
||||||
|
"type": "n8n-nodes-base.set",
|
||||||
|
"typeVersion": 3.3,
|
||||||
|
"position": [
|
||||||
|
1500,
|
||||||
|
220
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"assignments": {
|
||||||
|
"assignments": [
|
||||||
|
{
|
||||||
|
"id": "3ff845d5-9c2c-4744-bc33-a7318b4741fc",
|
||||||
|
"name": "payload.audience",
|
||||||
|
"value": "={{ $json.payload.audience }}",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "d1206579-634e-472a-9190-a176cf2477a1",
|
||||||
|
"name": "payload.jwtid",
|
||||||
|
"value": "={{ $json.payload.jwtid }}",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"id": "9e97ea34-ec32-4935-b116-e40815567e1c",
|
||||||
|
"name": "Edit Fields1",
|
||||||
|
"type": "n8n-nodes-base.set",
|
||||||
|
"typeVersion": 3.3,
|
||||||
|
"position": [
|
||||||
|
1520,
|
||||||
|
440
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"assignments": {
|
||||||
|
"assignments": [
|
||||||
|
{
|
||||||
|
"id": "46ed5c03-d41a-4387-988e-2ed3821f32d4",
|
||||||
|
"name": "payload.my_field_1",
|
||||||
|
"value": "={{ $json.payload.my_field_1 }}",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "0007786e-3f93-4146-8e10-32ab8e088b81",
|
||||||
|
"name": "payload.my_field_2",
|
||||||
|
"value": "={{ $json.payload.my_field_2 }}",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"id": "f205e447-2a98-48ef-bba5-12e9aecab90e",
|
||||||
|
"name": "Edit Fields2",
|
||||||
|
"type": "n8n-nodes-base.set",
|
||||||
|
"typeVersion": 3.3,
|
||||||
|
"position": [
|
||||||
|
1520,
|
||||||
|
860
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"assignments": {
|
||||||
|
"assignments": [
|
||||||
|
{
|
||||||
|
"id": "fe90f817-1b89-409c-992c-e42070fc67bf",
|
||||||
|
"name": "payload.my_field_1",
|
||||||
|
"value": "={{ $json.payload.my_field_1 }}",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "1b80e8b3-3004-4959-8c6c-0d36176579ea",
|
||||||
|
"name": "payload.my_field_2",
|
||||||
|
"value": "={{ $json.payload.my_field_2 }}",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"id": "0788f03e-0c1c-4e21-a408-9441930cd82f",
|
||||||
|
"name": "Edit Fields3",
|
||||||
|
"type": "n8n-nodes-base.set",
|
||||||
|
"typeVersion": 3.3,
|
||||||
|
"position": [
|
||||||
|
1520,
|
||||||
|
640
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"pinData": {
|
||||||
|
"Edit Fields": [
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"payload": {
|
||||||
|
"audience": "test",
|
||||||
|
"jwtid": "123"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Edit Fields1": [
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"payload": {
|
||||||
|
"audience": "test",
|
||||||
|
"jwtid": "123"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Edit Fields3": [
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"payload": {
|
||||||
|
"my_field_1": "value 1",
|
||||||
|
"my_field_2": "value 2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Edit Fields2": [
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"payload": {
|
||||||
|
"my_field_1": "value 1",
|
||||||
|
"my_field_2": "value 2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"connections": {
|
||||||
|
"When clicking \"Test workflow\"": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "JWT",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"node": "JWT3",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"JWT": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "JWT1",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"node": "JWT2",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"JWT3": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "JWT4",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"node": "JWT5",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"JWT1": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Edit Fields",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"JWT2": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Edit Fields1",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"JWT4": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Edit Fields3",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"JWT5": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Edit Fields2",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"active": false,
|
||||||
|
"settings": {
|
||||||
|
"executionOrder": "v1"
|
||||||
|
},
|
||||||
|
"versionId": "f70ffef1-3c5d-4991-a3aa-b4141b93e4cb",
|
||||||
|
"meta": {
|
||||||
|
"templateCredsSetupCompleted": true,
|
||||||
|
"instanceId": "be251a83c052a9862eeac953816fbb1464f89dfbf79d7ac490a8e336a8cc8bfd"
|
||||||
|
},
|
||||||
|
"id": "H0sZEXDuE7VIP5vz",
|
||||||
|
"tags": []
|
||||||
|
}
|
|
@ -287,7 +287,7 @@ export class Webhook extends Node {
|
||||||
if (expectedAuth.keyType === 'passphrase') {
|
if (expectedAuth.keyType === 'passphrase') {
|
||||||
secretOrPublicKey = expectedAuth.secret;
|
secretOrPublicKey = expectedAuth.secret;
|
||||||
} else {
|
} else {
|
||||||
secretOrPublicKey = formatPrivateKey(expectedAuth.publicKey);
|
secretOrPublicKey = formatPrivateKey(expectedAuth.publicKey, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -574,6 +574,7 @@
|
||||||
"dist/nodes/Jira/Jira.node.js",
|
"dist/nodes/Jira/Jira.node.js",
|
||||||
"dist/nodes/Jira/JiraTrigger.node.js",
|
"dist/nodes/Jira/JiraTrigger.node.js",
|
||||||
"dist/nodes/JotForm/JotFormTrigger.node.js",
|
"dist/nodes/JotForm/JotFormTrigger.node.js",
|
||||||
|
"dist/nodes/Jwt/Jwt.node.js",
|
||||||
"dist/nodes/Kafka/Kafka.node.js",
|
"dist/nodes/Kafka/Kafka.node.js",
|
||||||
"dist/nodes/Kafka/KafkaTrigger.node.js",
|
"dist/nodes/Kafka/KafkaTrigger.node.js",
|
||||||
"dist/nodes/Keap/Keap.node.js",
|
"dist/nodes/Keap/Keap.node.js",
|
||||||
|
|
|
@ -6,6 +6,51 @@ export const FAKE_CREDENTIALS_DATA = {
|
||||||
[JSON.stringify({ id: '20', name: 'Airtable account' })]: {
|
[JSON.stringify({ id: '20', name: 'Airtable account' })]: {
|
||||||
apiKey: 'key456',
|
apiKey: 'key456',
|
||||||
},
|
},
|
||||||
|
[JSON.stringify({ id: 'G45TOKX5kBEraTr1', name: 'JWT Auth test PEM' })]: {
|
||||||
|
keyType: 'pemKey',
|
||||||
|
privateKey: `
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCfw0m1K+M1/6Tw
|
||||||
|
CvLYDv0gmxa+reEdKBfT0/hfkkjFWqbMRo0f4CQ3PwrOavS+80PDy6nVL21BmGev
|
||||||
|
w1bF7KXmqOzr+yKOUJ8A4u6vXUQKzVSFBqb2YZmZL1s7va9aaO6pVANTbmYHpTjh
|
||||||
|
SBnBrXgidVOXNX1c+IG+OZZMiTFWg4lJTE9rvMbLh4o5FPwdZlA1rLAux4KXVNNr
|
||||||
|
mE7T5/tsuikR06KMJS6V6YR4PZmTsy/3D2clADXDCtbUdEe0eBYoUmRLMhRL6umq
|
||||||
|
h98Dsm5ZG+YB2dn0ThR/g7DPVwvmnrK2S5e4hpqFYxQ8V8pGx7dQLsc/utbvsn32
|
||||||
|
dctGivkFAgMBAAECggEABDB0QdZtRlC2S/8VgBnghFbcwVJA6WlQOqM/y43D77zh
|
||||||
|
S9D7yV6wxGwYRfJjCZDKcZtpECiGtmYfLeoy38zFSueaEtQKg23UxYqt1JZe/uOE
|
||||||
|
eFqEzUgg5XXq8AWY0AeZXoJP9gOalE++TpX76uq4EDtAXmIuL95qVIkhCk+8pfaR
|
||||||
|
avLcejnyYGSJAG1J9pXHNChXXDVPd7PrIa20A44osvusifVMlcIYM3qkv167ULzX
|
||||||
|
4nu2hZwlNxGKtpVPldFY/qu5S7SdLo/2BQinrMSSKRSFihA4Uuod8GK0+UwjE4gO
|
||||||
|
TD15bjqIcadlAYV6bn34sHnMU9hjhPB5NyXiINYdsQKBgQDNu0XFjYyAgwORaZYs
|
||||||
|
jVTJg+fQ9wM7xnlfxXCVb9eoOGF0blW9VjIEz8lLjmPlPFFVS+EPN0andHHqH4t5
|
||||||
|
SQZVZxgNMcodWs8BJTVZUkXa+IljHXT1Vkb2zvtH96ADzs3c43+tNpmKhjG3XK1U
|
||||||
|
rL/v8feU31nwQb7imOmYmzbHCQKBgQDGzJ/pRLByB24W6FRfHIItP81vVg5ckCXi
|
||||||
|
sIhzHUdUmTdVbdAxeS6IW2oAc/IuksvmiZMLYsm+sIFFePJQrBsoD41R5VsFcJqE
|
||||||
|
o5x0DUzbOzqaV4HPOHDniibudyryZKnBvkXlCjyCv4iPKaFhH4T1aB+wdK4pJPo2
|
||||||
|
fyABs2lFHQKBgQDHz6IFK+QREK3PdhA/twhpK65jWvUOAkbxyE3/JX/7xr6IGX02
|
||||||
|
hdfQqoqj0midRMbto+OzJol9q+/TZs3MfysimR1X+0qE1iSExUGaPfjQomC1He/x
|
||||||
|
M9l6bi7Jh+wmpp10cpQXhBb93jW9E8rYmWtVPNmsAn1UhlZBuCfwapd6GQKBgATM
|
||||||
|
f7ezzsaR41huN0ssdv/8oErluucFG8UDGegddtFV+X34bqQjFrp36nEkW15AcOeZ
|
||||||
|
vpDxy4js3dH9f2vvG6C172VgsffJphE5mdc7UvWf0mRTZHDKHf+Y2CO9gK3lPCvP
|
||||||
|
GgTTYG6PjQ5XpOuhRSZfYxRxXJrlp5yVKQKhgBMJAoGBAMc6ktd0iqHAYCW3d9QP
|
||||||
|
e618RiMlVIYZIUlLWAUQWQSf3linqMjo1rCbbI/lSxE216XwI/VBX50gg/Oy3aUl
|
||||||
|
CibHHk2aKGlxVxe0Huv5gcjbZgVh1EMi4oxh4600IrWRH1Uz5AleXnheNiappKnA
|
||||||
|
lOMhy99LXMlAOL7qOBnZHgrm
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
`,
|
||||||
|
publicKey: `
|
||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn8NJtSvjNf+k8Ary2A79
|
||||||
|
IJsWvq3hHSgX09P4X5JIxVqmzEaNH+AkNz8Kzmr0vvNDw8up1S9tQZhnr8NWxeyl
|
||||||
|
5qjs6/sijlCfAOLur11ECs1UhQam9mGZmS9bO72vWmjuqVQDU25mB6U44UgZwa14
|
||||||
|
InVTlzV9XPiBvjmWTIkxVoOJSUxPa7zGy4eKORT8HWZQNaywLseCl1TTa5hO0+f7
|
||||||
|
bLopEdOijCUulemEeD2Zk7Mv9w9nJQA1wwrW1HRHtHgWKFJkSzIUS+rpqoffA7Ju
|
||||||
|
WRvmAdnZ9E4Uf4Owz1cL5p6ytkuXuIaahWMUPFfKRse3UC7HP7rW77J99nXLRor5
|
||||||
|
BQIDAQAB
|
||||||
|
-----END PUBLIC KEY-----
|
||||||
|
`,
|
||||||
|
algorithm: 'RS256',
|
||||||
|
},
|
||||||
airtableApi: {
|
airtableApi: {
|
||||||
apiKey: 'key123',
|
apiKey: 'key123',
|
||||||
},
|
},
|
||||||
|
@ -45,4 +90,9 @@ export const FAKE_CREDENTIALS_DATA = {
|
||||||
refresh_token: 'REFRESHTOKEN',
|
refresh_token: 'REFRESHTOKEN',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
jwtAuth: {
|
||||||
|
keyType: 'passphrase',
|
||||||
|
secret: 'baz',
|
||||||
|
algorithm: 'HS256',
|
||||||
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
|
@ -223,14 +223,17 @@ export const keysToLowercase = <T>(headers: T) => {
|
||||||
* @param privateKey - The private key to format.
|
* @param privateKey - The private key to format.
|
||||||
* @returns The formatted private key.
|
* @returns The formatted private key.
|
||||||
*/
|
*/
|
||||||
export function formatPrivateKey(privateKey: string): string {
|
export function formatPrivateKey(privateKey: string, keyIsPublic = false): string {
|
||||||
|
let regex = /(PRIVATE KEY|CERTIFICATE)/;
|
||||||
|
if (keyIsPublic) {
|
||||||
|
regex = /(PUBLIC KEY)/;
|
||||||
|
}
|
||||||
if (!privateKey || /\n/.test(privateKey)) {
|
if (!privateKey || /\n/.test(privateKey)) {
|
||||||
return privateKey;
|
return privateKey;
|
||||||
}
|
}
|
||||||
let formattedPrivateKey = '';
|
let formattedPrivateKey = '';
|
||||||
const parts = privateKey.split('-----').filter((item) => item !== '');
|
const parts = privateKey.split('-----').filter((item) => item !== '');
|
||||||
parts.forEach((part) => {
|
parts.forEach((part) => {
|
||||||
const regex = /(PRIVATE KEY|CERTIFICATE)/;
|
|
||||||
if (regex.test(part)) {
|
if (regex.test(part)) {
|
||||||
formattedPrivateKey += `-----${part}-----`;
|
formattedPrivateKey += `-----${part}-----`;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2341,7 +2341,8 @@ export type FieldType =
|
||||||
| 'array'
|
| 'array'
|
||||||
| 'object'
|
| 'object'
|
||||||
| 'options'
|
| 'options'
|
||||||
| 'url';
|
| 'url'
|
||||||
|
| 'jwt';
|
||||||
|
|
||||||
export type ValidationResult = {
|
export type ValidationResult = {
|
||||||
valid: boolean;
|
valid: boolean;
|
||||||
|
|
|
@ -158,6 +158,20 @@ export const tryToParseUrl = (value: unknown): string => {
|
||||||
return String(value);
|
return String(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const tryToParseJwt = (value: unknown): string => {
|
||||||
|
const error = new ApplicationError(`The value "${String(value)}" is not a valid JWT token.`, {
|
||||||
|
extra: { value },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!value) throw error;
|
||||||
|
|
||||||
|
const jwtPattern = /^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_.+/=]*$/;
|
||||||
|
|
||||||
|
if (!jwtPattern.test(String(value))) throw error;
|
||||||
|
|
||||||
|
return String(value);
|
||||||
|
};
|
||||||
|
|
||||||
type ValidateFieldTypeOptions = Partial<{
|
type ValidateFieldTypeOptions = Partial<{
|
||||||
valueOptions: INodePropertyOptions[];
|
valueOptions: INodePropertyOptions[];
|
||||||
strict: boolean;
|
strict: boolean;
|
||||||
|
@ -279,6 +293,16 @@ export const validateFieldType = (
|
||||||
return { valid: false, errorMessage: defaultErrorMessage };
|
return { valid: false, errorMessage: defaultErrorMessage };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case 'jwt': {
|
||||||
|
try {
|
||||||
|
return { valid: true, newValue: tryToParseJwt(value) };
|
||||||
|
} catch (e) {
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
errorMessage: 'Value is not a valid JWT token',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
return { valid: true, newValue: value };
|
return { valid: true, newValue: value };
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue