first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled

This commit is contained in:
2026-03-17 16:22:57 +03:30
commit 3d5eaf9445
15349 changed files with 2847338 additions and 0 deletions
@@ -0,0 +1,61 @@
import type { TokenCredential, AccessToken } from '@azure/identity';
import type { ClientOAuth2TokenData } from '@n8n/client-oauth2';
import { ClientOAuth2 } from '@n8n/client-oauth2';
import type { INode } from 'n8n-workflow';
import { NodeOperationError } from 'n8n-workflow';
import type { AzureEntraCognitiveServicesOAuth2ApiCredential } from '../types';
/**
* Adapts n8n's credential retrieval into the TokenCredential interface expected by @azure/identity
*/
export class N8nOAuth2TokenCredential implements TokenCredential {
constructor(
private node: INode,
private credential: AzureEntraCognitiveServicesOAuth2ApiCredential,
) {}
/**
* Gets an access token from OAuth credential
*/
async getToken(): Promise<AccessToken | null> {
try {
if (!this.credential?.oauthTokenData?.access_token) {
throw new NodeOperationError(this.node, 'Failed to retrieve access token');
}
const oAuthClient = new ClientOAuth2({
clientId: this.credential.clientId,
clientSecret: this.credential.clientSecret,
accessTokenUri: this.credential.accessTokenUrl,
scopes: this.credential.scope?.split(' '),
authentication: this.credential.authentication,
authorizationUri: this.credential.authUrl,
additionalBodyProperties: {
resource: 'https://cognitiveservices.azure.com/',
},
});
const token = await oAuthClient.credentials.getToken();
const data = token.data as ClientOAuth2TokenData & {
expires_on: number;
};
return {
token: data.access_token,
expiresOnTimestamp: data.expires_on,
};
} catch (error) {
// Re-throw with better error message
throw new NodeOperationError(this.node, 'Failed to retrieve OAuth2 access token', error);
}
}
/**
* Gets the deployment details from the credential
*/
async getDeploymentDetails() {
return {
apiVersion: this.credential.apiVersion,
endpoint: this.credential.endpoint,
resourceName: this.credential.resourceName,
};
}
}
@@ -0,0 +1,45 @@
import { NodeOperationError, OperationalError, type ISupplyDataFunctions } from 'n8n-workflow';
import type { AzureOpenAIApiKeyModelConfig } from '../types';
/**
* Handles API Key authentication setup for Azure OpenAI
*/
export async function setupApiKeyAuthentication(
this: ISupplyDataFunctions,
credentialName: string,
): Promise<AzureOpenAIApiKeyModelConfig> {
try {
// Get Azure OpenAI Config (Endpoint, Version, etc.)
const configCredentials = await this.getCredentials<{
apiKey?: string;
resourceName: string;
apiVersion: string;
endpoint?: string;
}>(credentialName);
if (!configCredentials.apiKey) {
throw new NodeOperationError(
this.getNode(),
'API Key is missing in the selected Azure OpenAI API credential. Please configure the API Key or choose Entra ID authentication.',
);
}
this.logger.info('Using API Key authentication for Azure OpenAI.');
return {
azureOpenAIApiKey: configCredentials.apiKey,
azureOpenAIApiInstanceName: configCredentials.resourceName,
azureOpenAIApiVersion: configCredentials.apiVersion,
azureOpenAIEndpoint: configCredentials.endpoint,
};
} catch (error) {
if (error instanceof OperationalError) {
throw error;
}
this.logger.error(`Error setting up API Key authentication: ${error.message}`, error);
throw new NodeOperationError(this.getNode(), 'Failed to retrieve API Key', error);
}
}
@@ -0,0 +1,46 @@
import { getBearerTokenProvider } from '@azure/identity';
import { NodeOperationError, type ISupplyDataFunctions } from 'n8n-workflow';
import { N8nOAuth2TokenCredential } from './N8nOAuth2TokenCredential';
import type {
AzureEntraCognitiveServicesOAuth2ApiCredential,
AzureOpenAIOAuth2ModelConfig,
} from '../types';
const AZURE_OPENAI_SCOPE = 'https://cognitiveservices.azure.com/.default';
/**
* Creates Entra ID (OAuth2) authentication for Azure OpenAI
*/
export async function setupOAuth2Authentication(
this: ISupplyDataFunctions,
credentialName: string,
): Promise<AzureOpenAIOAuth2ModelConfig> {
try {
const credential =
await this.getCredentials<AzureEntraCognitiveServicesOAuth2ApiCredential>(credentialName);
// Create a TokenCredential
const entraTokenCredential = new N8nOAuth2TokenCredential(this.getNode(), credential);
const deploymentDetails = await entraTokenCredential.getDeploymentDetails();
// Use getBearerTokenProvider to create the function LangChain expects
// Pass the required scope for Azure Cognitive Services
const azureADTokenProvider = getBearerTokenProvider(entraTokenCredential, AZURE_OPENAI_SCOPE);
this.logger.debug('Successfully created Azure AD Token Provider.');
return {
azureADTokenProvider,
azureOpenAIApiInstanceName: deploymentDetails.resourceName,
azureOpenAIApiVersion: deploymentDetails.apiVersion,
azureOpenAIEndpoint: deploymentDetails.endpoint,
};
} catch (error) {
this.logger.error(`Error setting up Entra ID authentication: ${error.message}`, error);
throw new NodeOperationError(
this.getNode(),
`Error setting up Entra ID authentication: ${error.message}`,
error,
);
}
}