/n8n-tutorials

How to add custom credentials in n8n?

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.

Matt Graham, CEO of Rapid Developers

Book a call with an Expert

Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.

Book a free consultation

How to add custom credentials in n8n?

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:

  • Credentials in n8n are modular components that handle authentication with external services
  • Each credential type has properties (fields) that users fill out (like API keys, usernames, etc.)
  • Credentials are stored securely and can be reused across multiple workflows
  • Custom credentials must follow n8n's structure to integrate properly with the platform

 

Step 2: Setting Up Your Development Environment

 

To create custom credentials, you'll need a proper development environment:

  • Install n8n locally for development: npm install n8n -g
  • Create a new directory for your custom credentials module
  • Initialize a new npm package: npm init
  • Install necessary development dependencies: 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:

  • Start n8n with n8n start
  • Navigate to Settings > Credentials
  • Click on "Add Credential"
  • Your custom credential type should appear in the list
  • Fill in the required fields and test the connection

 

Step 13: Debugging Common Issues

 

If your custom credentials aren't appearing or aren't working as expected:

  • Check the n8n logs for any errors
  • Verify that your package.json has the correct "n8n.credentials" paths
  • Make sure you've restarted n8n after installing your custom credentials
  • Verify that your credentials structure follows n8n's requirements
  • Check for any TypeScript compilation errors

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:

  • Add your credentials files to your package
  • Update your package.json to include the credentials
  • Export the credentials in your package's index.ts file

// 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:

  • Use typeOptions: { password: true } for sensitive fields to mask them in the UI
  • Never store credentials in plain text or hardcode them
  • For OAuth2, implement proper token refresh handling
  • Use HTTPS for all API endpoints
  • Implement proper error handling to avoid exposing sensitive information in error messages

 

Step 19: Documenting Your Custom Credentials

 

Proper documentation helps users understand how to use your custom credentials:

  • Add a clear and descriptive documentationUrl that points to detailed setup instructions
  • Add helpful descriptions to each credential property
  • Include examples of how to obtain the required credentials from the service
  • Document any specific configuration requirements or limitations

 

Step 20: Publishing and Sharing Your Custom Credentials

 

Once your custom credentials are working properly, you can share them with the community:

  • Publish your package to npm: npm publish
  • Share your package on the n8n community forum
  • Consider contributing to the n8n main repository if your credentials would be valuable to many users
  • Maintain your package with updates as n8n evolves

 

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.

Want to explore opportunities to work with us?

Connect with our team to unlock the full potential of no-code solutions with a no-commitment consultation!

Book a Free Consultation

Client trust and success are our top priorities

When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.

Rapid Dev was an exceptional project management organization and the best development collaborators I've had the pleasure of working with. They do complex work on extremely fast timelines and effectively manage the testing and pre-launch process to deliver the best possible product. I'm extremely impressed with their execution ability.

CPO, Praction - Arkady Sokolov

May 2, 2023

Working with Matt was comparable to having another co-founder on the team, but without the commitment or cost. He has a strategic mindset and willing to change the scope of the project in real time based on the needs of the client. A true strategic thought partner!

Co-Founder, Arc - Donald Muir

Dec 27, 2022

Rapid Dev are 10/10, excellent communicators - the best I've ever encountered in the tech dev space. They always go the extra mile, they genuinely care, they respond quickly, they're flexible, adaptable and their enthusiasm is amazing.

Co-CEO, Grantify - Mat Westergreen-Thorne

Oct 15, 2022

Rapid Dev is an excellent developer for no-code and low-code solutions.
We’ve had great success since launching the platform in November 2023. In a few months, we’ve gained over 1,000 new active users. We’ve also secured several dozen bookings on the platform and seen about 70% new user month-over-month growth since the launch.

Co-Founder, Church Real Estate Marketplace - Emmanuel Brown

May 1, 2024 

Matt’s dedication to executing our vision and his commitment to the project deadline were impressive. 
This was such a specific project, and Matt really delivered. We worked with a really fast turnaround, and he always delivered. The site was a perfect prop for us!

Production Manager, Media Production Company - Samantha Fekete

Sep 23, 2022