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_core: ^0.5.3
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.

buildscript {

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.

apply plugin: ‘com.google.gms.google-services’
 
 

Initialize Firebase Platform in main.dart file

WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
 
 

Get current number of device for firebase phone authentication flutter

TextEditingController phoneNumEditingController = TextEditingController();
SmsAutoFill smsAutoFill = SmsAutoFill();

@override
void initState() {
    super.initState();
    getCurrentNumber();
}

getCurrentNumber() async {
    phoneNumEditingController.text = await smsAutoFill.hint;
}

 
 

UI for verify Phone Number

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();
    },
),
),
 
 

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:

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;
    });
};
 

Phone Number Failed:

PhoneVerificationFailed phoneVerificationFailed =
(FirebaseAuthException authException) {
    displayMessage(‘Phone number verification is failed. Code: ${authException.code}. Message: ${authException.message}’);
};
 

Verification Code Sent:

PhoneCodeSent phoneCodeSent =
(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:

PhoneCodeAutoRetrievalTimeout phoneCodeAutoRetrievalTimeout =
(String verificationId) {
    displayMessage(“verification code: ” + verificationId);
    strVerificationId = verificationId;
    setState(() {
        showVerifyNumberWidget = false;
        showVerificationCodeWidget = true;
    });
};
 

Phone Verification Method:

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}”);
}
}
 
 

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.

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))
 
 

Manual firebase phone authentication flutter

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());
}
}

 
 

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(),
    );
  }
}

 
 
 
firebase phone authentication flutter
 
 
firebase phone authentication flutter
 
 

One thought on “Firebase Phone Authentication Flutter

Leave a Reply