Skip to content

Commit

Permalink
Add secret field transformation for otp
Browse files Browse the repository at this point in the history
  • Loading branch information
Mikescops committed Aug 10, 2023
1 parent f2f7ed6 commit 155d81c
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 6 deletions.
6 changes: 6 additions & 0 deletions src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@ export class CouldNotFindTeamCredentialsError extends Error {
super('Could not find team credentials');
}
}

export class InvalidDashlanePathError extends Error {
constructor() {
super('Invalid Dashlane path');
}
}
14 changes: 13 additions & 1 deletion src/modules/database/vaultSecrets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ export const findVaultSecret = (vaultSecrets: VaultSecrets, parsedPath: ParsedPa
vaultSecrets.notes = vaultSecrets.notes.filter((note) => note.title === parsedPath.title);
}

if (parsedPath.secretId) {
vaultSecrets.credentials = vaultSecrets.credentials.filter(
(credential) => credential.id === parsedPath.secretId
);
vaultSecrets.notes = vaultSecrets.notes.filter((note) => note.id === parsedPath.secretId);
}

if (vaultSecrets.credentials.length === 0 && vaultSecrets.notes.length === 0) {
throw new Error(`No matching secret found for "${parsedPath.secretId ?? parsedPath.title ?? ''}"`);
}
Expand All @@ -72,7 +79,12 @@ export const findVaultSecret = (vaultSecrets: VaultSecrets, parsedPath: ParsedPa
}"`
);
}
return String(secretToRender[parsedPath.field]);

const fieldContent = String(secretToRender[parsedPath.field]);
if (parsedPath.transformation) {
return parsedPath.transformation(fieldContent);
}
return fieldContent;
}

return JSON.stringify(secretToRender);
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,4 +220,5 @@ export interface ParsedPath {
secretId?: string;
title?: string;
field?: string;
transformation?: (field: string) => string;
}
1 change: 1 addition & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ export * from './dialogs';
export * from './gotImplementation';
export * from './secretParser';
export * from './secretPath';
export * from './secretTransformation';
export * from './strings';
export * from './teamDeviceCredentials';
38 changes: 33 additions & 5 deletions src/utils/secretPath.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
import { isUuid } from './strings';
import { transformOtp } from './secretTransformation';
import { ParsedPath } from '../types';
import { InvalidDashlanePathError } from '../errors';

/**
* Function to parse a custom Dashlane path and return the query parameters for the vault lookup
* First we check if the path is a valid Dashlane path, should start with dl://
* Then we check if the path is a valid Dashlane vault id, should be a 32 character UUID string (ie: 11111111-1111-1111-1111-111111111111)
* Otherwise, we assume the path is a valid Dashlane title
* Finally, we check if the next chunk of the path is a valid Dashlane field
* Next, we check if the next chunk of the path is a valid Dashlane field
* Finally, we check if there is a '?key' or '?key=value' query string at the end of the path
* @param path
*/
export const parsePath = (path: string): ParsedPath => {
if (!path.startsWith('dl://')) {
throw new Error('Invalid Dashlane path');
throw new InvalidDashlanePathError();
}

const cleanPath = path.slice(5);
const queryParams = path.split('?');
if (queryParams.length > 2) {
throw new InvalidDashlanePathError();
}

const cleanPath = path.slice(5, path.length - (queryParams.length === 2 ? queryParams[1].length + 1 : 0));

const pathChunks = cleanPath.split('/');

if (pathChunks.length > 2) {
throw new Error('Invalid Dashlane path');
throw new InvalidDashlanePathError();
}

let secretId = undefined;
Expand All @@ -36,5 +44,25 @@ export const parsePath = (path: string): ParsedPath => {
field = pathChunks[1];
}

return { secretId, title, field };
let transformation = undefined;

if (queryParams.length === 2) {
const queryParamChunks = queryParams[1].split('=');
if (queryParamChunks.length > 2) {
throw new InvalidDashlanePathError();
}

const queryParamKey = queryParamChunks[0];
// const queryParamValue = queryParamChunks[1];

switch (queryParamKey) {
case 'otp':
transformation = transformOtp;
break;
default:
throw new InvalidDashlanePathError();
}
}

return { secretId, title, field, transformation };
};
5 changes: 5 additions & 0 deletions src/utils/secretTransformation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { authenticator } from 'otplib';

export const transformOtp = (secret: string) => {
return authenticator.generate(secret);
};

0 comments on commit 155d81c

Please sign in to comment.