@dendaio/n8n-nodes-collection
Version:
🚀 Comprehensive n8n node collection for financial analysis and automation. Features 55+ technical indicators (RSI, MACD, Bollinger Bands), 32+ candlestick patterns (Doji, Hammer, Engulfing), automated trading strategies, RSS feed processing, and OAuth2 v
261 lines • 12.4 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.Oauth2Validator = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const jose = __importStar(require("jose"));
class Oauth2Validator {
constructor() {
this.description = {
displayName: 'OAuth2 Validator',
name: 'oauth2Validator',
icon: 'file:oauth2.svg',
group: ['transform'],
version: 1,
description: 'Validate OAuth2 access tokens against an issuer',
defaults: {
name: 'OAuth2 Validator',
},
inputs: ["main"],
outputs: [
{
displayName: 'Validated',
type: "main",
},
{
displayName: 'Failed',
type: "main",
},
],
credentials: [
{
name: 'oauth2ValidatorConfigApi',
required: true,
},
],
properties: [
{
displayName: 'Authorization Header',
name: 'authorizationHeader',
type: 'string',
default: 'authorization',
description: 'The name of the header containing the authorization token',
},
{
displayName: 'Token Prefix',
name: 'tokenPrefix',
type: 'string',
typeOptions: { password: true },
default: 'Bearer ',
description: 'The prefix to remove from the token (e.g., "Bearer " for "Bearer token123")',
},
{
displayName: 'Options',
name: 'options',
type: 'collection',
placeholder: 'Add Option',
default: {},
options: [
{
displayName: 'Clock Tolerance',
name: 'clockTolerance',
type: 'number',
default: 30,
description: 'Clock tolerance in seconds for token validation',
},
{
displayName: 'Default Key ID',
name: 'defaultKeyId',
type: 'string',
default: '',
description: 'Default key ID to use when token header does not specify a KID (optional)',
},
{
displayName: 'Include Token Claims',
name: 'includeClaims',
type: 'boolean',
default: false,
description: 'Whether to include the decoded token claims in the output',
},
{
displayName: 'Validate Audience',
name: 'validateAudience',
type: 'boolean',
default: true,
description: 'Whether to validate the audience claim',
},
{
displayName: 'Validate Expiration',
name: 'validateExpiration',
type: 'boolean',
default: true,
description: 'Whether to validate token expiration',
},
{
displayName: 'Validate Issuer',
name: 'validateIssuer',
type: 'boolean',
default: true,
description: 'Whether to validate the issuer claim',
},
],
},
],
};
}
async execute() {
const items = this.getInputData();
const validatedData = [];
const failedData = [];
const credentials = await this.getCredentials('oauth2ValidatorConfigApi');
const authorizationHeader = this.getNodeParameter('authorizationHeader', 0);
const tokenPrefix = this.getNodeParameter('tokenPrefix', 0);
const options = this.getNodeParameter('options', 0);
const openidConfigUrl = credentials.openidConfigUrl;
if (!openidConfigUrl) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'OpenID Connect configuration URL is required');
}
const openidConfigResponse = await fetch(openidConfigUrl);
if (!openidConfigResponse.ok) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to fetch OpenID Connect configuration from ${openidConfigUrl}: ${openidConfigResponse.statusText}`);
}
const openidConfig = (await openidConfigResponse.json());
if (!openidConfig.issuer || !openidConfig.jwks_uri) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Invalid OpenID Connect configuration: missing issuer or jwks_uri');
}
for (let i = 0; i < items.length; i++) {
try {
const item = items[i];
const headers = item.json.headers || {};
const authHeaderValue = headers[authorizationHeader];
if (!authHeaderValue) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Authorization header '${authorizationHeader}' not found in request headers`);
}
let token = authHeaderValue;
if (tokenPrefix && authHeaderValue.startsWith(tokenPrefix)) {
token = authHeaderValue.substring(tokenPrefix.length);
}
if (!token) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No token found in authorization header');
}
let decoded;
try {
const jwks = jose.createRemoteJWKSet(new URL(openidConfig.jwks_uri));
const verifyOptions = {
issuer: options.validateIssuer !== false ? openidConfig.issuer : undefined,
audience: options.validateAudience !== false && credentials.audience
? credentials.audience
: undefined,
clockTolerance: options.validateExpiration !== false
? options.clockTolerance || 30
: undefined,
};
const result = await jose.jwtVerify(token, jwks, verifyOptions);
decoded = result.payload;
}
catch (jwsError) {
const clientSecret = credentials.clientSecret;
if (!clientSecret) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Client secret is required for JWE token decryption. Please configure the client secret in credentials.');
}
try {
let key;
if (clientSecret.length === 32) {
key = new TextEncoder().encode(clientSecret);
}
else if (clientSecret.length > 32) {
key = new TextEncoder().encode(clientSecret.substring(0, 32));
}
else {
const paddedSecret = clientSecret.padEnd(32, '0');
key = new TextEncoder().encode(paddedSecret);
}
const decrypted = await jose.compactDecrypt(token, key);
decoded = JSON.parse(new TextDecoder().decode(decrypted.plaintext));
if (options.validateIssuer !== false && decoded.iss !== openidConfig.issuer) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid issuer. Expected: ${openidConfig.issuer}, Got: ${decoded.iss}`);
}
if (options.validateAudience !== false &&
credentials.audience &&
decoded.aud !== credentials.audience) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid audience. Expected: ${credentials.audience}, Got: ${decoded.aud}`);
}
if (options.validateExpiration !== false) {
const now = Math.floor(Date.now() / 1000);
const clockTolerance = options.clockTolerance || 30;
if (decoded.exp && now > decoded.exp + clockTolerance) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Token has expired');
}
if (decoded.iat && now < decoded.iat - clockTolerance) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Token issued in the future');
}
}
}
catch (jweError) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `JWS verification failed: ${jwsError.message}. JWE decryption also failed: ${jweError.message}`);
}
}
const validatedItem = {
json: {
issuer: openidConfig.issuer,
subject: decoded.sub,
audience: decoded.aud,
issuedAt: decoded.iat,
expiresAt: decoded.exp,
...item.json,
},
};
if (options.includeClaims) {
validatedItem.json.claims = decoded;
}
validatedData.push(validatedItem);
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
const failedItem = {
json: {
error: errorMessage,
issuer: openidConfig.issuer,
...items[i].json,
},
};
failedData.push(failedItem);
}
}
return [validatedData, failedData];
}
}
exports.Oauth2Validator = Oauth2Validator;
//# sourceMappingURL=Oauth2Validator.node.js.map