Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do Phone Authentication in Flutter using Firebase?

I have searched many websites and I didn't find a way to implement phone authentication in Flutter using Firebase. Can anyone tell me how to this?

like image 835
Mohith7548 Avatar asked May 04 '18 18:05

Mohith7548


People also ask

How do you implement a phone number verification by OTP using Firebase in Flutter?

Enable Phone Authentication in Firebase All you have to do is click enabled. Then download the google-services. json file again, and add it the project under android/app . Note: If you want to authenticate using email/password then check this tutorial: Using Firebase Auth In Flutter.

How do you send OTP with Firebase in Flutter?

After making Firebase Project from Firebase console, and integrating it with Flutter application, you must enable the Phone sign up method first. For this go in Firebase console, open the Authentication tab from the left panel. Click on the Setup Sign up method and enable the Phone verification.


2 Answers

Well Documented Working Demo project here

Below is the detailed procedure

Steps

  1. Ask for user's phoneNumber
  2. Get OTP from Firebase
  3. SignIn to Firebase

Rules

  • SignIn/Login is done in the same way.
  • The OTP is only used to get AuthCrendential object
  • AuthCredential 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)

Workflow

  1. User gives the phoneNumber
  2. Firebase sends OTP
  3. SignIn the user
    • If the SIM card with the phoneNumber is not in the device that is currently running the app,
      • We have to first ask the OTP and get AuthCredential object
      • Next we can use that AuthCredential to signIn This method works even if the phoneNumber is in the device
    • Else if user provided SIM phoneNumber is in the device running the app,
      • We can signIn without the OTP.
      • because the verificationCompleted callback from submitPhoneNumber function gives the AuthCredential object which is needed to signIn the user
      • But in the previous case, it ain't called because the SIM is not in the phone.

Functions

  • SubmitPhoneNumber
Future<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 readable
    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 `milliseconds`
      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
  }
  • SubmitOTP
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();
  }
  • SignIn/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());
    }
  }
  • Logout
  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 here.

If you found issues, edits are welcome to this answer and to this repo README

like image 172
Mohith7548 Avatar answered Sep 20 '22 05:09

Mohith7548


Below are the steps:-

  1. Get OTP based on Phone Number:-

    void sendOTP(String phoneNumber, PhoneCodeSent codeSent,
          PhoneVerificationFailed verificationFailed) {
        if (!phoneNumber.contains('+')) phoneNumber = '+91' + phoneNumber;
        _firebaseAuth.verifyPhoneNumber(
            phoneNumber: phoneNumber,
            timeout: Duration(seconds: 30),
            verificationCompleted: null,
            verificationFailed: verificationFailed,
            codeSent: codeSent,
            codeAutoRetrievalTimeout: null);   }
    
  2. Use the codeSent function to retrieve verification_id and pass it to OTP screen

    void codeSent(String verificationId, [int forceResendingToken]) {
    Navigator.push(
        context,
        MaterialPageRoute(
            builder: (context) => Otp(
                  phoneNumber: _phoneNumber,
                  verificationId: verificationId,
                )));
    }
    
  3. Get user based on verification_id and OTP

    Future<bool> verifyOTP(String verificationId, String otp) async {
    AuthCredential credential = PhoneAuthProvider.getCredential(
      verificationId: verificationId,
      smsCode: otp,
    );
    AuthResult result;
    try {
      result = await _firebaseAuth.signInWithCredential(credential);
    } catch (e) {
      // throw e;
      return false;
    }
    print(result);
    (await result.user.getIdToken()).claims.forEach((k, v) {
      print('k= $k and v= $v');
    });
    if (result.user.uid != null) return true;
    return false;
    }
    

For more details watch the below video

https://youtu.be/e5M3EwJJYS4

like image 27
Nipun Madan Avatar answered Sep 20 '22 05:09

Nipun Madan