Demo Project to show how to use Phone Authentication in Flutter with Firebase backend
Demo Project to show how to do Phone Authentication in Flutter using Firebase backend.
At First | PhoneNo is entered and submitted |
---|---|
After OTP is entered & submitted | App is restarted |
---|---|
I felt there is no setp-by-step documentation for Firebase Phone Authentication in Flutter. There were couple of implementations on Medium but are out-dated and one article got it but that failed to explain some crucial concepts. AndroidX brought a lot of changes in addition to FlutterFire plugins update. I asked this question on stackoverflow almost 2 years ago, but failed to get step-by-step answer. So I created this demo project.
You can setup Firebase by following this guide: https://firebase.google.com/docs/flutter/setup
If you encounter errors with MultiDex
or AndroidX
make sure you follow below steps
// Inside android folder in app level build.gradle file
...
android {
...
defaultConfig {
...
multiDexEnabled true // add this
}
...
}
...
dependencies {
// implementation 'com.android.support:multidex:1.0.3' // No AndroidX support
implementation 'com.android.support:multidex:2.0.1' // Add this to support AndroidX
implementation 'androidx.browser:browser:1.2.0' // To display verification webpage in the user's default browser
...
}
...
AuthCrendential
objectAuthCredential
object is the only thing that is used to signIn the user.
It is obtained either from verificationCompleted
callback function in verifyPhoneNumber
or from the PhoneAuthProvider
.
(Don't worry if it's confusing, keep reading, you'll get it)phoneNumber
phoneNumber
is not in the device that is currently running the app,
AuthCredential
objectAuthCredential
to signIn
This method works even if the phoneNumber
is in the deviceverificationCompleted
callback from submitPhoneNumber
function gives the AuthCredential
object which is needed to signIn the userFuture<void> _submitPhoneNumber() async {
/// NOTE: Either append your phone number country code or add in the code itself
/// Since I'm in India we use "+91 " as prefix `phoneNumber`
String phoneNumber = "+91 " + _phoneNumberController.text.toString().trim();
print(phoneNumber);
/// The below functions are the callbacks, separated so as to make code more redable
void verificationCompleted(AuthCredential phoneAuthCredential) {
print('verificationCompleted');
...
this._phoneAuthCredential = phoneAuthCredential;
print(phoneAuthCredential);
}
void verificationFailed(AuthException error) {
...
print(error);
}
void codeSent(String verificationId, [int code]) {
...
print('codeSent');
}
void codeAutoRetrievalTimeout(String verificationId) {
...
print('codeAutoRetrievalTimeout');
}
await FirebaseAuth.instance.verifyPhoneNumber(
/// Make sure to prefix with your country code
phoneNumber: phoneNumber,
/// `seconds` didn't work. The underlying implementation code only reads in `millisenconds`
timeout: Duration(milliseconds: 10000),
/// If the SIM (with phoneNumber) is in the current device this function is called.
/// This function gives `AuthCredential`. Moreover `login` function can be called from this callback
verificationCompleted: verificationCompleted,
/// Called when the verification is failed
verificationFailed: verificationFailed,
/// This is called after the OTP is sent. Gives a `verificationId` and `code`
codeSent: codeSent,
/// After automatic code retrival `tmeout` this function is called
codeAutoRetrievalTimeout: codeAutoRetrievalTimeout,
); // All the callbacks are above
}
void _submitOTP() {
/// get the `smsCode` from the user
String smsCode = _otpController.text.toString().trim();
/// when used different phoneNumber other than the current (running) device
/// we need to use OTP to get `phoneAuthCredential` which is inturn used to signIn/login
this._phoneAuthCredential = PhoneAuthProvider.getCredential(
verificationId: this._verificationId, smsCode: smsCode);
_login();
}
Future<void> _login() async {
/// This method is used to login the user
/// `AuthCredential`(`_phoneAuthCredential`) is needed for the signIn method
/// After the signIn method from `AuthResult` we can get `FirebaserUser`(`_firebaseUser`)
try {
await FirebaseAuth.instance
.signInWithCredential(this._phoneAuthCredential)
.then((AuthResult authRes) {
_firebaseUser = authRes.user;
print(_firebaseUser.toString());
});
...
} catch (e) {
...
print(e.toString());
}
}
Future<void> _logout() async {
/// Method to Logout the `FirebaseUser` (`_firebaseUser`)
try {
// signout code
await FirebaseAuth.instance.signOut();
_firebaseUser = null;
...
} catch (e) {
...
print(e.toString());
}
}
For more details on implementation please refer to the lib/main.dart
file.
README
useful please star the repository