Learn how to add custom credentials in n8n by creating, testing, and implementing API Key or OAuth2 authentication modules to connect services beyond native support.
Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
To add custom credentials in n8n, you need to create a new credentials module with proper structure, define the necessary properties, implement authentication logic, and register it with n8n. This allows you to connect to services that aren't natively supported by n8n's existing credential types or to customize authentication for your specific needs.
Comprehensive Guide to Adding Custom Credentials in n8n
Step 1: Understanding n8n Credentials Structure
Before diving into creating custom credentials, it's important to understand how credentials work in n8n:
Step 2: Setting Up Your Development Environment
To create custom credentials, you'll need a proper development environment:
npm install n8n -g
npm init
npm install n8n-core n8n-workflow typescript --save-dev
Step 3: Creating the Basic Credentials Structure
Let's create a basic structure for our custom credentials:
// YourCustomCredentials.credentials.ts
import {
ICredentialType,
INodeProperties,
} from 'n8n-workflow';
export class YourCustomCredentials implements ICredentialType {
name = 'yourCustomCredentials';
displayName = 'Your Custom Service';
documentationUrl = 'https://your-documentation-url.com';
properties: INodeProperties[] = [
{
displayName: 'API Key',
name: 'apiKey',
type: 'string',
default: '',
required: true,
},
// Add more properties as needed
];
}
Step 4: Defining Credential Properties
Expand your credentials by adding all necessary properties for authentication:
// Expanded properties for a more complex authentication
properties: INodeProperties[] = [
{
displayName: 'Authentication Type',
name: 'authenticationType',
type: 'options',
options: [
{
name: 'API Key',
value: 'apiKey',
},
{
name: 'OAuth2',
value: 'oAuth2',
},
],
default: 'apiKey',
},
{
displayName: 'API Key',
name: 'apiKey',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
authenticationType: [
'apiKey',
],
},
},
},
{
displayName: 'Access Token',
name: 'accessToken',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
authenticationType: [
'oAuth2',
],
},
},
},
{
displayName: 'API URL',
name: 'apiUrl',
type: 'string',
default: 'https://api.example.com',
required: true,
},
];
Step 5: Implementing OAuth2 Authentication (If Needed)
If your service requires OAuth2 authentication, you'll need to implement the OAuth2 flow:
// OAuth2 implementation for your custom credentials
import {
ICredentialType,
INodeProperties,
ICredentialTestRequest,
ICredentialDataDecryptedObject,
IHttpRequestOptions,
GenericValue,
} from 'n8n-workflow';
export class YourOAuth2Credentials implements ICredentialType {
name = 'yourOAuth2Credentials';
displayName = 'Your OAuth2 Service';
documentationUrl = 'https://your-documentation-url.com';
extends = [
'oAuth2Api',
];
properties: INodeProperties[] = [
{
displayName: 'Authorization URL',
name: 'authUrl',
type: 'string',
default: 'https://your-service.com/oauth/authorize',
required: true,
},
{
displayName: 'Access Token URL',
name: 'accessTokenUrl',
type: 'string',
default: 'https://your-service.com/oauth/token',
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: 'Scope',
name: 'scope',
type: 'string',
default: '',
required: false,
},
{
displayName: 'Auth URI Query Parameters',
name: 'authQueryParameters',
type: 'string',
default: '',
displayOptions: {
show: {
authenticationMethod: [
'authorizationCode',
],
},
},
description: 'Query parameters that get added to authorization URL',
},
];
// Implement authentication validation
authenticate: ICredentialTestRequest = {
url: '={{$credentials.apiUrl}}/api/user/me',
headers: {
'Authorization': '=Bearer {{$credentials.accessToken}}',
},
};
}
Step 6: Adding Authentication Testing
It's important to add a way for users to test if their credentials are valid:
// For API Key-based authentication
authenticate: ICredentialTestRequest = {
url: '={{$credentials.apiUrl}}/api/test-endpoint',
headers: {
'X-API-Key': '={{$credentials.apiKey}}',
},
};
// For more complex authentication, you might need to implement a custom test function
async test(this: ICredentialTestFunctions, credential: ICredentialDataDecryptedObject): Promise {
const credentials = credential.data as IDataObject;
const apiKey = credentials.apiKey as string;
const apiUrl = credentials.apiUrl as string;
const options: IHttpRequestOptions = {
method: 'GET',
url: `${apiUrl}/api/test-endpoint`,
headers: {
'X-API-Key': apiKey,
},
};
try {
await this.helpers.request(options);
return {
status: 'OK',
message: 'Authentication successful!',
};
} catch (error) {
return {
status: 'Error',
message: `Authentication failed: ${error.message}`,
};
}
}
Step 7: Registering Your Custom Credentials
To make your custom credentials available in n8n, you need to register them properly. Create an index file that exports your credentials:
// index.ts
import { YourCustomCredentials } from './YourCustomCredentials.credentials';
import { YourOAuth2Credentials } from './YourOAuth2Credentials.credentials';
export const credentialTypes = [
YourCustomCredentials,
YourOAuth2Credentials,
];
Step 8: Compiling Your Credentials Module
Set up TypeScript configuration and compile your module:
// tsconfig.json
{
"compilerOptions": {
"target": "es2019",
"module": "commonjs",
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"declaration": true
},
"include": [
"\*_/_.ts"
],
"exclude": [
"node\_modules",
"dist"
]
}
Then compile with:
npx tsc
Step 9: Creating a Package.json for Your Module
Update your package.json to properly describe your module:
{
"name": "n8n-custom-credentials",
"version": "0.1.0",
"description": "Custom credentials for n8n",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc",
"test": "echo "Error: no test specified" && exit 1"
},
"keywords": [
"n8n",
"n8n-community-node-package",
"credentials"
],
"author": "Your Name",
"license": "MIT",
"n8n": {
"credentials": [
"dist/YourCustomCredentials.credentials.js",
"dist/YourOAuth2Credentials.credentials.js"
]
},
"devDependencies": {
"n8n-core": "^0.125.0",
"n8n-workflow": "^0.107.0",
"typescript": "^4.8.4"
}
}
Step 10: Installing Custom Credentials in n8n
There are several ways to install your custom credentials in n8n:
Method 1: Local Development Installation
# Navigate to your n8n installation directory
cd ~/.n8n
# Create a custom directory if it doesn't exist
mkdir -p custom
# Install your custom credentials
npm install --save path/to/your/custom-credentials
Method 2: Publishing to npm and Installing
# First publish your package
npm publish
# Then install in n8n
cd ~/.n8n
npm install --save your-package-name
Method 3: Using n8n-nodes-base.config.js
Create a configuration file in your n8n installation directory:
// ~/.n8n/n8n-nodes-base.config.js
module.exports = {
// This loads all custom credentials from these directories
customCredentialsDir: [
'path/to/your/custom-credentials/dist',
],
};
Step 11: Implementing Advanced Authentication Features
For more advanced authentication scenarios, you might need to implement additional features:
// Example of implementing token refresh for OAuth2
import {
ICredentialType,
ICredentialTestRequest,
IHttpRequestOptions,
INodeProperties,
ITokenData,
NodePropertyTypes,
} from 'n8n-workflow';
export class AdvancedOAuth2Credentials implements ICredentialType {
name = 'advancedOAuth2Credentials';
displayName = 'Advanced OAuth2 API';
documentationUrl = 'https://your-docs.com';
extends = ['oAuth2Api'];
properties: INodeProperties[] = [
// ... your properties here
];
async getRefreshToken(this: any, refreshToken: string, credentials: ICredentialDataDecryptedObject): Promise {
const options: IHttpRequestOptions = {
method: 'POST',
url: credentials.accessTokenUrl as string,
body: {
client\_id: credentials.clientId,
client\_secret: credentials.clientSecret,
grant_type: 'refresh_token',
refresh\_token: refreshToken,
},
json: true,
};
const response = await this.helpers.request(options);
return {
accessToken: response.access\_token,
refreshToken: response.refresh\_token || refreshToken,
expiresIn: response.expires\_in,
};
}
}
Step 12: Testing Your Custom Credentials
After installing your custom credentials, start n8n and test them:
n8n start
Step 13: Debugging Common Issues
If your custom credentials aren't appearing or aren't working as expected:
You can enable debug logs by starting n8n with:
N8N_LOG_LEVEL=debug n8n start
Step 14: Creating a Complete Example - API Key Authentication
Let's put everything together with a complete example for a custom API Key authentication:
// CustomApiKeyCredentials.credentials.ts
import {
ICredentialType,
INodeProperties,
ICredentialTestRequest,
} from 'n8n-workflow';
export class CustomApiKeyCredentials implements ICredentialType {
name = 'customApiKeyCredentials';
displayName = 'Custom API Service';
documentationUrl = 'https://docs.customapi.com';
properties: INodeProperties[] = [
{
displayName: 'API Key',
name: 'apiKey',
type: 'string',
typeOptions: {
password: true,
},
default: '',
required: true,
description: 'The API key for authentication',
},
{
displayName: 'API URL',
name: 'apiUrl',
type: 'string',
default: 'https://api.customservice.com/v1',
required: true,
description: 'The base URL of the API',
},
{
displayName: 'API Key Header Name',
name: 'apiKeyHeaderName',
type: 'string',
default: 'X-API-Key',
required: true,
description: 'The header name for the API key',
},
];
// Test request to validate credentials
authenticate: ICredentialTestRequest = {
url: '={{$credentials.apiUrl}}/user/me',
headers: {
'={{$credentials.apiKeyHeaderName}}': '={{$credentials.apiKey}}',
},
};
}
Step 15: Creating a Complete Example - OAuth2 Authentication
Here's a complete example for OAuth2 authentication:
// CustomOAuth2Credentials.credentials.ts
import {
ICredentialType,
INodeProperties,
ICredentialTestRequest,
ITokenData,
IHttpRequestOptions,
ICredentialDataDecryptedObject,
} from 'n8n-workflow';
export class CustomOAuth2Credentials implements ICredentialType {
name = 'customOAuth2Credentials';
displayName = 'Custom OAuth2 Service';
documentationUrl = 'https://docs.customservice.com/oauth2';
extends = ['oAuth2Api'];
properties: INodeProperties[] = [
{
displayName: 'Authorization URL',
name: 'authUrl',
type: 'string',
default: 'https://auth.customservice.com/oauth/authorize',
required: true,
},
{
displayName: 'Access Token URL',
name: 'accessTokenUrl',
type: 'string',
default: 'https://auth.customservice.com/oauth/token',
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: 'Scope',
name: 'scope',
type: 'string',
default: 'read write',
required: false,
description: 'Space-separated list of scopes',
},
{
displayName: 'Authentication',
name: 'authentication',
type: 'options',
options: [
{
name: 'Body',
value: 'body',
},
{
name: 'Header',
value: 'header',
},
],
default: 'body',
description: 'Method to use for authentication',
},
{
displayName: 'API URL',
name: 'apiUrl',
type: 'string',
default: 'https://api.customservice.com/v1',
required: true,
},
];
// Authentication test
authenticate: ICredentialTestRequest = {
url: '={{$credentials.apiUrl}}/user/me',
headers: {
'Authorization': '=Bearer {{$credentials.accessToken}}',
},
};
// Token refresh implementation
async getRefreshToken(this: any, refreshToken: string, credentials: ICredentialDataDecryptedObject): Promise {
const authenticationMethod = credentials.authentication as string;
const options: IHttpRequestOptions = {
method: 'POST',
url: credentials.accessTokenUrl as string,
skipSslCertificateValidation: false,
body: {
grant_type: 'refresh_token',
refresh\_token: refreshToken,
},
headers: {},
};
if (authenticationMethod === 'header') {
const base64Credentials = Buffer.from(`${credentials.clientId}:${credentials.clientSecret}`).toString('base64');
options.headers!['Authorization'] = `Basic ${base64Credentials}`;
} else {
// Body authentication
Object.assign(options.body, {
client\_id: credentials.clientId,
client\_secret: credentials.clientSecret,
});
}
const response = await this.helpers.request(options);
return {
accessToken: response.access\_token,
refreshToken: response.refresh\_token || refreshToken,
expiresIn: response.expires\_in,
};
}
}
Step 16: Using Custom Credentials in a Node
To use your custom credentials in a custom node, reference them in your node implementation:
// YourCustomNode.node.ts
import {
IExecuteFunctions,
INodeExecutionData,
INodeType,
INodeTypeDescription,
IDataObject,
IHttpRequestOptions,
} from 'n8n-workflow';
export class YourCustomNode implements INodeType {
description: INodeTypeDescription = {
displayName: 'Your Custom Node',
name: 'yourCustomNode',
icon: 'file:your-icon.svg',
group: ['transform'],
version: 1,
description: 'Performs operations with your custom service',
defaults: {
name: 'Your Custom Node',
},
inputs: ['main'],
outputs: ['main'],
credentials: [
{
name: 'customApiKeyCredentials',
required: true,
},
],
properties: [
// Your node properties
],
};
async execute(this: IExecuteFunctions): Promise {
const items = this.getInputData();
const returnData: IDataObject[] = [];
// Get credentials for this node
const credentials = await this.getCredentials('customApiKeyCredentials');
for (let i = 0; i < items.length; i++) {
// Use credentials in your HTTP request
const options: IHttpRequestOptions = {
method: 'GET',
url: `${credentials.apiUrl}/some-endpoint`,
headers: {
[credentials.apiKeyHeaderName as string]: credentials.apiKey,
},
};
const response = await this.helpers.request(options);
returnData.push(response as IDataObject);
}
return [this.helpers.returnJsonArray(returnData)];
}
}
Step 17: Adding Credentials to an Existing Community Package
If you already have a community node package and want to add credentials to it:
// In your package's index.ts
import { YourCustomNode } from './nodes/YourCustomNode.node';
import { YourCustomCredentials } from './credentials/YourCustomCredentials.credentials';
export {
YourCustomNode,
YourCustomCredentials,
};
Update your package.json:
{
"name": "n8n-nodes-your-package",
"version": "0.1.0",
// ... other fields
"n8n": {
"nodes": [
"dist/nodes/YourCustomNode.node.js"
],
"credentials": [
"dist/credentials/YourCustomCredentials.credentials.js"
]
}
}
Step 18: Security Considerations
When implementing custom credentials, keep these security considerations in mind:
typeOptions: { password: true }
for sensitive fields to mask them in the UI
Step 19: Documenting Your Custom Credentials
Proper documentation helps users understand how to use your custom credentials:
documentationUrl
that points to detailed setup instructions
Step 20: Publishing and Sharing Your Custom Credentials
Once your custom credentials are working properly, you can share them with the community:
npm publish
Conclusion
Creating custom credentials in n8n allows you to extend the platform's connectivity to any service you need. By following this guide, you've learned how to create, test, and implement custom credentials for both simple API Key authentication and more complex OAuth2 flows. This opens up endless possibilities for automation with services that aren't natively supported in n8n.
Remember to keep your custom credentials updated as both n8n and the target services evolve over time. With well-implemented custom credentials, you can significantly enhance the capabilities of your n8n workflows.
When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.