Skip to content
This repository has been archived by the owner on Aug 11, 2024. It is now read-only.

Commit

Permalink
feat(MFA): Cleanups
Browse files Browse the repository at this point in the history
  • Loading branch information
JumpLink committed Nov 10, 2023
1 parent cf7e9a0 commit dd3b81a
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 22 deletions.
8 changes: 7 additions & 1 deletion src/api/controllers/ContactController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,13 @@ export class ContactController {
@Body() data: DeleteContactMfaData,
@Params() { id }: { id: string }
): Promise<void> {
await ContactMfaService.delete(target, id, data);
if (id === "me") {
await ContactMfaService.deleteSecure(target, data);
} else {
// It's secure to call this unsecure method here because the user is an admin,
// this is checked in the `@TargetUser()` decorator
await ContactMfaService.deleteUnsecure(target);
}
}

@OnUndefined(204)
Expand Down
51 changes: 30 additions & 21 deletions src/core/services/ContactMfaService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,38 +63,47 @@ class ContactMfaService {
* Delete contact MFA
*
* ### ATTENTION
* If the id is `'me'` we check if the token is valid, otherwise the user must be an admin, this must be checked before calling this method.
* E.g. with the `@TargetUser()` or `@Authorized()` decorators.
* This method is secure because the token is checked.
*
* @param contact The contact
* @param data The MFA type and the token (if the user is not an admin)
*/
async deleteSecure(contact: Contact, data: DeleteContactMfaData) {
if (!data.token) {
throw new ForbiddenError({
code: LOGIN_CODES.MISSING_TOKEN,
message:
"The contact itself needs to enter the old code to delete its MFA"
});
}
const tokenValidation = await this.checkToken(contact, data.token, 2);
if (!tokenValidation.isValid) {
throw new ForbiddenError({
code: LOGIN_CODES.INVALID_TOKEN,
message: "Invalid token"
});
}

return this.deleteUnsecure(contact);
}

/**
* Delete contact MFA
*
* ### ATTENTION
* In this unsecure method the token is not checked. So calling this method is only allowed for admins.
*
* @param contact The contact
* @param id The request contact ID (we check if the id is 'me' or the contact ID)
* @param data The MFA type and the token (if the user is not an admin)
*/
async delete(contact: Contact, id: string, data: DeleteContactMfaData) {
async deleteUnsecure(contact: Contact) {
const mfa = await this.get(contact);

if (!mfa) {
throw new NotFoundError("Contact has no MFA");
}

// If the id is 'me' we check if the token is valid
if (id === "me") {
if (!data.token) {
throw new ForbiddenError({
code: LOGIN_CODES.MISSING_TOKEN,
message:
"The contact itself needs to enter the old code to delete its MFA"
});
}
const tokenValidation = await this.checkToken(contact, data.token, 2);
if (!tokenValidation.isValid) {
throw new ForbiddenError({
code: LOGIN_CODES.INVALID_TOKEN,
message: "Invalid token"
});
}
}

await getRepository(ContactMfa).delete(mfa.id);
}

Expand Down

0 comments on commit dd3b81a

Please sign in to comment.