signInWithEmailAndPassword method

  1. @override
Future<AuthUser<User>> signInWithEmailAndPassword({
  1. required String email,
  2. required String password,
  3. String? merchantId,
})
override

Implementation

@override
Future<AuthUser<User>> signInWithEmailAndPassword(
    {required String email,
    required String password,
    String? merchantId}) async {
  final MonitoringService monitoringService = core.get<MonitoringService>();
  var trace =
      await monitoringService.createTrace(name: 'signInWithEmailAndPassword');
  trace.start();
  try {
    if (!isReady) {
      throw LittlefishFirebaseAuthException('AUTH_INIT_000',
          '$providerName: Firebase is not initialized, $providerName cannot sign in with email and password');
    }

    if (email.isEmpty || password.isEmpty) {
      throw LittlefishFirebaseAuthException('AUTH_007',
          '$providerName: Email or password is empty, $providerName cannot sign in with email and password');
    }

    AuthUser<User>? authUser;
    switch (authMode) {
      case AuthMode.providerOnly:
        logger.debug(
          this,
          "$providerName: Signing in with email:$email and password with conditions",
        );
        // PART 1: Sign in with provider
        var r = await kInstance?.signInWithEmailAndPassword(
          email: email,
          password: password,
        );

        if (r?.user == null) {
          throw LittlefishFirebaseAuthException('AUTH_008',
              '$providerName: Sign in with email and password failed, $providerName cannot locate user information post-logon');
        }

        kUserCredential = r!.credential;
        authUser = FirebaseAuthUser(
          kUser: r.user!,
          additionalUserInfo:
              _convertAdditionalUserInfo(r.additionalUserInfo),
          baseUserId: r.user?.uid ?? '',
          baseUserFirstName: r.user?.displayName ?? '',
          baseUserLastName: r.user?.displayName ?? '',
          baseUserEmail: r.user?.email ?? '',
          baseUserRegisteredDate:
              r.user?.metadata.creationTime ?? DateTime.now(),
          baseUserMobileNumber: r.user?.phoneNumber ?? '',
          baseUserProfileImageUri: r.user?.photoURL ?? '',
          baseUserGender: UserGender.notSpecified,
          baseUserDisplayName: r.user?.displayName ?? '',
          baseUserEmailVerified: r.user?.emailVerified ?? false,
        );

        logger.info(
          this,
          "$providerName: Signed in with email:$email and password",
        );
        // PART 2: Call custom auth to get token

        final idToken = await r.user?.getIdToken();

        authenticationResult = AuthResult(
          token: idToken,
          accessToken: idToken,
          authenticated: !(r.user?.isAnonymous ?? true),
          businesses: [],
          message: 'Signed in with provider only',
          otpId: '',
          refreshToken: '',
          sessionId: '',
          verified: r.user?.emailVerified ?? false,
        );

        // Fire-and-forget: track login for providerOnly since no backend
        // login endpoint is called (TryWriteLoginTracking never fires).
        _trackLoginEvent(authUser);

        break;

      case AuthMode.customOnly:
        await signInApi(email, password);
        if (authenticationResult?.accessToken == null) {
          throw LittlefishFirebaseAuthException('AUTH_009',
              '$providerName: Custom authentication failed, no token received');
        }
        authUser = await signInWithCustomToken(
            token: authenticationResult!.accessToken!);
        break;

      case AuthMode.providerAndCustom:
        logger.debug(
          this,
          "$providerName: Signing in with email:$email and password",
        );
        // PART 1: Sign in with provider
        var r = await kInstance?.signInWithEmailAndPassword(
          email: email,
          password: password,
        );
        // authenticationResult = AuthResult();

        if (r?.user == null) {
          throw LittlefishFirebaseAuthException('AUTH_008',
              '$providerName: Sign in with email and password failed, $providerName cannot locate user information post-logon');
        }

        kUserCredential = r!.credential;
        authUser = FirebaseAuthUser(
          kUser: r.user!,
          additionalUserInfo:
              _convertAdditionalUserInfo(r.additionalUserInfo),
          baseUserId: r.user?.uid ?? '',
          baseUserFirstName: r.user?.displayName ?? '',
          baseUserLastName: r.user?.displayName ?? '',
          baseUserEmail: r.user?.email ?? '',
          baseUserRegisteredDate:
              r.user?.metadata.creationTime ?? DateTime.now(),
          baseUserMobileNumber: r.user?.phoneNumber ?? '',
          baseUserProfileImageUri: r.user?.photoURL ?? '',
          baseUserGender: UserGender.notSpecified,
          baseUserDisplayName: r.user?.displayName ?? '',
          baseUserEmailVerified: r.user?.emailVerified ?? false,
        );

        logger.info(
          this,
          "$providerName: Signed in with email:$email and password",
        );
        // PART 2: Call custom auth to get token

        final idToken = await r.user?.getIdToken();

        authenticationResult = AuthResult(
          token: idToken,
          accessToken: idToken,
          authenticated: !(r.user?.isAnonymous ?? true),
          businesses: [],
          message: 'Signed in with provider only',
          otpId: '',
          refreshToken: '',
          sessionId: '',
          verified: r.user?.emailVerified ?? false,
        );
        try {
          authenticationResult = await signInApi(email, password);

          await signInWithCustomToken(token: authenticationResult!.token!);
        } catch (e, st) {
          logger.error('FirebaseAuthService',
              'Custom authentication failed, signing out from Firebase to ensure clean state. Error: $e',
              error: e, stackTrace: st);
          await signOut();
          throw LittlefishFirebaseAuthException(
            AuthenticationErrorCodes.customAuthFailedSigningOut.code,
            AuthenticationErrorCodes.customAuthFailedSigningOut.message,
            cause: e,
          );
        }

        break;

      case AuthMode.providerAndCustomConditions:
        logger.debug(
          this,
          "$providerName: Signing in with email:$email and password with conditions",
        );
        // PART 1: Sign in with provider
        var r = await kInstance?.signInWithEmailAndPassword(
          email: email,
          password: password,
        );

        if (r?.user == null) {
          throw LittlefishFirebaseAuthException('AUTH_008',
              '$providerName: Sign in with email and password failed, $providerName cannot locate user information post-logon');
        }

        kUserCredential = r!.credential;
        authUser = FirebaseAuthUser(
          kUser: r.user!,
          additionalUserInfo:
              _convertAdditionalUserInfo(r.additionalUserInfo),
          baseUserId: r.user?.uid ?? '',
          baseUserFirstName: r.user?.displayName ?? '',
          baseUserLastName: r.user?.displayName ?? '',
          baseUserEmail: r.user?.email ?? '',
          baseUserRegisteredDate:
              r.user?.metadata.creationTime ?? DateTime.now(),
          baseUserMobileNumber: r.user?.phoneNumber ?? '',
          baseUserProfileImageUri: r.user?.photoURL ?? '',
          baseUserGender: UserGender.notSpecified,
          baseUserDisplayName: r.user?.displayName ?? '',
          baseUserEmailVerified: r.user?.emailVerified ?? false,
        );

        logger.info(
          this,
          "$providerName: Signed in with email:$email and password",
        );
        // PART 2: Call custom auth to get token

        try {
          authenticationResult = await signInApiWithConditions(
              email, password, merchantId ?? '', settings.platformType);

          await signInWithCustomToken(token: authenticationResult!.token!);
        } catch (e, st) {
          logger.error('FirebaseAuthService',
              'Custom authentication failed, signing out from Firebase to ensure clean state. Error: $e',
              error: e, stackTrace: st);
          await signOut();
          throw LittlefishFirebaseAuthException(
            AuthenticationErrorCodes.customAuthFailedSigningOut.code,
            AuthenticationErrorCodes.customAuthFailedSigningOut.message,
            cause: e,
          );
        }

        break;
    }

    return authUser;
  } on FirebaseAuthException catch (e) {
    throw _handleFirebaseAuthException(e);
  } catch (e) {
    if (e is LittlefishException) {
      rethrow;
    }
    throw LittlefishFirebaseAuthException(
      'AUTH_014',
      'An unexpected error occurred during sign in with email and password.',
      cause: e,
    );
  } finally {
    trace.stop();
  }
}