Skip to content

Commit

Permalink
Add requireSecretAuth middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
dangtony98 committed Jan 1, 2023
1 parent fc61849 commit 6f054d8
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 17 deletions.
4 changes: 2 additions & 2 deletions backend/src/ee/routes/v1/secret.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import express from 'express';
const router = express.Router();
import {
requireAuth,
requireWorkspaceAuth,
requireSecretAuth,
validateRequest
} from '../../../middleware';
import { body, query, param } from 'express-validator';
Expand All @@ -12,7 +12,7 @@ import { ADMIN, MEMBER, COMPLETED, GRANTED } from '../../../variables';
router.get(
'/:secretId/secret-versions',
requireAuth,
requireWorkspaceAuth({
requireSecretAuth({
acceptedRoles: [ADMIN, MEMBER],
acceptedStatuses: [COMPLETED, GRANTED]
}),
Expand Down
2 changes: 2 additions & 0 deletions backend/src/middleware/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import requireOrganizationAuth from './requireOrganizationAuth';
import requireIntegrationAuth from './requireIntegrationAuth';
import requireIntegrationAuthorizationAuth from './requireIntegrationAuthorizationAuth';
import requireServiceTokenAuth from './requireServiceTokenAuth';
import requireSecretAuth from './requireSecretAuth';
import validateRequest from './validateRequest';

export {
Expand All @@ -17,5 +18,6 @@ export {
requireIntegrationAuth,
requireIntegrationAuthorizationAuth,
requireServiceTokenAuth,
requireSecretAuth,
validateRequest
};
2 changes: 1 addition & 1 deletion backend/src/middleware/requireBotAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const requireBotAuth = ({
location?: req;
}) => {
return async (req: Request, res: Response, next: NextFunction) => {
const bot = await Bot.findOne({ _id: req[location].botId });
const bot = await Bot.findById(req[location].botId);

if (!bot) {
return next(AccountNotFoundError({message: 'Failed to locate Bot account'}))
Expand Down
50 changes: 50 additions & 0 deletions backend/src/middleware/requireSecretAuth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Request, Response, NextFunction } from 'express';
import { UnauthorizedRequestError, SecretNotFoundError } from '../utils/errors';
import { Secret } from '../models';
import {
validateMembership
} from '../helpers/membership';

/**
* Validate if user on request has proper membership to modify secret.
* @param {Object} obj
* @param {String[]} obj.acceptedRoles - accepted workspace roles
* @param {String[]} obj.acceptedStatuses - accepted workspace statuses
* @param {String[]} obj.location - location of [workspaceId] on request (e.g. params, body) for parsing
*/
const requireSecretAuth = ({
acceptedRoles,
acceptedStatuses
}: {
acceptedRoles: string[];
acceptedStatuses: string[];
}) => {
return async (req: Request, res: Response, next: NextFunction) => {
try {
const { secretId } = req.params;

const secret = await Secret.findById(secretId);

if (!secret) {
return next(SecretNotFoundError({
message: 'Failed to find secret'
}));
}

await validateMembership({
userId: req.user._id.toString(),
workspaceId: secret.workspace.toString(),
acceptedRoles,
acceptedStatuses
});

req.secret = secret as any;

next();
} catch (err) {
return next(UnauthorizedRequestError({ message: 'Unable to authenticate secret' }));
}
}
}

export default requireSecretAuth;
4 changes: 2 additions & 2 deletions backend/src/types/express/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import * as express from 'express';


// TODO: fix (any) types
declare global {
namespace Express {
interface Request {
user: any;
workspace: any;
membership: any;
organizationt: any;
organization: any;
membershipOrg: any;
integration: any;
integrationAuth: any;
bot: any;
secret: any;
serviceToken: any;
accessToken: any;
query?: any;
Expand Down
34 changes: 22 additions & 12 deletions backend/src/utils/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const RouteNotFoundError = (error?: Partial<RequestErrorContext>) => new
message: error?.message ?? 'The requested source was not found',
context: error?.context,
stack: error?.stack
})
});

export const MethodNotAllowedError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.INFO,
Expand All @@ -17,7 +17,7 @@ export const MethodNotAllowedError = (error?: Partial<RequestErrorContext>) => n
message: error?.message ?? 'The requested method is not allowed for the resource',
context: error?.context,
stack: error?.stack
})
});

export const UnauthorizedRequestError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.INFO,
Expand All @@ -26,7 +26,7 @@ export const UnauthorizedRequestError = (error?: Partial<RequestErrorContext>) =
message: error?.message ?? 'You are not authorized to access this resource',
context: error?.context,
stack: error?.stack
})
});

export const ForbiddenRequestError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.INFO,
Expand All @@ -35,7 +35,7 @@ export const ForbiddenRequestError = (error?: Partial<RequestErrorContext>) => n
message: error?.message ?? 'You are not allowed to access this resource',
context: error?.context,
stack: error?.stack
})
});

export const BadRequestError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.INFO,
Expand All @@ -44,7 +44,7 @@ export const BadRequestError = (error?: Partial<RequestErrorContext>) => new Req
message: error?.message ?? 'The request is invalid or cannot be served',
context: error?.context,
stack: error?.stack
})
});

export const InternalServerError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
Expand All @@ -53,7 +53,7 @@ export const InternalServerError = (error?: Partial<RequestErrorContext>) => new
message: error?.message ?? 'The server encountered an error while processing the request',
context: error?.context,
stack: error?.stack
})
});

export const ServiceUnavailableError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
Expand All @@ -62,7 +62,7 @@ export const ServiceUnavailableError = (error?: Partial<RequestErrorContext>) =>
message: error?.message ?? 'The service is currently unavailable. Please try again later.',
context: error?.context,
stack: error?.stack
})
});

export const ValidationError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
Expand All @@ -71,7 +71,7 @@ export const ValidationError = (error?: Partial<RequestErrorContext>) => new Req
message: error?.message ?? 'The request failed validation',
context: error?.context,
stack: error?.stack
})
});

//* ----->[INTEGRATION ERRORS]<-----
export const IntegrationNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
Expand All @@ -81,7 +81,7 @@ export const IntegrationNotFoundError = (error?: Partial<RequestErrorContext>) =
message: error?.message ?? 'The requested integration was not found',
context: error?.context,
stack: error?.stack
})
});

//* ----->[WORKSPACE ERRORS]<-----
export const WorkspaceNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
Expand All @@ -91,7 +91,7 @@ export const WorkspaceNotFoundError = (error?: Partial<RequestErrorContext>) =>
message: error?.message ?? 'The requested workspace was not found',
context: error?.context,
stack: error?.stack
})
});

//* ----->[ORGANIZATION ERRORS]<-----
export const OrganizationNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
Expand All @@ -101,7 +101,7 @@ export const OrganizationNotFoundError = (error?: Partial<RequestErrorContext>)
message: error?.message ?? 'The requested organization was not found',
context: error?.context,
stack: error?.stack
})
});

//* ----->[ACCOUNT ERRORS]<-----
export const AccountNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
Expand All @@ -111,6 +111,16 @@ export const AccountNotFoundError = (error?: Partial<RequestErrorContext>) => ne
message: error?.message ?? 'The requested account was not found',
context: error?.context,
stack: error?.stack
})
});

//* ----->[SECRET ERRORS]<-----
export const SecretNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
statusCode: error?.statusCode ?? 404,
type: error?.type ?? 'secret_not_found_error',
message: error?.message ?? 'The requested secret was not found',
context: error?.context,
stack: error?.stack
});

//* ----->[MISC ERRORS]<-----
1 change: 1 addition & 0 deletions frontend/components/utilities/attemptLogin.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const attemptLogin = async (
// if everything works, go the main dashboard page.
const { token, publicKey, encryptedPrivateKey, iv, tag } =
await login2(email, clientProof);

SecurityClient.setToken(token);

const privateKey = Aes256Gcm.decrypt({
Expand Down

0 comments on commit 6f054d8

Please sign in to comment.