🌎Auth Domain Firebase

Nesta seção, você vai encontrar os códigos utilizados para realizar a autenticação do seu aplicativo através do Firebase, com email e senha, google, apple, telefone, etc.

O Firebase é uma mão na roda quando se trata de autenticação, em qualquer método que seja ele provê maneiras muito fáceis de implementação, que vamos ver a seguir.

!!!! COMO UTILIZAR ESSA AUTENTICAÇÃO COM O PLUGIN!!!!

〽️Package Firebase Auth

É importante lembrar de:

As autenticações com redes sociais, demandas outros packages juntamente do Firebase para funcionar, e cada uma com suas peculiaridades de configuração para Android e iOS, é importante seguir fielmente a documentação para que tudo isso funcione, abaixo vou deixar os links dos plugins utilizados:

firebase_auth

google_sign_in

sign_in_with_apple

flutter_facebook_auth

Registrar usuário com email e senha

O código a seguir mostra como realizar o registro com email e senha pelo firebase, e ainda mostrando alguns dos possíveis erros retornados, onde podemos pegar seu código e mostrar uma mensagem ao usuário.

Future<Either<AuthCustomException, RegisterSuccess>> register({
    required String email,
    required String password,
  }) async {
    try {
      await FirebaseAuth.instance.createUserWithEmailAndPassword(
        email: email,
        password: password,
      );
      
      Authentication.saveToken(
        await firebaseAuthInstace.currentUser?.getIdToken() ?? "",
      );

      return Right(RegisterSuccess());
    } on FirebaseAuthException catch (e) {
      if (e.code == 'email-already-in-use') {
        return const Left(
          AuthCustomException(
            message: "Este email já esta em uso.",
          ),
        );
      } else {
        return const Left(
          AuthCustomException(),
        );
      }
    } catch (e) {
      return const Left(
        AuthCustomException(),
      );
    }
  }

Login com email e senha

O código a seguir mostra como realizar o login com email e senha pelo firebase, e ainda mostrando alguns dos possíveis erros retornados, onde podemos pegar seu código e mostrar uma mensagem ao usuário.

  Future<Either<AuthCustomException, LoginSuccess>> login({
    required String email,
    required String password,
  }) async {
    try {
      await FirebaseAuth.instance.signInWithEmailAndPassword(
        email: email,
        password: password,
      );
      
      
      Authentication.saveToken(
        await firebaseAuthInstace.currentUser?.getIdToken() ?? "",
      );


      return Right(LoginSuccess());
    } on FirebaseAuthException catch (e) {
      if (e.code == 'user-not-found') {
        return const Left(
          AuthCustomException(
            message: "Não foi encontrado nenhum usuário com este email.",
          ),
        );
      } else if (e.code == 'wrong-password') {
        return const Left(AuthCustomException(
          message: "Senha incorreta.",
        ));
      } else {
        return const Left(AuthCustomException());
      }
    } catch (e) {
      return const Left(AuthCustomException());
    }
  }

Logout

await FirebaseAuth.instance.signOut();

Envio de recuperação de senha pelo email

Nesta função, antes de fazer o envio para o email, é checado se o usuário logado atualmente, é um usuário que fez registro com email e senha, para que de fato seja possível esta alteração.

Future<Either<AuthCustomException, RequestSuccess>> passwordRecover({
    required String email,
  }) async {
    List<String> loginMethods =
        await FirebaseAuth.instance.fetchSignInMethodsForEmail(email);

    if (loginMethods.isNotEmpty && loginMethods.contains("password")) {
      try {
        await FirebaseAuth.instance.sendPasswordResetEmail(email: email);

        return Right(RequestSuccess());
      } on FirebaseAuthException catch (e) {
        log(e.toString());
        if (e.code == 'auth/invalid-email' || e.code == 'invalid-email') {
          return const Left(
            AuthCustomException(
              message: "Email inválido.",
            ),
          );
        } else if (e.code == 'auth/user-not-found' ||
            e.code == 'user-not-found') {
          return const Left(
            AuthCustomException(
              message: "Este email não está cadastrado.",
            ),
          );
        } else {
          return const Left(
            AuthCustomException(),
          );
        }
      } catch (e) {
        return const Left(
          AuthCustomException(),
        );
      }
    } else {
      return const Left(
        AuthCustomException(
          message: "Não é possível alterar a senha para este email.",
        ),
      );
    }
  }

Deletar conta

Future<Either<AuthCustomException, RequestSuccess>> deleteAccount() async {
    if (FirebaseAuth.instance.currentUser == null) {
      return const Left(
        AuthCustomException(),
      );
    } else {
      try {
        await FirebaseAuth.instance.currentUser?.delete();

        return Right(RequestSuccess());
      } on FirebaseAuthException catch (e) {
        if (e.code == 'firebase_auth/requires-recent-login' ||
            e.code == 'requires-recent-login' &&
                e.code == 'auth/requires-recent-login') {
          return const Left(
            AuthCustomException(
              message:
                  "É necessário que você saia e faça login novamente para poder deletar sua conta.",
            ),
          );
        }
        return const Left(
          AuthCustomException(),
        );
      } catch (e) {
        return const Left(
          AuthCustomException(),
        );
      }
    }
  }

Login/Registro com Apple

O login com redes sociais, é independente se existe uma conta já ou não, se já existe ele vai acessar, se não existe vai criar, com a mesma função.

Future<Either<AuthCustomException, LoginSuccess>> signInWithApple() async {
    try {
      final credential = await SignInWithApple.getAppleIDCredential(
        scopes: [
          AppleIDAuthorizationScopes.email,
          AppleIDAuthorizationScopes.fullName,
        ],
      );

      final AuthCredential firebaseCredentials =
          OAuthProvider('apple.com').credential(
        accessToken: credential.authorizationCode,
        idToken: credential.identityToken,
      );

      final UserCredential authResult =
          await FirebaseAuth.instance.signInWithCredential(firebaseCredentials);

      Authentication.saveToken(
          await FirebaseAuth.instance.currentUser!.getIdToken());
          
      final User? user = authResult.user;

      if (user != null) {
        assert(!user.isAnonymous);

        final User? currentUser = firebaseAuthInstace.currentUser;
        assert(user.uid == currentUser!.uid);

        Authentication.saveToken(
          await FirebaseAuth.instance.currentUser!.getIdToken(),
        );

        return Right(LoginSuccess());
      } else {
        return const Left(AuthCustomException());
      }
    } on FirebaseAuthException catch (e) {
      if (e.code == 'user-not-found') {
        return const Left(
          AuthCustomException(
            message: "Não foi encontrado nenhum usuário com este email.",
          ),
        );
      } else if (e.code == 'wrong-password') {
        return const Left(AuthCustomException(
          message: "Senha incorreta.",
        ));
      } else {
        return const Left(AuthCustomException());
      }
    } catch (e) {
      log(e.toString());
      return const Left(AuthCustomException());
    }
  }

Login e logout com Google

Future<Either<AuthCustomException, LoginSuccess>> signInWithGoogle() async {
    try {
      final GoogleSignInAccount? googleSignInAccount =
          await googleSignIn.signIn();
      final GoogleSignInAuthentication googleSignInAuthentication =
          await googleSignInAccount!.authentication;

      final AuthCredential credential = GoogleAuthProvider.credential(
        accessToken: googleSignInAuthentication.accessToken,
        idToken: googleSignInAuthentication.idToken,
      );

      final UserCredential authResult =
          await FirebaseAuth.instance.signInWithCredential(credential);
      final User? user = authResult.user;

      if (user != null) {
        assert(!user.isAnonymous);

        final User? currentUser = FirebaseAuth.instance.currentUser;
        assert(user.uid == currentUser!.uid);

        Authentication.saveToken(
          await FirebaseAuth.instance.currentUser!.getIdToken(),
        );

        return Right(LoginSuccess());
      } else {
        return const Left(AuthCustomException());
      }
    } on FirebaseAuthException catch (e) {
      if (e.code == 'user-not-found') {
        return const Left(
          AuthCustomException(
            message: "Não foi encontrado nenhum usuário com este email.",
          ),
        );
      } else if (e.code == 'wrong-password') {
        return const Left(AuthCustomException(
          message: "Senha incorreta.",
        ));
      } else {
        return const Left(AuthCustomException());
      }
    } catch (e) {
      return const Left(AuthCustomException());
    }
  }
googleSignIn.signOut();

Exemplo de chamada store:

@action
  Future loginWithGoogle(BuildContext context) async {
    try {
      loading = true;
      final result = await GetIt.I.get<ILoginWithGoogleUsecase>()();

      return result.fold(
        (l) {
          loading = false;
          customErrorHelper(context, e: l);
          printException("AuthStore.loginWithGoogle", l, l);
          return false;
        },
        (r) async {
          loading = false;
          return true;
        },
      );
    } catch (e, s) {
      printException("AuthStore.loginWithGoogle", e, s);
      loading = false;
      return false;
    }
  }

Login e logout Facebook

Future signInWithFacebook() async {
    try {
      final LoginResult result = await FacebookAuth.instance.login();
      if (result.status == LoginStatus.success) {
        final OAuthCredential credential =
            FacebookAuthProvider.credential(result.accessToken?.token ?? "");

        await _auth.signInWithCredential(credential);
        Authentication.saveToken(await _auth.currentUser?.getIdToken() ?? "");
      }
      return "";
    } catch (e, s) {
       log(e.toString());
      printException("signInWithGoogle.authDatasource", e, s);
      throw AuthCustomException(
        "Ocorreu um erro inesperado.",
      );
    }
  }
FacebookAuth.instance.logOut();

Envio de sms para login com telefone

Este é código abaixo é para realizar apenas o envio do sms para o telefone inserido, após o sucesso nessa requisição que realizaremos o login.

Future signInWithPhone(
    BuildContext context, {
    required Function() onVerificationCompleted,
    required Function() onCodeSent,
  }) async {
    try {
      loading = true;

      await FirebaseAuth.instance.verifyPhoneNumber(
        phoneNumber: "+$registerPhoneNumberCountry $registerPhoneNumber",
        verificationCompleted: (PhoneAuthCredential credential) async {},
        codeAutoRetrievalTimeout: (String verificationId) {
          log('codeAutoRetrievalTimeout');
        },
        verificationFailed: (FirebaseAuthException e) {
          if (e.code == 'invalid-phone-number') {
            showDialogHelper(
              body: "Número de telefone inválido.",
              confirmButtonText: 'OK',
              context: context,
              title: 'Erro',
            );
          } else {
            customErrorHelper(context, e: e);
          }
          loading = false;
        },
        codeSent: (String verificationId, int? resendToken) async {
          loading = false;
          currentVerificationId = verificationId;
          onCodeSent();
          startTimer();
        },
      );

      return true;
    } catch (e, s) {
      printException("SignInWithPhone", e, s);
      return false;
    }
  }

Login com código de sms do telefone

@action
  Future signInWithPhoneCode(BuildContext context) async {
    try {
      loading = true;
      PhoneAuthCredential credential = PhoneAuthProvider.credential(
        verificationId: currentVerificationId,
        smsCode: registerSmsCode,
      );

      await FirebaseAuth.instance.signInWithCredential(credential);

      Authentication.saveToken(
        await FirebaseAuth.instance.currentUser!.getIdToken(),
      );
      loading = false;

      return true;
    } on FirebaseAuthException catch (e, s) {
      if (e.code == 'firebase_auth/session-expired' ||
          e.code == 'session-expired') {
        showDialogHelper(
          body: "Código expirado.",
          confirmButtonText: 'OK',
          context: context,
          title: 'Erro',
        );
      } else {
        customErrorHelper(context, e: e);
      }

      loading = false;
      printException("signInWithPhoneCode", e, s);
      return false;
    } catch (e, s) {
      loading = false;
      printException("signInWithPhoneCode", e, s);
      customErrorHelper(context, e: e);
      return false;
    }
  }

Last updated