Skip to content

Commit

Permalink
fix(core): Improve error handling on Credentials decryption
Browse files Browse the repository at this point in the history
  • Loading branch information
netroy committed Jan 27, 2025
1 parent 6dd90c8 commit 5c58065
Show file tree
Hide file tree
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
Expand Up @@ -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';

Expand Down Expand Up @@ -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-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
Expand Up @@ -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
Expand Up @@ -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<
Expand All @@ -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 });
}
}

Expand Down

0 comments on commit 5c58065

Please sign in to comment.