Credentials & Authentication
Credentials in n8n handle authentication for external services. They’re defined separately from nodes and can be shared across multiple node types.
ICredentialType Interface
All credentials implement the ICredentialType interface:
import type {
ICredentialType,
INodeProperties,
IAuthenticateGeneric,
ICredentialTestRequest,
} from 'n8n-workflow';
export class MyServiceApi implements ICredentialType {
name = 'myServiceApi';
displayName = 'My Service API';
documentationUrl = 'myservice';
properties: INodeProperties[] = [
// Credential fields
];
authenticate?: IAuthenticateGeneric;
test?: ICredentialTestRequest;
}
Required Properties
| Property | Type | Description |
|---|
name | string | Internal identifier (camelCase) |
displayName | string | Name shown in UI |
documentationUrl | string | Link to documentation |
properties | INodeProperties[] | Credential input fields |
authenticate | object | Authentication configuration |
test | object | Credential test request |
Basic Authentication Examples
API Key
Basic Auth
Bearer Token
Multiple Fields
Simple API key authentication:export class MyServiceApi implements ICredentialType {
name = 'myServiceApi';
displayName = 'My Service API';
documentationUrl = 'myservice';
properties: INodeProperties[] = [
{
displayName: 'API Key',
name: 'apiKey',
type: 'string',
typeOptions: { password: true },
default: '',
required: true,
},
];
authenticate: IAuthenticateGeneric = {
type: 'generic',
properties: {
headers: {
'X-API-Key': '={{$credentials.apiKey}}',
},
},
};
test: ICredentialTestRequest = {
request: {
baseURL: 'https://api.myservice.com',
url: '/v1/auth/test',
},
};
}
Username and password authentication:export class HttpBasicAuth implements ICredentialType {
name = 'httpBasicAuth';
displayName = 'Basic Auth';
documentationUrl = 'httprequest';
genericAuth = true;
properties: INodeProperties[] = [
{
displayName: 'User',
name: 'user',
type: 'string',
default: '',
resolvableField: true,
},
{
displayName: 'Password',
name: 'password',
type: 'string',
typeOptions: { password: true },
default: '',
resolvableField: true,
},
];
}
Bearer token authentication:export class SlackApi implements ICredentialType {
name = 'slackApi';
displayName = 'Slack API';
documentationUrl = 'slack';
properties: INodeProperties[] = [
{
displayName: 'Access Token',
name: 'accessToken',
type: 'string',
typeOptions: { password: true },
default: '',
required: true,
},
];
authenticate: IAuthenticateGeneric = {
type: 'generic',
properties: {
headers: {
Authorization: '=Bearer {{$credentials.accessToken}}',
},
},
};
test: ICredentialTestRequest = {
request: {
baseURL: 'https://slack.com',
url: '/api/users.profile.get',
},
rules: [
{
type: 'responseSuccessBody',
properties: {
key: 'error',
value: 'invalid_auth',
message: 'Invalid access token',
},
},
],
};
}
Multiple credential fields:export class MyComplexApi implements ICredentialType {
name = 'myComplexApi';
displayName = 'My Complex API';
documentationUrl = 'myservice';
properties: INodeProperties[] = [
{
displayName: 'API URL',
name: 'url',
type: 'string',
default: 'https://api.myservice.com',
required: true,
},
{
displayName: 'Client ID',
name: 'clientId',
type: 'string',
default: '',
required: true,
},
{
displayName: 'Client Secret',
name: 'clientSecret',
type: 'string',
typeOptions: { password: true },
default: '',
required: true,
},
{
displayName: 'Environment',
name: 'environment',
type: 'options',
options: [
{
name: 'Production',
value: 'production',
},
{
name: 'Sandbox',
value: 'sandbox',
},
],
default: 'production',
},
];
authenticate: IAuthenticateGeneric = {
type: 'generic',
properties: {
headers: {
'Client-ID': '={{$credentials.clientId}}',
'Client-Secret': '={{$credentials.clientSecret}}',
},
},
};
}
OAuth2 Credentials
OAuth2 credentials require additional configuration:
export class MyServiceOAuth2Api implements ICredentialType {
name = 'myServiceOAuth2Api';
extends = ['oAuth2Api'];
displayName = 'My Service OAuth2 API';
documentationUrl = 'myservice';
properties: INodeProperties[] = [
{
displayName: 'Grant Type',
name: 'grantType',
type: 'hidden',
default: 'authorizationCode',
},
{
displayName: 'Authorization URL',
name: 'authUrl',
type: 'hidden',
default: 'https://auth.myservice.com/oauth/authorize',
},
{
displayName: 'Access Token URL',
name: 'accessTokenUrl',
type: 'hidden',
default: 'https://auth.myservice.com/oauth/token',
},
{
displayName: 'Scope',
name: 'scope',
type: 'string',
default: 'read write',
},
{
displayName: 'Auth URI Query Parameters',
name: 'authQueryParameters',
type: 'hidden',
default: '',
},
{
displayName: 'Authentication',
name: 'authentication',
type: 'hidden',
default: 'body',
},
];
}
Credential Testing
The test property defines how to validate credentials:
test: ICredentialTestRequest = {
request: {
baseURL: 'https://api.myservice.com',
url: '/v1/auth/verify',
method: 'GET',
},
};
Using Credentials in Nodes
Declaring Credentials
In your node’s description:
description: INodeTypeDescription = {
// ... other properties
credentials: [
{
name: 'myServiceApi',
required: true,
},
// Multiple credential options
{
name: 'myServiceOAuth2Api',
required: true,
displayOptions: {
show: {
authentication: ['oAuth2'],
},
},
},
],
};
Accessing Credentials
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const credentials = await this.getCredentials('myServiceApi');
const apiKey = credentials.apiKey as string;
const baseUrl = credentials.baseUrl as string;
// Use credentials in request
const response = await this.helpers.request({
method: 'GET',
url: `${baseUrl}/api/users`,
headers: {
'X-API-Key': apiKey,
},
});
return [this.helpers.returnJsonArray(response)];
}
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
// Automatically applies authentication from credential config
const response = await this.helpers.requestWithAuthentication.call(
this,
'myServiceApi',
{
method: 'GET',
url: 'https://api.myservice.com/users',
},
);
return [this.helpers.returnJsonArray(response)];
}
methods = {
loadOptions: {
async getProjects(this: ILoadOptionsFunctions) {
const credentials = await this.getCredentials('myServiceApi');
const response = await this.helpers.request({
method: 'GET',
url: 'https://api.myservice.com/projects',
headers: {
'X-API-Key': credentials.apiKey as string,
},
});
return response.map(project => ({
name: project.name,
value: project.id,
}));
},
},
};
Conditional Credential Fields
Show/hide credential fields based on other fields:
properties: INodeProperties[] = [
{
displayName: 'Authentication',
name: 'authentication',
type: 'options',
options: [
{
name: 'API Key',
value: 'apiKey',
},
{
name: 'OAuth2',
value: 'oAuth2',
},
],
default: 'apiKey',
},
{
displayName: 'API Key',
name: 'apiKey',
type: 'string',
typeOptions: { password: true },
displayOptions: {
show: {
authentication: ['apiKey'],
},
},
default: '',
},
{
displayName: 'Client ID',
name: 'clientId',
type: 'string',
displayOptions: {
show: {
authentication: ['oAuth2'],
},
},
default: '',
},
];
Real-World Example: AMQP Credentials
Here’s the complete AMQP credential test from the source:
// In Amqp.node.ts
methods = {
credentialTest: {
async amqpConnectionTest(
this: ICredentialTestFunctions,
credential: ICredentialsDecrypted,
): Promise<INodeCredentialTestResult> {
const credentials = credential.data as ICredentialDataDecryptedObject;
const rhea = require('rhea');
try {
const connection = rhea.connect({
hostname: credentials.hostname,
port: credentials.port,
username: credentials.username,
password: credentials.password,
transport: credentials.transportType,
});
// Wait for connection
await new Promise((resolve, reject) => {
connection.on('connection_open', () => {
connection.close();
resolve(true);
});
connection.on('disconnected', (context: any) => {
reject(context.error || new Error('Connection failed'));
});
});
return {
status: 'OK',
message: 'Connection successful!',
};
} catch (error) {
return {
status: 'Error',
message: error.message,
};
}
},
},
};
Security Best Practices
Follow these security guidelines when implementing credentials.
Use Password Type
Always use typeOptions: { password: true } for sensitive fields:{
displayName: 'API Secret',
name: 'apiSecret',
type: 'string',
typeOptions: { password: true },
default: '',
}
Validate Credentials
Always implement a test request or custom test function to validate credentials.
Handle Errors Securely
Don’t expose sensitive information in error messages:catch (error) {
return {
status: 'Error',
message: 'Authentication failed. Please check your credentials.',
// Don't include: error.message (may contain sensitive info)
};
}
Use HTTPS
Always use HTTPS for API endpoints in credential tests and authentication.
Common Patterns
Multi-Region Support
properties: INodeProperties[] = [
{
displayName: 'Region',
name: 'region',
type: 'options',
options: [
{
name: 'US',
value: 'us',
},
{
name: 'EU',
value: 'eu',
},
{
name: 'Asia',
value: 'asia',
},
],
default: 'us',
},
{
displayName: 'API Key',
name: 'apiKey',
type: 'string',
typeOptions: { password: true },
default: '',
},
];
authenticate: IAuthenticateGeneric = {
type: 'generic',
properties: {
headers: {
'X-API-Key': '={{$credentials.apiKey}}',
'X-Region': '={{$credentials.region}}',
},
},
};
Custom Domain Support
properties: INodeProperties[] = [
{
displayName: 'Domain',
name: 'domain',
type: 'string',
default: 'https://api.example.com',
placeholder: 'https://your-domain.example.com',
description: 'The domain of your instance',
},
{
displayName: 'API Token',
name: 'apiToken',
type: 'string',
typeOptions: { password: true },
default: '',
},
];
Next Steps
Testing
Learn how to test nodes and credentials
Node Structure
Understand how to use credentials in nodes