🌎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.
Atenção, no futuro todas as implementação mostradas a seguir, estarão disponíveis através de um "package" próprio nosso pelo github, e será necessarío apenas a chamada da função.
ACONTECEU!!! Com isso, toda a explicação do código abaixo serve para aprendizado, mas não será mais necessário a sua devida implementação em cada projeto, vamos precisar apenas registrar no pubspec e utilizar as suas funções.
!!!! COMO UTILIZAR ESSA AUTENTICAÇÃO COM O PLUGIN!!!!
〽️Package Firebase AuthOs códigos a seguir, foram feitos utilizando o package dartz, para uso do Either, no retorno de suas funções. Mas ele serve apenas para que o retorno das funções seja ou Esquerda (erro), ou Direita (successo) sempre, e torne mais fácil a verificação da resposta.
É 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:
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