Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(core): Improve error handling on Credentials decryption
Browse files Browse the repository at this point in the history
netroy committed Jan 27, 2025

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 0979a99 commit 045b062
Showing 3 changed files with 51 additions and 5 deletions.
35 changes: 35 additions & 0 deletions packages/core/src/__tests__/credentials.test.ts
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ import { Container } from '@n8n/di';
import { mock } from 'jest-mock-extended';
import type { CredentialInformation } from 'n8n-workflow';

import { CREDENTIAL_ERRORS } from '@/constants';
import { Cipher } from '@/encryption/cipher';
import type { InstanceSettings } from '@/instance-settings';

@@ -57,4 +58,38 @@ describe('Credentials', () => {
expect(credentials.getData().key1).toEqual(initialData);
});
});

describe('getData', () => {
const nodeCredentials = { id: '123', name: 'testName' };
const credentialType = 'testApi';

test('should throw an error when data is missing', () => {
const credentials = new Credentials(nodeCredentials, credentialType);
credentials.data = undefined;

expect(() => credentials.getData()).toThrow(CREDENTIAL_ERRORS.NO_DATA);
});

test('should throw an error when decryption fails', () => {
const credentials = new Credentials(nodeCredentials, credentialType);
credentials.data = 'invalid-credentials-data';

expect(() => credentials.getData()).toThrow(CREDENTIAL_ERRORS.DECRYPTION_FAILED);
});

test('should throw an error when JSON parsing fails', () => {
const credentials = new Credentials(nodeCredentials, credentialType);
credentials.data = cipher.encrypt('invalid-json-string');

expect(() => credentials.getData()).toThrow(CREDENTIAL_ERRORS.INVALID_JSON);
});
test('should successfully decrypt and parse valid JSON credentials', () => {
const credentials = new Credentials(nodeCredentials, credentialType);
credentials.setData({ username: 'testuser', password: 'testpass' });

const decryptedData = credentials.getData();
expect(decryptedData.username).toBe('testuser');
expect(decryptedData.password).toBe('testpass');
});
});
});
7 changes: 7 additions & 0 deletions packages/core/src/constants.ts
Original file line number Diff line number Diff line change
@@ -14,3 +14,10 @@ export const CONFIG_FILES = 'N8N_CONFIG_FILES';
export const BINARY_DATA_STORAGE_PATH = 'N8N_BINARY_DATA_STORAGE_PATH';
export const UM_EMAIL_TEMPLATES_INVITE = 'N8N_UM_EMAIL_TEMPLATES_INVITE';
export const UM_EMAIL_TEMPLATES_PWRESET = 'N8N_UM_EMAIL_TEMPLATES_PWRESET';

export const CREDENTIAL_ERRORS = {
NO_DATA: 'No data is set on this credentials.',
DECRYPTION_FAILED:
'Credentials could not be decrypted. The likely reason is that a different "encryptionKey" was used to encrypt the data.',
INVALID_JSON: 'Decrypted credentials data is not valid JSON.',
};
14 changes: 9 additions & 5 deletions packages/core/src/credentials.ts
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ import { Container } from '@n8n/di';
import type { ICredentialDataDecryptedObject, ICredentialsEncrypted } from 'n8n-workflow';
import { ApplicationError, ICredentials, jsonParse } from 'n8n-workflow';

import { CREDENTIAL_ERRORS } from '@/constants';
import { Cipher } from '@/encryption/cipher';

export class Credentials<
@@ -21,17 +22,20 @@ export class Credentials<
*/
getData(): T {
if (this.data === undefined) {
throw new ApplicationError('No data is set so nothing can be returned.');
throw new ApplicationError(CREDENTIAL_ERRORS.NO_DATA);
}

let decryptedData: string;
try {
const decryptedData = this.cipher.decrypt(this.data);
decryptedData = this.cipher.decrypt(this.data);
} catch (e) {
throw new ApplicationError(CREDENTIAL_ERRORS.DECRYPTION_FAILED, { cause: e });
}

try {
return jsonParse(decryptedData);
} catch (e) {
throw new ApplicationError(
'Credentials could not be decrypted. The likely reason is that a different "encryptionKey" was used to encrypt the data.',
);
throw new ApplicationError(CREDENTIAL_ERRORS.INVALID_JSON, { cause: e });
}
}

0 comments on commit 045b062

Please sign in to comment.