Firebase Phone Authentication Flutter
In this article, we are going to learn firebase phone authentication in flutter platform. This flutter example helps you to authenticate mobile number using firebase with sms verification code in flutter applications.
In this tutorial, first we create project in firebase to integrate our app with firebase platform. Then we enable phone authentication in firebase. To integrate our android app with firebase, we need SHA-1 key and package name of our application.
Add required dependencies in our pubspec.yaml file
Below first two dependencies are required to link our project with firebase. Third library is required to get phone number of device automatically without user input. After adding these libraries in pubspec.yaml file, click on pub get button in android studio to sync library with our application.
firebase_auth: ^0.18.4+1
sms_autofill: ^1.2.7
Changes For Android Platform
First we need to create android app in our firebase project. After completing this step we can download google-services.json file. Then place this file under android/app folder in our source code.

Then we need to add following dependency in root level build.gradle file under android folder.
repositories {
google()
}
dependencies {
classpath ‘com.google.gms:google-services:4.3.4’
}
}
allprojects {
repositories {
google()
}
}
add google services plugin app level build.gradle file under android folder.
Initialize Firebase Platform in main.dart file
await Firebase.initializeApp();
Get current number of device for firebase phone authentication flutter
SmsAutoFill smsAutoFill = SmsAutoFill();
@override
void initState() {
super.initState();
getCurrentNumber();
}
getCurrentNumber() async {
phoneNumEditingController.text = await smsAutoFill.hint;
}
UI for verify Phone Number
controller: phoneNumEditingController,
decoration: const InputDecoration(
labelText: ‘Enter Phone number’),
keyboardType: TextInputType.number,
),
SizedBox(
height: 25,
),
if(showVerifyNumberWidget) Container(
padding: const EdgeInsets.symmetric(vertical: 16.0),
alignment: Alignment.center,
child: RaisedButton(
padding: EdgeInsets.symmetric(vertical: 15, horizontal: 25),
color: Colors.pinkAccent,
child: Text(“Verify Number”, style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold, color: Colors.white)),
onPressed: () async {
phoneNumberVerification();
},
),
),
Firebase phone authentication flutter
We can authenticate phone number using verifyPhoneNumber() method of FirebaseAuth class. First we need to create different callbacks to handle phone verification output.
Phone Number Successfully Verified:
(PhoneAuthCredential phoneAuthCredential) async {
await firebaseAuth.signInWithCredential(phoneAuthCredential);
displayMessage( “Phone number is automatically verified and user signed in: ${firebaseAuth.currentUser.uid}”);
setState(() {
showVerifyNumberWidget = false;
showVerificationCodeWidget = false;
showSuccessWidget = true;
});
};
Phone Number Failed:
(FirebaseAuthException authException) {
displayMessage(‘Phone number verification is failed. Code: ${authException.code}. Message: ${authException.message}’);
};
Verification Code Sent:
(String verificationId, [int forceResendingToken]) async {
displayMessage(‘Please check your phone for the verification code.’);
strVerificationId = verificationId;
setState(() {
showVerifyNumberWidget = false;
showVerificationCodeWidget = true;
});
};
Auto Phone Verification Timeout Error:
(String verificationId) {
displayMessage(“verification code: ” + verificationId);
strVerificationId = verificationId;
setState(() {
showVerifyNumberWidget = false;
showVerificationCodeWidget = true;
});
};
Phone Verification Method:
await firebaseAuth.verifyPhoneNumber(
phoneNumber: phoneNumEditingController.text,
timeout: const Duration(seconds: 5),
verificationCompleted: phoneVerificationCompleted,
verificationFailed: phoneVerificationFailed,
codeSent: phoneCodeSent,
codeAutoRetrievalTimeout: phoneCodeAutoRetrievalTimeout
);
} catch (e) {
displayMessage(“Failed to Verify Phone Number: ${e}”);
}
}
UI for verification code input
If auto phone verification is not successful then we need to authenticate phone number manually. So we display input field to enter sms verification code and button for submit it. After successful phone verification, we display success message.
controller: smsEditingController,
decoration: const InputDecoration(labelText: ‘Verification code’),
),
SizedBox(
height: 25,
),
if(showVerificationCodeWidget) Container(
padding: const EdgeInsets.only(top: 16.0),
alignment: Alignment.center,
child: RaisedButton(
color: Colors.pinkAccent,
onPressed: () async {
signInWithPhoneNumber();
},
child: Text(“Sign in”, style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold, color: Colors.white))
),
),
if(showSuccessWidget) Text(‘You are successfully logged in!’, style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold))
Manual firebase phone authentication flutter
try {
final AuthCredential credential = PhoneAuthProvider.credential(
verificationId: strVerificationId,
smsCode: smsEditingController.text,
);
final User user = (await firebaseAuth.signInWithCredential(credential)).user;
displayMessage(“Successfully signed in UID: ${user.uid}”);
setState(() {
showVerificationCodeWidget = false;
showSuccessWidget = true;
});
} catch (e) {
displayMessage(“Failed to sign in: ” + e.toString());
}
}
Final Code
import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:sms_autofill/sms_autofill.dart'; class MyLoginPage extends StatefulWidget { @override _MyLoginPageState createState() => _MyLoginPageState(); } class _MyLoginPageState extends State<MyLoginPage> { FirebaseAuth firebaseAuth = FirebaseAuth.instance; SmsAutoFill smsAutoFill = SmsAutoFill(); String strVerificationId; final globalKey = GlobalKey<ScaffoldState>(); TextEditingController phoneNumEditingController = TextEditingController(); TextEditingController smsEditingController = TextEditingController(); bool showVerifyNumberWidget = true; bool showVerificationCodeWidget = false; bool showSuccessWidget = false; @override void initState() { super.initState(); getCurrentNumber(); } getCurrentNumber() async { phoneNumEditingController.text = await smsAutoFill.hint; } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Firebase Phone Authentication Sample'), ), key: globalKey, resizeToAvoidBottomPadding: false, body: Center( child: Padding( padding: EdgeInsets.all(40), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ if(showVerifyNumberWidget) TextFormField( controller: phoneNumEditingController, decoration: const InputDecoration( labelText: 'Enter Phone number'), keyboardType: TextInputType.number, ), SizedBox( height: 25, ), if(showVerifyNumberWidget) Container( padding: const EdgeInsets.symmetric(vertical: 16.0), alignment: Alignment.center, child: RaisedButton( padding: EdgeInsets.symmetric(vertical: 15, horizontal: 25), color: Colors.pinkAccent, child: Text("Verify Number", style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold, color: Colors.white)), onPressed: () async { phoneNumberVerification(); }, ), ), if(showVerificationCodeWidget) TextFormField( controller: smsEditingController, decoration: const InputDecoration(labelText: 'Verification code'), ), SizedBox( height: 25, ), if(showVerificationCodeWidget) Container( padding: const EdgeInsets.only(top: 16.0), alignment: Alignment.center, child: RaisedButton( color: Colors.pinkAccent, onPressed: () async { signInWithPhoneNumber(); }, child: Text("Sign in", style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold, color: Colors.white)) ), ), if(showSuccessWidget) Text('You are successfully logged in!', style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold)) ], )), )); } Future<void> phoneNumberVerification() async { PhoneVerificationCompleted phoneVerificationCompleted = (PhoneAuthCredential phoneAuthCredential) async { await firebaseAuth.signInWithCredential(phoneAuthCredential); displayMessage( "Phone number is automatically verified and user signed in: ${firebaseAuth.currentUser.uid}"); setState(() { showVerifyNumberWidget = false; showVerificationCodeWidget = false; showSuccessWidget = true; }); }; PhoneVerificationFailed phoneVerificationFailed = (FirebaseAuthException authException) { displayMessage('Phone number verification is failed. Code: ${authException.code}. Message: ${authException.message}'); }; PhoneCodeSent phoneCodeSent = (String verificationId, [int forceResendingToken]) async { displayMessage('Please check your phone for the verification code.'); strVerificationId = verificationId; setState(() { showVerifyNumberWidget = false; showVerificationCodeWidget = true; }); }; PhoneCodeAutoRetrievalTimeout phoneCodeAutoRetrievalTimeout = (String verificationId) { displayMessage("verification code: " + verificationId); strVerificationId = verificationId; setState(() { showVerifyNumberWidget = false; showVerificationCodeWidget = true; }); }; try { await firebaseAuth.verifyPhoneNumber( phoneNumber: phoneNumEditingController.text, timeout: const Duration(seconds: 5), verificationCompleted: phoneVerificationCompleted, verificationFailed: phoneVerificationFailed, codeSent: phoneCodeSent, codeAutoRetrievalTimeout: phoneCodeAutoRetrievalTimeout); } catch (e) { displayMessage("Failed to Verify Phone Number: ${e}"); } } void displayMessage(String message) { globalKey.currentState.showSnackBar(SnackBar(content: Text(message))); } void signInWithPhoneNumber() async { try { final AuthCredential credential = PhoneAuthProvider.credential( verificationId: strVerificationId, smsCode: smsEditingController.text, ); final User user = (await firebaseAuth.signInWithCredential(credential)).user; displayMessage("Successfully signed in UID: ${user.uid}"); setState(() { showVerificationCodeWidget = false; showSuccessWidget = true; }); } catch (e) { displayMessage("Failed to sign in: " + e.toString()); } } }
import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; import 'package:flutterfirebasephoneauth/my_login_page.dart'; void main() async{ WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); runApp(MyApp()); } class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: MyLoginPage(), ); } }



