Shruti Ramnandan Sharma
Shruti Ramnandan Sharma

Reputation: 4545

How to check user is logged in or not with phone authentication using firebase in flutter?

Here, I'm authenticated through the phone number with OTP code using firebase but after login succeeded, it navigated through home page but when I click on back it drags me login Screen.

here, the code I have tried, but it doesn't work

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


  void isSignedIn() async {
    this.setState(() {
      isLoading = true;
    });

  firebaseAuth.currentUser().then((user){
    if(user !=null){
      Navigator.of(context).pushReplacementNamed('/homepage');
    }else{
       verifyPhone();
    }
  });
  this.setState(() {
    isLoading = false;
  });

  }

Method for getting OTP code

Future<void> verifyPhone()async{
    final PhoneCodeAutoRetrievalTimeout autoRetrieval=(String verId){
      this.verificationId=verId;
    };

    final PhoneCodeSent smsCodeSent=(String verId, [int forceCodeResend]){
      this.verificationId=verId;
      smsCodeDialog(context).then((value){
        print("Signed in");
      });
    };



    final PhoneVerificationCompleted verificationCompleted = (AuthCredential credential) {
     print("verified");
   };

    final PhoneVerificationFailed verfifailed=(AuthException exception){
      print("${exception.message}");
    };

    await firebaseAuth.verifyPhoneNumber(
     phoneNumber: this.phoneNo,
     codeAutoRetrievalTimeout: autoRetrieval,
     codeSent: smsCodeSent,
     timeout: const Duration(seconds: 10),
     verificationCompleted: verificationCompleted,
     verificationFailed: verfifailed
    );
  }

here the dialog box for sign in with OTP code

Future<bool> smsCodeDialog(BuildContext context){
    return showDialog(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context){
        return new AlertDialog(
          title: Text('Enter sms Code'),
          content: TextField(
            onChanged: (value){
              this.smsCode=value;
            },
          ),
          contentPadding: const EdgeInsets.all(10.0),
          actions: <Widget>[
            new FlatButton(
              child: Text("Done"),
              onPressed: (){
                firebaseAuth.currentUser().then((user){
                  if(user !=null){
                    Navigator.of(context).pop();
                    Navigator.of(context).pushReplacementNamed('/homepage');
                  }else{
                    Navigator.of(context).pop();
                    signIn();
                  }
                });
              },
            )
          ],
        );
      }
    );
  }

method for Sign in with phone number

signIn()async{
    AuthCredential credential= PhoneAuthProvider.getCredential(
      verificationId: verificationId,
      smsCode: smsCode
    );
    await  firebaseAuth.signInWithCredential(credential).then((user){
       Navigator.of(context).pushReplacementNamed('/homepage');
         print('signed in with phone number successful: user -> $user');
    }).catchError((onError){
      print(onError);
    });
  }
`

Upvotes: 1

Views: 3216

Answers (2)

Mahmoud Abu Alheja
Mahmoud Abu Alheja

Reputation: 3658

Use method below by pass verificationID come from API firebase when code sent and code enter by user, so if method return FirebaseUser the code is correct if return null the code enter by user is not correct

Future<FirebaseUser> getUserFromCodePhone(String code, String verificationID) async {
    FirebaseAuth mAuth = FirebaseAuth.instance;

    AuthCredential phoneAuthCredential = PhoneAuthProvider.getCredential(
        verificationId: verificationID, smsCode: code);
    try {
      AuthResult result = await mAuth.signInWithCredential(phoneAuthCredential);

      FirebaseUser currentUser = await mAuth.currentUser();
      if (currentUser != null && result.user.uid == currentUser.uid) {
        return currentUser;
      } else {
        return null;
      }
    } on PlatformException catch (_) {}

    return null;
  }

How it work ? : when use signInWithCredential method if code passed to AuthCredential is false then the method will throw PlatformException so out from try block and return null

Upvotes: 0

Shady Boshra
Shady Boshra

Reputation: 2911

Welcome Shruti Ramnandan Sharma in Stackoverflow and Flutter dev.

Your code seems to working fine with me, I coded for you a one page dart that can test you the whole code with fixing your problem with going back to Login or VerifyPhone page.

Note: I changed your order of code in verifyPhone() method.

And Changed Navigator.of(context).pushReplacementNamed('/homepage'); to

Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => HomeRoute()));

The whole code here

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';

void main() => runApp(VerifyPhoneRoute());

class VerifyPhoneRoute extends StatefulWidget {
  @override
  _VerifyPhoneRouteState createState() {
    return _VerifyPhoneRouteState();
  }
}

class _VerifyPhoneRouteState extends State<VerifyPhoneRoute> {
  bool isLoading = false;
  FirebaseAuth firebaseAuth = FirebaseAuth.instance;
  String verificationId;
  String phoneNo = "Your number here";
  String smsCode;

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

  void isSignedIn() async {
    this.setState(() {
      isLoading = true;
    });

    firebaseAuth.currentUser().then((user) {
      if (user != null) {
        Navigator.pushReplacement(
          context,
          MaterialPageRoute(builder: (context) => HomeRoute()),
        );
      } else {
        verifyPhone();
      }
    });
    this.setState(() {
      isLoading = false;
    });
  }

  Future<void> verifyPhone() async {
    final PhoneVerificationCompleted verificationCompleted =
        (AuthCredential credential) {
      print("verified");
    };

    final PhoneVerificationFailed verifyFailed = (AuthException exception) {
      print("${exception.message}");
    };

    final PhoneCodeSent smsCodeSent = (String verId, [int forceCodeResend]) {
      this.verificationId = verId;
      smsCodeDialog(context).then((value) {
        print("Signed in");
      });
    };

    final PhoneCodeAutoRetrievalTimeout autoRetrieval = (String verId) {
      this.verificationId = verId;
    };

    await firebaseAuth.verifyPhoneNumber(
        phoneNumber: this.phoneNo,
        codeAutoRetrievalTimeout: autoRetrieval,
        codeSent: smsCodeSent,
        timeout: const Duration(seconds: 10),
        verificationCompleted: verificationCompleted,
        verificationFailed: verifyFailed);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter Inapp Plugin by dooboolab'),
        ),
        body: Center(
          child: RaisedButton(
              child: Text("Verify"),
              onPressed: () {
                verifyPhone();
              }),
        ),
      ),
    );
  }

  Future<bool> smsCodeDialog(BuildContext context) {
    return showDialog(
        context: context,
        barrierDismissible: false,
        builder: (BuildContext context) {
          return new AlertDialog(
            title: Text('Enter sms Code'),
            content: TextField(
              onChanged: (value) {
                this.smsCode = value;
              },
            ),
            contentPadding: const EdgeInsets.all(10.0),
            actions: <Widget>[
              new FlatButton(
                child: Text("Done"),
                onPressed: () {
                  firebaseAuth.currentUser().then((user) {
                    if (user != null) {
                      Navigator.of(context).pop();
                      Navigator.pushReplacement(
                        context,
                        MaterialPageRoute(builder: (context) => HomeRoute()),
                      );
                    } else {
                      Navigator.of(context).pop();
                      signIn();
                    }
                  });
                },
              )
            ],
          );
        });
  }

  signIn() async {
    AuthCredential credential = PhoneAuthProvider.getCredential(
        verificationId: verificationId, smsCode: smsCode);
    await firebaseAuth.signInWithCredential(credential).then((user) {
      Navigator.pushReplacement(
        context,
        MaterialPageRoute(builder: (context) => HomeRoute()),
      );
      print('signed in with phone number successful: user -> $user');
    }).catchError((onError) {
      print(onError);
    });
  }
}

class HomeRoute extends StatefulWidget {
  @override
  _HomeRouteState createState() {
    return _HomeRouteState();
  }
}

class _HomeRouteState extends State<HomeRoute> {
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter Inapp Plugin by dooboolab'),
        ),
        body: Center(
          child: Text("Welcome There."),
        ),
      ),
    );
  }
}

This code works fine with me. So if there's any problem happened with you again, don't be hesitate to comment on this answer. And if this answered your question and solve your problem, please make it as answer.

Upvotes: 3

Related Questions