Skip to content

Instantly share code, notes, and snippets.

@erluxman
Last active July 6, 2020 03:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erluxman/fe93be1cbd25293c8f855ceaf4cb3b0f to your computer and use it in GitHub Desktop.
Save erluxman/fe93be1cbd25293c8f855ceaf4cb3b0f to your computer and use it in GitHub Desktop.
FirebaseAuthRepo
import 'package:apple_sign_in/apple_sign_in.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_facebook_login/flutter_facebook_login.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:rxdart/rxdart.dart';
import 'package:toast_badge/toast_badge.dart';
/* Add the following dependencies to fully use it
firebase_auth: ^0.16.1
flutter_facebook_login: ^3.0.0
google_sign_in: ^4.5.1
firebase_core: ^0.4.5
apple_sign_in: ^0.1.0
rxdart
toast_badge
*/
class AuthRepo with ChangeNotifier {
BehaviorSubject<FirebaseUser> _userStream = BehaviorSubject();
BehaviorSubject<bool> _verificationCodeSent = BehaviorSubject();
String _verificationId;
AuthRepo() {
_init();
}
Stream<FirebaseUser> user() => _userStream;
Stream<bool> verificationCodeSent() => _verificationCodeSent;
_init() async {
print("user stream initialized");
_userStream.add(await FirebaseAuth.instance.currentUser());
print(_userStream.value);
}
Future<void> updateDisplayName(String newName) async {
//Have to call it twice for name coz for some strange reason, name does not update in one call.
await _updateFirebaseProfile(displayName: newName);
await _updateFirebaseProfile(displayName: newName);
return _userStream.add(await FirebaseAuth.instance.currentUser());
}
Future<void> updateImageUrl(String newImageUrl) async {
await _updateFirebaseProfile(photoUrl: newImageUrl);
return _userStream.add(await FirebaseAuth.instance.currentUser());
}
Future<void> _updateFirebaseProfile({String displayName, String photoUrl}) async {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
UserUpdateInfo newInfo = UserUpdateInfo();
newInfo.displayName = displayName ?? user.displayName;
newInfo.photoUrl = photoUrl ?? user.photoUrl;
return await user.updateProfile(newInfo);
}
sendVerificationCode(String phone) async {
await FirebaseAuth.instance.verifyPhoneNumber(
phoneNumber: phone,
timeout: Duration(minutes: 1),
verificationCompleted: completed(),
verificationFailed: failed(),
codeSent: codeSent(),
codeAutoRetrievalTimeout: autoTimeout(),
);
}
submitVerificationCode(String verificationCode) async {
print("login with phone Otp:$verificationCode and verification code $verificationCode");
AuthCredential cred =
PhoneAuthProvider.getCredential(verificationId: _verificationId, smsCode: verificationCode);
AuthResult result = await FirebaseAuth.instance.signInWithCredential(cred);
print("Auth result : ${result.user.phoneNumber}");
ToastBadge.show("Login Success");
await Future.delayed(Duration(seconds: 2));
FirebaseUser user = await FirebaseAuth.instance?.currentUser();
_userStream.add(user);
_verificationId = null;
_verificationCodeSent.add(false);
print("user's phone number ${user?.phoneNumber}");
print("user is verified ${user?.phoneNumber}");
}
logOut() async {
_userStream.add(null);
ToastBadge.show("Logout Success");
await Future.delayed(Duration(seconds: 2));
FirebaseAuth.instance.signOut();
_userStream.add(await FirebaseAuth.instance.currentUser());
}
PhoneVerificationCompleted completed() => (AuthCredential cred) async {
print("verification completed ${cred.toString()}");
FirebaseUser user = await FirebaseAuth.instance.currentUser();
print("phone number : ${user.phoneNumber}");
};
PhoneVerificationFailed failed() => (AuthException exception) {
print("verification failed ${exception.message}");
};
PhoneCodeSent codeSent() => (String code, [int force]) {
print("verification code sent $code");
_verificationId = code;
ToastBadge.show("Code Sent");
_verificationCodeSent.add(true);
};
PhoneCodeAutoRetrievalTimeout autoTimeout() => (String verificationID) {
print("auto retribal timeout $verificationID");
};
@override
void dispose() {
super.dispose();
_userStream.close();
_verificationCodeSent.close();
}
loginWithFacebook() async {
final AuthResult authResult =
await FirebaseAuth.instance.signInWithCredential(await _getFbCredential());
final FirebaseUser user = authResult.user;
_userStream.add(user);
}
loginWithGoogle() async {
final FirebaseAuth _auth = FirebaseAuth.instance;
final AuthCredential credential = await _getGoogleCredential();
final AuthResult result = await _auth.signInWithCredential(credential);
final FirebaseUser user = result.user;
_userStream.add(user);
}
Future<void> addGoogle() async {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
AuthCredential googleauthCredential = await _getGoogleCredential();
await user.linkWithCredential(googleauthCredential);
return _userStream.add(await FirebaseAuth.instance.currentUser());
}
loginWithApple() async {
final FirebaseAuth _auth = FirebaseAuth.instance;
final AuthCredential credential = await _getAppleCredential();
if (credential == null) return;
final AuthResult result = await _auth.signInWithCredential(credential);
final FirebaseUser user = result.user;
_userStream.add(user);
}
Future<void> addApple() async {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
AuthCredential appleCreds = await _getAppleCredential();
await user.linkWithCredential(appleCreds);
return _userStream.add(await FirebaseAuth.instance.currentUser());
}
Future<AuthCredential> _getGoogleCredential() async {
final GoogleSignIn _googleSignIn = GoogleSignIn();
final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
return GoogleAuthProvider.getCredential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
}
Future<AuthCredential> _getAppleCredential() async {
final AuthorizationResult result = await AppleSignIn.performRequests([
AppleIdRequest(requestedScopes: [Scope.email, Scope.fullName])
]);
if (result.status != AuthorizationStatus.authorized) return null;
final AppleIdCredential appleIdCredential = result.credential;
final OAuthProvider oAuthProvider = OAuthProvider(providerId: "apple.com");
return oAuthProvider.getCredential(
idToken: String.fromCharCodes(appleIdCredential.identityToken),
accessToken: String.fromCharCodes(appleIdCredential.authorizationCode),
);
}
Future<AuthCredential> _getFbCredential() async {
FacebookLoginResult result = await FacebookLogin().logIn(['email']);
if (result.accessToken == null) {
await FacebookLogin().logOut();
print("fbloginerror" + result.errorMessage);
result = await FacebookLogin().logIn(['email']);
if (result.accessToken == null) {
ToastBadge.show(result.errorMessage, mode: ToastMode.ERROR);
}
}
return FacebookAuthProvider.getCredential(accessToken: result.accessToken.token);
}
loginWithEmailPass(String email, String password) async {
AuthCredential emailCred = await _getEmailCredential(email, password).catchError(
(error) {
print("caught error 1 $error");
ToastBadge.show(error.toString(), mode: ToastMode.ERROR);
},
);
FirebaseAuth.instance.signInWithCredential(emailCred).then((AuthResult authResult) {
final FirebaseUser user = authResult.user;
_userStream.add(user);
}).catchError(
(Object e) {
if (e is PlatformException && e.code == "ERROR_USER_NOT_FOUND") {
FirebaseAuth.instance
.createUserWithEmailAndPassword(email: email, password: password)
.then((AuthResult authResult) {
final FirebaseUser user = authResult.user;
_userStream.add(user);
});
}
ToastBadge.show(e.toString(), mode: ToastMode.ERROR);
print("caught error 2 $e");
},
);
}
Future<AuthCredential> _getEmailCredential(String email, String password) async =>
EmailAuthProvider.getCredential(email: email, password: password);
Future<void> addFacebook() async {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
AuthCredential fbAuthCredential = await _getFbCredential();
await user.linkWithCredential(fbAuthCredential);
return _userStream.add(await FirebaseAuth.instance.currentUser());
}
Future<void> removeFacebook() async {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
await user.unlinkFromProvider(FacebookAuthProvider.providerId);
return _userStream.add(await FirebaseAuth.instance.currentUser());
}
Future<void> removeProvider(String providerID) async {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
List<UserInfo> providers =
user.providerData.where((UserInfo provider) => provider.providerId != "firebase").toList();
providers.removeWhere((UserInfo info) => info.providerId == providerID);
//There needs to be at least one firebase Id and another provider Id (email/fb/google)
if (providers.length < 1) {
ToastBadge.show("Needs at least one way to login to your account", mode: ToastMode.ERROR);
return;
} else {
await user.unlinkFromProvider(providerID);
return _userStream.add(await FirebaseAuth.instance.currentUser());
}
}
Future<void> removeGoogle() async {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
await user.unlinkFromProvider(GoogleAuthProvider.providerId);
return _userStream.add(await FirebaseAuth.instance.currentUser());
}
Future<void> sendForgotPasswordEmail(String email) async {
return await FirebaseAuth.instance.sendPasswordResetEmail(email: email);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment