File

src/auth/auth.service.ts

Index

Properties
Methods

Constructor

constructor()

Methods

Async associateAuthToken
associateAuthToken(undefined: IAssociateAuthToken)
Parameters :
Name Type Optional
IAssociateAuthToken No
Returns : unknown
Async authenticateUserAndChangeTempPswd
authenticateUserAndChangeTempPswd(authChangePasswordUserDto: AuthChangePasswordUserDto)

Admin receive email from cognito with temp password to join. The new admin need to login with a new password to change the temp password.

Parameters :
Name Type Optional
authChangePasswordUserDto AuthChangePasswordUserDto No
Returns : unknown
Async authenticateUserWithMfa
authenticateUserWithMfa(authLoginUserDto: AuthLoginUserDto)
Parameters :
Name Type Optional
authLoginUserDto AuthLoginUserDto No
Async changeUserPassword
changeUserPassword(authChangePasswordUserDto: AuthChangePasswordUserDto)
Parameters :
Name Type Optional
authChangePasswordUserDto AuthChangePasswordUserDto No
Returns : any
Async confirmUserPassword
confirmUserPassword(authConfirmPasswordUserDto: AuthConfirmPasswordUserDto)
Parameters :
Name Type Optional
authConfirmPasswordUserDto AuthConfirmPasswordUserDto No
Returns : Promise<literal type>
Async createPlatformAdmin
createPlatformAdmin(authChangePasswordUserDto: Omit)
Parameters :
Name Type Optional
authChangePasswordUserDto Omit<AuthChangePasswordUserDto | "mfaCode" | "session"> No
Returns : unknown
Async deleteCognitoUser
deleteCognitoUser(email: string)
Parameters :
Name Type Optional
email string No
Returns : Promise<void>
Async disableEnableUser
disableEnableUser(undefined: AllowDisallowDto)
Parameters :
Name Type Optional
AllowDisallowDto No
Returns : unknown
Async enableMFA
enableMFA(email: string)
Parameters :
Name Type Optional
email string No
Returns : unknown
Async forgotUserPassword
forgotUserPassword(authForgotPasswordUserDto: AuthForgotPasswordUserDto)
Parameters :
Name Type Optional
authForgotPasswordUserDto AuthForgotPasswordUserDto No
Returns : Promise<string>
Async getCognitoUser
getCognitoUser(email: string)
Parameters :
Name Type Optional
email string No
Async registerCognitoUser
registerCognitoUser(authRegisterUserDto: AuthRegisterUserDto)
Parameters :
Name Type Optional
authRegisterUserDto AuthRegisterUserDto No
Async registerUser
registerUser(authRegisterUserDto: AuthRegisterUserDto, onBoardedUser: UserJwtPayload)
Parameters :
Name Type Optional
authRegisterUserDto AuthRegisterUserDto No
onBoardedUser UserJwtPayload No
Returns : unknown
Async setUpPlatformAdminWeb3Roles
setUpPlatformAdminWeb3Roles(address: string)
Parameters :
Name Type Optional
address string No
Returns : Promise<ContractTransactionResponse[]>
Async signIn
signIn(email: string, password: string)
Parameters :
Name Type Optional
email string No
password string No
Returns : unknown
Async totpChallenge
totpChallenge(undefined: ITotpChallenge)
Parameters :
Name Type Optional
ITotpChallenge No
Returns : unknown
Async validateAndGetSubscribedFunds
validateAndGetSubscribedFunds(authRegisterUserDto: AuthRegisterUserDto, onBoardedUser: UserJwtPayload)
Parameters :
Name Type Optional
authRegisterUserDto AuthRegisterUserDto No
onBoardedUser UserJwtPayload No
Returns : Promise<Fund[]>
Async validateMFA
validateMFA(UserCode: string, AccessTokenOrSession: string)
Parameters :
Name Type Optional
UserCode string No
AccessTokenOrSession string No
Returns : unknown

Properties

Private Readonly adminService
Type : AdminService
Decorators :
@Inject(AdminService)
Private Readonly authWeb3
Type : AuthWeb3Service
Decorators :
@Inject(AuthWeb3Service)
Private cognitoIdentityServiceProvider
Type : CognitoIdentityServiceProvider
Private Readonly emailService
Type : EmailService
Decorators :
@Inject(EmailService)
Private Readonly fundService
Type : FundService
Decorators :
@Inject(FundService)
Private Readonly internalInternalCustodialService
Type : InternalCustodialService
Decorators :
@Inject(InternalCustodialService)
Private Readonly revertOperationService
Type : RevertOperationService
Decorators :
@Inject(RevertOperationService)
Private Readonly userCmsService
Type : UserCmsService
Decorators :
@Inject(UserCmsService)
Private userPool
Type : CognitoUserPool
Private Readonly userService
Type : UserService
Decorators :
@Inject(UserService)
Private Readonly walletService
Type : WalletService
Decorators :
@Inject(WalletService)
import {
  BadRequestException,
  Inject,
  Injectable,
  ServiceUnavailableException,
  UnauthorizedException,
} from "@nestjs/common";

import {
  AuthenticationDetails,
  CognitoUser,
  CognitoUserAttribute,
  CognitoUserPool,
} from "amazon-cognito-identity-js";
import QR from "qrcode";

import type {
  CognitoUserSession,
  ICognitoUserData,
} from "amazon-cognito-identity-js";
import type { IAssociateAuthToken } from "./interfaces/auth.interface";

import type { AuthChangePasswordUserDto } from "./dtos/auth-change-password-user.dto";
import type { AuthLoginUserDto } from "./dtos/auth-login-user.dto";
import type { AuthRegisterUserDto } from "./dtos/auth-register-user.dto";

import type { AuthConfirmPasswordUserDto } from "./dtos/auth-confirm-password-user.dto";
import type { AuthForgotPasswordUserDto } from "./dtos/auth-forgot-password-user.dto";
import {
  ContractName,
  EndUserRoles,
  TransactionNames,
  UserJwtPayload,
} from "src/common/interfaces";
import { UserService } from "src/user/user.service";
import { FundService } from "src/security/fund.service";
import { WalletService } from "src/wallet/wallet.service";
import { AdminService } from "src/admin/admin.service";
import { ICognitoUserSession, ITotpChallenge } from "./interfaces";
import { EmailService } from "src/common/provider/mail/email.service";
import { InternalCustodialService } from "src/shared/custodial/internalCustodial.service";
import { AuthWeb3Service } from "./auth.web3.service";
import { UserCmsService } from "src/user/user.cms.service";
import { Fund } from "src/security/schemas/fund.schema";
import { RevertOperationService } from "src/revertOperation/revertOperation.service";
import { ContractTransactionResponse, parseEther } from "ethers";
import { transactionSubmitter } from "src/common/provider";
import { PaymentToken, Roles } from "src/common/constants";
import { CognitoIdentityServiceProvider } from "aws-sdk";
import { RoleRegistry } from "src/shared/artifacts/RoleRegistry";
import { AllowDisallowDto } from "./dtos/auth-status-user.dto";

@Injectable()
export class AuthService {
  @Inject(UserService)
  private readonly userService: UserService;

  @Inject(AdminService)
  private readonly adminService: AdminService;

  @Inject(FundService)
  private readonly fundService: FundService;

  @Inject(WalletService)
  private readonly walletService: WalletService;

  @Inject(EmailService)
  private readonly emailService: EmailService;

  @Inject(InternalCustodialService)
  private readonly internalInternalCustodialService: InternalCustodialService;

  @Inject(AuthWeb3Service)
  private readonly authWeb3: AuthWeb3Service;

  @Inject(UserCmsService)
  private readonly userCmsService: UserCmsService;

  @Inject(RevertOperationService)
  private readonly revertOperationService: RevertOperationService;

  private userPool: CognitoUserPool;
  private cognitoIdentityServiceProvider: CognitoIdentityServiceProvider;

  constructor() {
    this.userPool = new CognitoUserPool({
      UserPoolId: process.env.AWS_COGNITO_USER_POOL_ID,
      ClientId: process.env.AWS_COGNITO_CLIENT_ID,
    });
    this.cognitoIdentityServiceProvider = new CognitoIdentityServiceProvider({
      region: process.env.AWS_COGNITO_REGION,
      endpoint: process.env.AWS_COGNITO_AUTHORITY,
    });
  }
  async registerUser(
    authRegisterUserDto: AuthRegisterUserDto,
    onBoardedUser: UserJwtPayload,
  ) {
    const operationId = RevertOperationService.getOperationId();
    const subscribedFunds = await this.validateAndGetSubscribedFunds(
      authRegisterUserDto,
      onBoardedUser,
    );
    try {
      const [defaultWallet, , dealer] = await Promise.all([
        this.walletService.create({
          walletLabel: "default wallet",
        }),
        this.registerCognitoUser(authRegisterUserDto),
        onBoardedUser.role === EndUserRoles.dealer &&
          this.userService.findUserByProperty({ email: onBoardedUser.email }),
      ]);
      this.revertOperationService.pushRevertOperation(operationId, [
        {
          revertFunction: this.deleteCognitoUser,
          args: [authRegisterUserDto.email],
          rFunctionId: RevertOperationService.getRevertFunctionId(),
        },
      ]);

      const newUser = await this.userService.create({
        ...authRegisterUserDto,
        onboardByEmail: onBoardedUser.email,
        wallets: [defaultWallet],
        subscribedFunds,
        bankDetails: {
          bankName: authRegisterUserDto.bankName,
          bankAddress: authRegisterUserDto.bankAddress,
          bankChaps: authRegisterUserDto.bankChaps,
          bankBic: authRegisterUserDto.bankBic,
          accountBic: authRegisterUserDto.accountBic,
          accountName: authRegisterUserDto.accountName,
          accountNo: authRegisterUserDto.accountNo,
          ibanNo: authRegisterUserDto.ibanNo,
          ultimateName: authRegisterUserDto.ultimateName,
          ultimateAccountNo: authRegisterUserDto.ultimateAccountNo,
          currency: authRegisterUserDto.currency,
          abaCode: authRegisterUserDto.abaCode,
        },
      });

      this.revertOperationService.pushRevertOperation(operationId, [
        {
          revertFunction: this.userService.deleteByEmail,
          args: [authRegisterUserDto.email],
          rFunctionId: RevertOperationService.getRevertFunctionId(),
        },
      ]);

      let txs: ContractTransactionResponse[] = [];
      if (
        authRegisterUserDto.endUserRole === EndUserRoles.dealer ||
        authRegisterUserDto.endUserRole === EndUserRoles.investor
      ) {
        txs = await this.authWeb3.onboardUser({
          onBoardedByRole: onBoardedUser.role as "admin" | EndUserRoles.dealer,
          userJwtPayload: onBoardedUser,
          newUserRole: authRegisterUserDto.endUserRole,
          newUser,
          internalCustodialService: this.internalInternalCustodialService,
          onChainFields: authRegisterUserDto.onChainFields,
          dealerAddressSubmitter: dealer ? dealer.wallets[0].address : null,
          dealerId: dealer
            ? dealer._id.toString()
            : authRegisterUserDto.dealerId,
        });
        if (authRegisterUserDto.endUserRole === EndUserRoles.dealer) {
          await this.userCmsService.addUserInCms(newUser.email);
          this.revertOperationService.pushRevertOperation(operationId, [
            {
              revertFunction: this.userCmsService.removeUserFromCms,
              args: [newUser.email],
              rFunctionId: RevertOperationService.getRevertFunctionId(),
            },
          ]);
        }
      }
      if (authRegisterUserDto.endUserRole === EndUserRoles.fundAdmin) {
        const tx = await transactionSubmitter({
          signerKey: process.env.RELAYER_KEY,
          contractAddress: RoleRegistry.address,
          transactionName: TransactionNames.grantRole,
          contractName: ContractName.RoleRegistry,
          args: [Roles.FundAdmin, newUser.wallets[0].address],
        });
        await tx.wait();
        txs.push(tx);

        txs.push(
          await transactionSubmitter({
            signerKey: process.env.RELAYER_KEY,
            contractAddress: PaymentToken,
            contractName: ContractName.erc20,
            transactionName: TransactionNames.mint,
            args: [newUser.wallets[0].address, parseEther("1000000")],
          }),
        );
      }

      return { newUser, txs };
    } catch (error) {
      console.error(error);
      await this.revertOperationService.runRevertOperation(operationId);
      throw new ServiceUnavailableException(error);
    }
  }
  async validateAndGetSubscribedFunds(
    authRegisterUserDto: AuthRegisterUserDto,
    onBoardedUser: UserJwtPayload,
  ): Promise<Fund[]> {
    if (
      onBoardedUser.role === EndUserRoles.dealer &&
      authRegisterUserDto.endUserRole !== EndUserRoles.investor
    ) {
      throw new UnauthorizedException(
        `Only admin is allowed to create ${authRegisterUserDto.endUserRole}`,
      );
    }
    const subscribedFunds = await this.fundService.findByIds({
      ids: authRegisterUserDto.subscribedFunds,
    });

    if (
      subscribedFunds.length === 0 &&
      authRegisterUserDto.subscribedFunds.length > 0
    ) {
      throw new BadRequestException("Wrong fund Id");
    }
    return subscribedFunds;
  }

  async registerCognitoUser(
    authRegisterUserDto: AuthRegisterUserDto,
  ): Promise<CognitoUser> {
    const { endUserRole, email, password } = authRegisterUserDto;

    return new Promise((resolve, reject) => {
      this.userPool.signUp(
        email,
        password,
        [
          new CognitoUserAttribute({
            Name: "custom:role",
            Value: endUserRole,
          }),
        ],
        null,
        (err, result) => {
          if (!result) {
            reject(err);
          } else {
            resolve(result.user);
          }
        },
      );
    });
  }

  async authenticateUserWithMfa(authLoginUserDto: AuthLoginUserDto): Promise<
    | ICognitoUserSession // If didn't setup the mfa
    | (CognitoIdentityServiceProvider.AuthenticationResultType & {
        payload: {
          email: string;
          role: string;
        };
      }) // if setup the mfa
  > {
    const { email, password, session, mfaCode } = authLoginUserDto;

    const userData = {
      Username: email,
      Pool: this.userPool,
    };

    const authenticationDetails = new AuthenticationDetails({
      Username: email,
      Password: password,
    });

    const cognitoIdentityServiceProvider = this.cognitoIdentityServiceProvider;

    const userCognito = new CognitoUser(userData);
    return new Promise((resolve, reject) => {
      userCognito.authenticateUser(authenticationDetails, {
        onSuccess: (result) => {
          resolve({
            accessToken: result.getIdToken().getJwtToken(),
            refreshToken: result.getRefreshToken().getToken(),
            payload: {
              email: result.getIdToken().payload.email,
              role: result.getIdToken().payload["custom:role"],
            },
          });
        },
        onFailure: (err) => {
          reject(err);
        },
        mfaSetup: () => {
          throw new UnauthorizedException("Please setup your authenticator");
        },
        totpRequired: async (challengeName) => {
          if (challengeName !== "SOFTWARE_TOKEN_MFA") {
            reject("Soft token is the only supported Challenge");
          }

          try {
            const [authInfo, userInfo] = await Promise.all([
              this.totpChallenge({
                email,
                mfaCode,
                session,
                cognitoIdentityServiceProvider,
              }),
              cognitoIdentityServiceProvider
                .adminGetUser({
                  Username: email,
                  UserPoolId: this.userPool.getUserPoolId(),
                })
                .promise(),
            ]);
            const payload: Record<string, string> = {};
            userInfo.UserAttributes.forEach((attribute) => {
              if (attribute.Name === "custom:role")
                payload.role = attribute.Value;
              else payload[attribute.Name] = attribute.Value;
            });
            resolve({
              ...authInfo.AuthenticationResult,
              payload: { email: payload.email, role: payload.role },
            });
          } catch (totpChallengeError) {
            reject(totpChallengeError);
          }
        },
      });
    });
  }

  /**
     Admin receive email from cognito with temp password to join. 
     The new admin need to login with a new password to change the temp password.
  */
  async authenticateUserAndChangeTempPswd(
    authChangePasswordUserDto: AuthChangePasswordUserDto,
  ) {
    const { email, currentPassword, newPassword, mfaCode, session } =
      authChangePasswordUserDto;
    const userData = {
      Username: email,
      Pool: this.userPool,
    };

    const authenticationDetails = new AuthenticationDetails({
      Username: email,
      Password: currentPassword,
    });

    const userCognito = new CognitoUser(userData);

    const cognitoIdentityServiceProvider = this.cognitoIdentityServiceProvider;

    return new Promise((resolve, reject) => {
      userCognito.authenticateUser(authenticationDetails, {
        onSuccess: (result) => {
          resolve({
            accessToken: result.getIdToken().getJwtToken(),
            refreshToken: result.getRefreshToken().getToken(),
            payload: {
              email: result.getIdToken().payload.email,
              role: result.getIdToken().payload["custom:role"],
            },
          });
        },
        onFailure: (err) => {
          reject(err);
        },
        newPasswordRequired: function () {
          userCognito.completeNewPasswordChallenge(newPassword, null, this);
        },
        mfaSetup: () => {
          resolve(true);
        },
        totpRequired: async (challengeName) => {
          if (challengeName !== "SOFTWARE_TOKEN_MFA") {
            reject("Soft token is the only supported Challenge");
          }

          try {
            const authInfo = await this.totpChallenge({
              email,
              mfaCode,
              session,
              cognitoIdentityServiceProvider,
            });

            await cognitoIdentityServiceProvider
              .changePassword({
                PreviousPassword: currentPassword,
                ProposedPassword: newPassword,
                AccessToken: authInfo.AuthenticationResult.AccessToken,
              })
              .promise();

            resolve(authInfo.AuthenticationResult);
          } catch (totpChallengeError) {
            reject(totpChallengeError);
          }
        },
      });
    });
  }

  async createPlatformAdmin(
    authChangePasswordUserDto: Omit<
      AuthChangePasswordUserDto,
      "mfaCode" | "session"
    >,
  ) {
    const { email, currentPassword, newPassword } = authChangePasswordUserDto;
    const userData = {
      Username: email,
      Pool: this.userPool,
    };

    const authenticationDetails = new AuthenticationDetails({
      Username: email,
      Password: currentPassword,
    });

    const userCognito = new CognitoUser(userData);
    const cognitoIdentityServiceProvider = this.cognitoIdentityServiceProvider;
    const adminService = this.adminService;
    const setUpPlatformAdminWeb3Roles = this.setUpPlatformAdminWeb3Roles;
    const user = await cognitoIdentityServiceProvider
      .adminGetUser({
        Username: email,
        UserPoolId: this.userPool.getUserPoolId(),
      })
      .promise();
    const roleAttribute = user.UserAttributes.find(
      (attribute) => attribute.Name === "custom:role",
    );
    if (!roleAttribute || roleAttribute.Value !== "admin") {
      throw new UnauthorizedException("Only admins are allowed for this call");
    }
    return new Promise((resolve, reject) => {
      userCognito.authenticateUser(authenticationDetails, {
        newPasswordRequired: async function () {
          const admin = await adminService.create(email);
          userCognito.completeNewPasswordChallenge(newPassword, null, this);
          resolve(setUpPlatformAdminWeb3Roles(admin.wallets[0].address));
        },
        mfaSetup: () => {
          reject("This call used on `newPasswordRequired` challenge only.");
        },
        totpRequired: () => {
          reject("This call used on `newPasswordRequired` challenge only.");
        },
        onFailure: (err) => {
          console.log("hnaa");
          reject(err);
        },
        onSuccess: () => {
          reject("This call used on `newPasswordRequired` challenge only");
        },
      });
    });
  }
  async setUpPlatformAdminWeb3Roles(
    address: string,
  ): Promise<ContractTransactionResponse[]> {
    const txs: ContractTransactionResponse[] = [];

    txs.push(
      await transactionSubmitter({
        signerKey: process.env.RELAYER_KEY,
        contractAddress: RoleRegistry.address,
        transactionName: TransactionNames.grantRole,
        contractName: ContractName.RoleRegistry,
        args: [Roles.Admin, address],
      }),
    );
    await txs[0].wait();

    txs.push(
      await transactionSubmitter({
        signerKey: process.env.RELAYER_KEY,
        contractAddress: RoleRegistry.address,
        transactionName: TransactionNames.grantRole,
        contractName: ContractName.RoleRegistry,
        args: [Roles.FundAdmin, address],
      }),
    );
    await txs[1].wait();

    txs.push(
      await transactionSubmitter({
        signerKey: process.env.RELAYER_KEY,
        contractAddress: PaymentToken,
        contractName: ContractName.erc20,
        transactionName: TransactionNames.mint,
        args: [address, parseEther("1000000000")],
      }),
    );
    return txs;
  }
  async changeUserPassword(
    authChangePasswordUserDto: AuthChangePasswordUserDto,
  ) {
    const { email, currentPassword, newPassword, mfaCode, session } =
      authChangePasswordUserDto;

    const userData = {
      Username: email,
      Pool: this.userPool,
    };

    const authenticationDetails = new AuthenticationDetails({
      Username: email,
      Password: currentPassword,
    });

    const userCognito = new CognitoUser(userData);
    const cognitoIdentityServiceProvider = this.cognitoIdentityServiceProvider;

    try {
      await new Promise((resolve, reject) => {
        userCognito.authenticateUser(authenticationDetails, {
          onSuccess: function (session) {
            try {
              userCognito.changePassword(
                currentPassword,
                newPassword,
                (err) => {
                  if (err) {
                    reject(err);
                  }
                },
              );
              resolve(session);
            } catch (passwordChangeError) {
              reject(passwordChangeError);
            }
          },
          onFailure: function (authenticationError) {
            reject(authenticationError);
          },
          totpRequired: async (challengeName) => {
            if (challengeName !== "SOFTWARE_TOKEN_MFA") {
              reject("Soft token is the only supported Challenge");
            }

            try {
              const authInfo = await this.totpChallenge({
                email,
                mfaCode,
                session,
                cognitoIdentityServiceProvider,
              });

              await cognitoIdentityServiceProvider
                .changePassword({
                  PreviousPassword: currentPassword,
                  ProposedPassword: newPassword,
                  AccessToken: authInfo.AuthenticationResult.AccessToken,
                })
                .promise();

              resolve(authInfo.AuthenticationResult);
            } catch (totpChallengeError) {
              reject(totpChallengeError);
            }
          },
        });
      });
    } catch (error) {
      console.error("An error occurred:", error);
      throw new ServiceUnavailableException(error);
    }
  }

  async forgotUserPassword(
    authForgotPasswordUserDto: AuthForgotPasswordUserDto,
  ): Promise<string> {
    const { email } = authForgotPasswordUserDto;

    const userData = {
      Username: email,
      Pool: this.userPool,
    };

    const userCognito = new CognitoUser(userData);

    return new Promise((resolve, reject) => {
      userCognito.forgotPassword({
        onSuccess: (result) => {
          resolve(result);
        },
        onFailure: (err) => {
          reject(err);
        },
      });
    });
  }

  async confirmUserPassword(
    authConfirmPasswordUserDto: AuthConfirmPasswordUserDto,
  ): Promise<{ status: string }> {
    const { email, confirmationCode, newPassword } = authConfirmPasswordUserDto;

    const userData = {
      Username: email,
      Pool: this.userPool,
    };

    const userCognito = new CognitoUser(userData);

    return new Promise((resolve, reject) => {
      userCognito.confirmPassword(confirmationCode, newPassword, {
        onSuccess: () => {
          resolve({ status: "success" });
        },
        onFailure: (err) => {
          reject(err);
        },
      });
    });
  }

  async getCognitoUser(email: string): Promise<CognitoUserSession> {
    const userData: ICognitoUserData = {
      Username: email,
      Pool: this.userPool,
    };

    const userCognito = new CognitoUser(userData);
    return new Promise((resolve, reject) => {
      userCognito.getSession((error, session) => {
        if (error) {
          reject(error);
        }
        resolve(session);
      });
    });
  }

  async signIn(email: string, password: string) {
    const signInParams: AWS.CognitoIdentityServiceProvider.InitiateAuthRequest =
      {
        AuthFlow: "USER_PASSWORD_AUTH",
        ClientId: process.env.AWS_COGNITO_CLIENT_ID, // Replace with your Cognito User Pool App Client ID
        AuthParameters: {
          USERNAME: email,
          PASSWORD: password,
        },
      };

    const authResponse = await this.cognitoIdentityServiceProvider
      .initiateAuth(signInParams)
      .promise();
    if (authResponse.ChallengeName === "MFA_SETUP") {
      const authenticatorData = await this.associateAuthToken({
        userSession: authResponse.Session,
        email,
      });
      return {
        ...authenticatorData,
        ChallengeName: authResponse.ChallengeName,
      };
    }
    return authResponse;
  }

  async totpChallenge({
    email,
    mfaCode,
    session,
    cognitoIdentityServiceProvider,
  }: ITotpChallenge) {
    try {
      const params: CognitoIdentityServiceProvider.Types.AdminRespondToAuthChallengeRequest =
        {
          ChallengeName: "SOFTWARE_TOKEN_MFA",
          ClientId: process.env.AWS_COGNITO_CLIENT_ID,
          ChallengeResponses: {
            USERNAME: email,
            SOFTWARE_TOKEN_MFA_CODE: mfaCode,
          },
          Session: session,
          UserPoolId: process.env.AWS_COGNITO_USER_POOL_ID,
        };

      return await cognitoIdentityServiceProvider
        .adminRespondToAuthChallenge(params)
        .promise();
    } catch (error) {
      console.error("Verification failed:", error);
      throw new ServiceUnavailableException(error);
    }
  }

  async enableMFA(email: string) {
    try {
      const enableMFAParams: AWS.CognitoIdentityServiceProvider.AdminSetUserMFAPreferenceRequest =
        {
          SoftwareTokenMfaSettings: {
            Enabled: true,
            PreferredMfa: true,
          },
          UserPoolId: this.userPool.getUserPoolId(),
          Username: email,
        };

      await this.cognitoIdentityServiceProvider
        .adminSetUserMFAPreference(enableMFAParams)
        .promise();
      return { message: "MFA enabled successfully!" };
    } catch (error) {
      console.error("Verification failed:", error);
      throw new ServiceUnavailableException(error);
    }
  }

  async validateMFA(UserCode: string, AccessTokenOrSession: string) {
    try {
      const params: AWS.CognitoIdentityServiceProvider.VerifySoftwareTokenRequest =
        {
          Session: AccessTokenOrSession,
          UserCode,
        };

      await this.cognitoIdentityServiceProvider
        .verifySoftwareToken(params)
        .promise();
      return { message: "Verification successful!" };
    } catch (error) {
      console.error("Verification failed:", error);
      throw new UnauthorizedException(error);
    }
  }

  async associateAuthToken({ userSession, email }: IAssociateAuthToken) {
    const { SecretCode, Session } = await this.cognitoIdentityServiceProvider
      .associateSoftwareToken({ Session: userSession })
      .promise();
    const name = `Libre Capital: ${email}`;
    const uri = `otpauth://totp/${decodeURI(name)}?secret=${SecretCode}`;
    const qrCode = await QR.toDataURL(uri);
    return {
      qrCode,
      secretCode: SecretCode,
      session: Session,
    };
  }
  async disableEnableUser({ email, isDisabled }: AllowDisallowDto) {
    const params = {
      UserPoolId: this.userPool.getUserPoolId(),
      Username: email, // Username of the user you want to disable
    };
    if (isDisabled)
      await this.cognitoIdentityServiceProvider
        .adminDisableUser(params)
        .promise();
    else
      await this.cognitoIdentityServiceProvider
        .adminEnableUser(params)
        .promise();
    return {
      message: `User with email ${email} is ${
        isDisabled ? "disabled" : "enabled"
      } successfully.`,
    };
  }

  async deleteCognitoUser(email: string): Promise<void> {
    const userData: ICognitoUserData = {
      Username: email,
      Pool: this.userPool,
    };
    const userCognito = new CognitoUser(userData);

    return new Promise((resolve, reject) => {
      userCognito.deleteUser((error) => {
        if (error) {
          reject(error);
        }
        resolve();
      });
    });
  }
}

results matching ""

    No results matching ""