Categories:
Search articles

Search for articles

Sorry, but we couldn't find any matches...

But perhaps we can interest you in one of our more popular articles?

Flutter web: Firebase Authentication and Google Sign-In

Aug 5, 2020

This article was updated in September 2020. Written by Souvik Biswas

Welcome to the third part of the Flutter web article series. Previously, you learned how to make a Flutter web app responsive, and also how to add animations and dynamic theming support to it.

If you are not familiar with the previous two articles, you can check them out here:

In this article, I will cover a really important topic — authentication for your web app. If you want to create any kind of web app for practical use case, you will definitely need it. In-app authentication is necessary if you want to restrict users based on their different access levels. It also helps to provide more personalized experience to each of them.

In this article, we will mainly look into two types of user authentications:

  • Authentication via email and password
  • Authentication via Google Sign-In

I will be using Firebase Authentication for our purpose, as it is very easy to use with very minimal setup.

You might already be familiar with Firebase Authentication for Flutter mobile apps, but keep reading, because integrating Firebase with Flutter web is a bit different.

Overview

The topics that I am going to cover in this article are as follows:

  • Creating a new Firebase project
  • Configuring Firebase for web
  • Configuring Google Sign-In
  • Integrating Firebase with Flutter:
    • Email and password registration and sign-in
    • Google Sign-In
  • Auto login (as users return back to your web app)

Creating a new Firebase project

You need to create a new Firebase project in order to get access to their services.

  1. Go to Firebase console.

  2. Sign in with your Google account.

  3. Click on Add project.

  4. Enter a Project name and click Continue.

  5. Turn off Google Analytics for this project and click Create project.

  6. Wait for the creation process to complete and then click Continue.

  7. This will lead you to the Project Overview page. From here, you will be able to set up Firebase for your web app.

Configuring Firebase for web

Your new Firebase project is created and you can proceed to set up Firebase for your web app.

  1. Select Web on the Project Overview page (notice the icon I've circled in red).

  2. Choose a nickname for your app (App nickname) and click on Register app.

  3. Copy the script.

  4. Navigate to root project directory –> web –> index.html and paste the script into the body tag before your main.dart.js script.

    <!DOCTYPE html>
    <html>
      <!-- ... -->
      <body>
        <!-- ... -->
    
        <!-- ADD THIS BEFORE YOUR main.dart.js SCRIPT -->
    
        <!-- The core Firebase JS SDK (always required for using any firebase service) -->
        <script src="https://www.gstatic.com/firebasejs/7.5.0/firebase-app.js"></script>
        <!-- Firebase Auth SDK -->
        <script src="https://www.gstatic.com/firebasejs/7.5.0/firebase-auth.js"></script>
        <script>
          // Your web app's Firebase configuration
          var firebaseConfig = {
            apiKey: "...",
            authDomain: "...",
            databaseURL: "...",
            projectId: "...",
            storageBucket: "...",
            messagingSenderId: "...",
            appId: "...",
          };
          // Initialize Firebase
          firebase.initializeApp(firebaseConfig);
        </script>
        <!-- END OF FIREBASE INIT CODE -->
    
        <script src="main.dart.js" type="application/javascript"></script>
      </body>
    </html>
    
  5. Click Continue to console.

  6. Go to your project settings.

  7. Under the General tab, select your Support email.

We will also be using Google Sign-In in our project, so let's complete the setup for that as well. If you do not want to integrate Google Sign-In with your project, you can skip the next part.

Configuring Google Sign-In

You will be requiring OAuth client ID in order to use Google Sign-In with your web app.

  1. Go to the Credentials page.

  2. Make sure that the correct project is selected and click on CREATE CREDENTIALS.

  3. Select OAuth client ID from the list.

  4. Select Web application from the Application type dropdown.

  5. Enter a name for your OAuth client and click on CREATE.

  6. Copy the generated Client ID.

  7. Navigate to root project directory –> web –> index.html and add the following meta tag, somewhere in the head of the document:

    <meta name="google-signin-client_id" content="YOUR_GOOGLE_SIGN_IN_OAUTH_CLIENT_ID.apps.googleusercontent.com">
    

    Replace YOUR_GOOGLE_SIGN_IN_OAUTH_CLIENT_ID with your Client ID.

For this client to work correctly, you will need to configure the Authorized JavaScript origins, which identify the domains from which your application can send API requests. When in local development, this is normally localhost and some port.

Follow the steps below:

  1. Go to the Credentials page.

  2. Click Edit in the OAuth Web application client that you just created.

  3. Click on Add URI.

  4. Enter a localhost port, like this:

  5. Click Save.

By default, flutter run starts in a random port. If you need to deal with authentication like the above, you will have to use that specific port which is added to the Authorized JavaScript origins list.

You can use the following command to listen to that specific port:

flutter run -d chrome --web-hostname localhost --web-port 7357

Integrating Firebase Authentication into Flutter web

  • Add the firebase_core & firebase_auth plugin to your pubspec.yaml file.

    The web implementation of these plugins, i.e. firebase_core_web & firebase_auth_web is automatically added to your dependencies.

    dependencies:
      firebase_core: ^0.5.0
      firebase_auth: ^0.18.0+1
    
  • Create a new Dart file called authentication.dart in the path lib/utils.

  • Import the packages:

    import 'package:firebase_core/firebase_core.dart';
    import 'package:firebase_auth/firebase_auth.dart';
    
  • Create an instance of FirebaseAuth and add a few variables that we will use later:

    final FirebaseAuth _auth = FirebaseAuth.instance;
      
    bool authSignedIn;
    String uid;
    String userEmail;
    

Authenticating using email and password

You will need to register the user first using email and password, and then they can login using the proper credentials.

For registering a new user, you can use the method createUserWithEmailAndPassword provided by FirebaseAuth.

We will define a new function called registerWithEmailPassword that will handle the whole registration process of a new user. This function will contain two parameters, an email and a password, which will be used to authenticate the user.

Future<String> registerWithEmailPassword(String email, String password) async {
  // Initialize Firebase
  await Firebase.initializeApp();

  final UserCredential userCredential = await _auth.createUserWithEmailAndPassword(
    email: email,
    password: password,
  );

  final User user = userCredential.user;

  if (user != null) {
    // checking if uid or email is null
    assert(user.uid != null);
    assert(user.email != null);

    uid = user.uid;
    userEmail = user.email;

    assert(!user.isAnonymous);
    assert(await user.getIdToken() != null);

    return 'Successfully registered, User UID: ${user.uid}';
  }

  return null;
}

After an user is successfully registered, they can login using their correct credentials. You can use the method signInWithEmailAndPassword provided by FirebaseAuth to authenticate the login process.

We will define another function called signInWithEmailPassword for handling the login process.

Future<String> signInWithEmailPassword(String email, String password) async {
  // Initialize Firebase
  await Firebase.initializeApp();

  final UserCredential userCredential = await _auth.signInWithEmailAndPassword(
    email: email,
    password: password,
  );

  final User user = userCredential.user;

  if (user != null) {
    // checking if uid or email is null
    assert(user.uid != null);
    assert(user.email != null);

    uid = user.uid;
    userEmail = user.email;

    assert(!user.isAnonymous);
    assert(await user.getIdToken() != null);

    final User currentUser = _auth.currentUser;
    assert(user.uid == currentUser.uid);

    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setBool('auth', true);

    return 'Successfully logged in, User UID: ${user.uid}';
  }

  return null;
}

Shared Preferences is used for caching the login status. This will be helpful while we set up auto login in our web app.

Let's also define a handy function for signing out of an account.

Future<String> signOut() async {
  await _auth.signOut();

  SharedPreferences prefs = await SharedPreferences.getInstance();
  prefs.setBool('auth', false);

  uid = null;
  userEmail = null;

  return 'User signed out';
}

In order to use email and password authentication from your Flutter web app, you will have to enable it in the Firebase Authentication settings.

  • Open your project page on Firebase.

  • Go to Authentication from the left side menu and under Users tab click on Set up sign-in method.

  • Go to Sign-in method tab and enable Email/Password from the Sign-in providers list.

  • Click Save.

Authenticating using Google Sign-In

  • Add the google_sign_in plugin to your pubspec.yaml file.

    The web implementation of this plugin, i.e. google_sign_in_web is automatically added to your dependencies.

    dependencies:
      google_sign_in: ^4.5.3
    
  • Import the package in your authentication.dart file:

    import 'package:google_sign_in/google_sign_in.dart';
    
  • Create an instance of GoogleSignIn and add a few more variables:

    final GoogleSignIn googleSignIn = GoogleSignIn();
      
    String name;
    String imageUrl;
    
  • Define a new function called signInWithGoogle, which we will use to handle the Google Sign-In process:

    Future<String> signInWithGoogle() async {
      // Initialize Firebase
      await Firebase.initializeApp();
      
      final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
      final GoogleSignInAuthentication googleSignInAuthentication = await googleSignInAccount.authentication;
      
      final AuthCredential credential = GoogleAuthProvider.credential(
        accessToken: googleSignInAuthentication.accessToken,
        idToken: googleSignInAuthentication.idToken,
      );
      
      final UserCredential userCredential = await _auth.signInWithCredential(credential);
      final User user = userCredential.user;
      
      if (user != null) {
        // Checking if email and name is null
        assert(user.uid != null);
        assert(user.email != null);
        assert(user.displayName != null);
        assert(user.photoURL != null);
      
        uid = user.uid;
        name = user.displayName;
        userEmail = user.email;
        imageUrl = user.photoURL;
      
        assert(!user.isAnonymous);
        assert(await user.getIdToken() != null);
      
        final User currentUser = _auth.currentUser;
        assert(user.uid == currentUser.uid);
      
        SharedPreferences prefs = await SharedPreferences.getInstance();
        prefs.setBool('auth', true);
      
        return 'Google sign in successful, User UID: ${user.uid}';
      }
      
      return null;
    }
    
  • Next, define a handy function for signing out of Google:

    void signOutGoogle() async {
      await googleSignIn.signOut();
      await _auth.signOut();
      
      SharedPreferences prefs = await SharedPreferences.getInstance();
      prefs.setBool('auth', false);
      
      uid = null;
      name = null;
      userEmail = null;
      imageUrl = null;
      
      print("User signed out of Google account");
    }
    

In order to authenticate using Google Sign-In from your Flutter web app, you will have to enable it in the Firebase Authentication settings.

  • Open your project page on Firebase.

  • Go to Authentication –> Sign-in method.

  • Enable Google from the Sign-in providers list, and enter a project name.

  • Click Save.

We have successfully configured both types of authentication for our web app and also defined all the functions required for handling user registration and login.

Now, we can move on and integrate them with the UI of our Flutter web app.

Building the AuthDialog UI

We will be showing a dialog-box for the authentication UI. Users can either login using email and password or using Google Sign-In.

Create a new file called auth_dialog.dart in the path lib/widgets, and inside it define a StatefulWidget called AuthDialog. It will mainly consist of two TextField widgets, Log in and Sign up buttons, and a button for using Google Sign-In.

// The basic skeleton structure of the widget

class AuthDialog extends StatefulWidget {
  @override
  _AuthDialogState createState() => _AuthDialogState();
}

class _AuthDialogState extends State<AuthDialog> {
  @override
  Widget build(BuildContext context) {
    return Dialog(
      // ...
      child: SingleChildScrollView(
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Container(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisSize: MainAxisSize.min,
              children: [
                Text('Email address'),
                TextField(hintText: "Email"),
                Text('Password'),
                TextField(hintText: "Password"),
                Row(
                  mainAxisSize: MainAxisSize.max,
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: [
                    Flexible(
                      flex: 1,
                      child: Container(
                        width: double.maxFinite,
                        child: FlatButton(
                          onPressed: () {},
                          child: Text(
                            'Log in',
                            style: TextStyle(fontSize: 14, color: Colors.white),
                          ),
                        ),
                      ),
                    ),
                    Flexible(
                      flex: 1,
                      child: Container(
                        width: double.maxFinite,
                        child: FlatButton(
                          onPressed: () {},
                          child: Text(
                            'Sign up',
                            style: TextStyle(fontSize: 14, color: Colors.white),
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
                Center(child: GoogleButton()),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Email and password TextField(s)

Let's take a better look at the TextField widgets. Here, I am showing only the email text field, you can define the password text field in a similar manner.

  • Define a TextEditingController, FocusNode and a boolean to track whether the text field is being used.

    TextEditingController textControllerEmail;
    FocusNode textFocusNodeEmail;
    bool _isEditingEmail = false;
    
  • Initialize them:

    @override
    void initState() {
      textControllerEmail = TextEditingController();
      textControllerEmail.text = null;
      textFocusNodeEmail = FocusNode();
    
      super.initState();
    }
    
  • Define a method to validate an email address:

    String _validateEmail(String value) {
      value = value.trim();
    
      if (textControllerEmail.text != null) {
        if (value.isEmpty) {
          return 'Email can\'t be empty';
        } else if (!value.contains(RegExp(
            r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+"))) {
          return 'Enter a correct email address';
        }
      }
    
      return null;
    }
    
  • The email TextField widget should look like this:

    TextField(
      focusNode: textFocusNodeEmail,
      keyboardType: TextInputType.emailAddress,
      textInputAction: TextInputAction.next,
      controller: textControllerEmail,
      autofocus: false,
      onChanged: (value) {
        setState(() {
          _isEditingEmail = true;
        });
      },
      onSubmitted: (value) {
        textFocusNodeEmail.unfocus();
        FocusScope.of(context).requestFocus(textFocusNodePassword);
      },
      style: TextStyle(color: Colors.black),
      decoration: InputDecoration(
        border: new OutlineInputBorder(
          borderRadius: BorderRadius.circular(10),
          borderSide: BorderSide(
            color: Colors.blueGrey[800],
            width: 3,
          ),
        ),
        filled: true,
        hintStyle: new TextStyle(
          color: Colors.blueGrey[300],
        ),
        hintText: "Email",
        fillColor: Colors.white,
        errorText: _isEditingEmail
            ? _validateEmail(textControllerEmail.text)
            : null,
        errorStyle: TextStyle(
          fontSize: 12,
          color: Colors.redAccent,
        ),
      ),
    ),  
    

Log in and Sign up buttons

The following is the code for the Log in button, which invokes the function registerWithEmailPassword that we defined earlier.

FlatButton(
  color: Colors.blueGrey[800],
  hoverColor: Colors.blueGrey[900],
  highlightColor: Colors.black,
  onPressed: () async {
    if (_validateEmail(textControllerEmail.text) == null && _validatePassword(textControllerPassword.text) == null) {
      setState(() {
        _isRegistering = true;
      });
      await registerWithEmailPassword(textControllerEmail.text, textControllerPassword.text)
          .then((result) {
        print(result);
      }).catchError((error) {
        print('Registration Error: $error');
      });
    }
    setState(() {
      _isRegistering = false;
      _isEditingEmail = false;
    });
  },
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.circular(15),
  ),
  child: Padding(
    padding: EdgeInsets.only(top: 15.0, bottom: 15.0),
    child: _isRegistering
        ? SizedBox(
            height: 16,
            width: 16,
            child: CircularProgressIndicator(
              strokeWidth: 2,
              valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
            ),
          )
        : Text(
            'Sign up',
            style: TextStyle(fontSize: 14, color: Colors.white),
          ),
  ),
)

The UI code for the Sign up button will be similar to this. The main difference is that in that case, you have to invoke the function signInWithEmailPassword.

Google Sign-In button

You will need an image to design the Google Sign-In button. Download it from here.

Add it in the path assets/images and import it using the pubspec.yaml file:

flutter:
  assets:
    - assets/images/

The UI code for the button is as follows:

class GoogleButton extends StatefulWidget {
  @override
  _GoogleButtonState createState() => _GoogleButtonState();
}

class _GoogleButtonState extends State<GoogleButton> {
  bool _isProcessing = false;

  @override
  Widget build(BuildContext context) {
    return DecoratedBox(
      decoration: ShapeDecoration(
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(20),
          side: BorderSide(color: Colors.blueGrey, width: 3),
        ),
        color: Colors.white,
      ),
      child: OutlineButton(
        highlightColor: Colors.blueGrey[100],
        splashColor: Colors.blueGrey[200],
        onPressed: () async {
          setState(() {
            _isProcessing = true;
          });
          await signInWithGoogle().then((result) {
            print(result);
            Navigator.of(context).pop();
            Navigator.of(context).pushReplacement(
              MaterialPageRoute(
                fullscreenDialog: true,
                builder: (context) => HomePage(),
              ),
            );
          }).catchError((error) {
            print('Registration Error: $error');
          });
          setState(() {
            _isProcessing = false;
          });
        },
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(20),
          side: BorderSide(color: Colors.blueGrey, width: 3),
        ),
        highlightElevation: 0,
        // borderSide: BorderSide(color: Colors.blueGrey, width: 3),
        child: Padding(
          padding: const EdgeInsets.fromLTRB(0, 10, 0, 10),
          child: _isProcessing
              ? CircularProgressIndicator(
                  valueColor: new AlwaysStoppedAnimation<Color>(
                    Colors.blueGrey,
                  ),
                )
              : Row(
                  mainAxisSize: MainAxisSize.min,
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Image(
                      image: AssetImage("assets/images/google_logo.png"),
                      height: 30.0,
                    ),
                    Padding(
                      padding: const EdgeInsets.only(left: 20),
                      child: Text(
                        'Continue with Google',
                        style: TextStyle(
                          fontSize: 20,
                          color: Colors.blueGrey,
                        ),
                      ),
                    )
                  ],
                ),
        ),
      ),
    );
  }
}

Updating the HomePage UI

We have to make changes in two places for integrating the AuthDialog widget, that is in the top bar (for large screens) and the drawer (for small screens).

To show the dialog box, make a call to the showDialog method from the onTap of the Sign in button.

InkWell(
  onTap: userEmail == null
      ? () {
          showDialog(
            context: context,
            builder: (context) => AuthDialog(),
          );
        }
      : null,

  // ...
)

Update the child of the InkWell to show the Sign in button only when the user is not signed in already, otherwise display the user profile picture (if present), user email / name and a Sign out button.

If the user is logged in, the userEmail will be non-null, irrespective to the authentication method.

// Code for the Sign in button, present in the top bar

InkWell(
  child: userEmail == null
      ? Text(
          'Sign in',
          style: TextStyle(
            color: _isHovering[3] ? Colors.white : Colors.white70,
          ),
        )
      : Row(
          children: [
            CircleAvatar(
              radius: 15,
              backgroundImage: imageUrl != null
                  ? NetworkImage(imageUrl)
                  : null,
              child: imageUrl == null
                  ? Icon(Icons.account_circle, size: 30)
                  : Container(),
            ),
            Text(
              name ?? userEmail,
              style: TextStyle(
                color: _isHovering[3]
                    ? Colors.white
                    : Colors.white70,
              ),
            ),
            FlatButton(
              // ...
              onPressed: () {},
              child: Text(
                'Sign out',
                style: TextStyle(
                  fontSize: 14,
                  color: Colors.white,
                ),
              ),
            ),
          ],
        ),
),

The full code for the Sign out button is as follows:

FlatButton(
  color: Colors.blueGrey,
  hoverColor: Colors.blueGrey[700],
  highlightColor: Colors.blueGrey[800],
  onPressed: _isProcessing
      ? null
      : () async {
          setState(() {
            _isProcessing = true;
          });
          await signOut().then((result) {
            print(result);
            Navigator.of(context).pushReplacement(
              MaterialPageRoute(
                fullscreenDialog: true,
                builder: (context) => HomePage(),
              ),
            );
          }).catchError((error) {
            print('Sign Out Error: $error');
          });
          setState(() {
            _isProcessing = false;
          });
        },
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.circular(15),
  ),
  child: Padding(
    padding: EdgeInsets.only(
      top: 8.0,
      bottom: 8.0,
    ),
    child: _isProcessing
        ? CircularProgressIndicator()
        : Text(
            'Sign out',
            style: TextStyle(
              fontSize: 14,
              color: Colors.white,
            ),
          ),
  ),
)

You have to make similar code changes to the Drawer (which is displayed only on small screens).

The code changes for the Drawer are available here.

Auto login

In order to prevent the situation where users have to log in every time they come back to your web app or reload the web page, you can cache their login status and auto-login as they come back to your web app.

  • Define a new function in the authentication.dart file, called getUser to retrieve the user information if they had already logged in previously:

    Future getUser() async {
      // Initialize Firebase
      await Firebase.initializeApp();
      
      SharedPreferences prefs = await SharedPreferences.getInstance();
      bool authSignedIn = prefs.getBool('auth') ?? false;
      
      final User user = _auth.currentUser;
      
      if (authSignedIn == true) {
        if (user != null) {
          uid = user.uid;
          name = user.displayName;
          userEmail = user.email;
          imageUrl = user.photoURL;
        }
      }
    }
    
  • Create the MyApp, defined in main.dart file, a StatefulWidget and define a method called getUserInfo to invoke the getUser function:

    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => _MyAppState();
    }
      
    class _MyAppState extends State<MyApp> {
      Future getUserInfo() async {
        await getUser();
        setState(() {});
        print(uid);
      }
      
      @override
      Widget build(BuildContext context) {
        // ...
      }
    }
    
  • Call it from the initState method:

    class _MyAppState extends State<MyApp> {
      @override
      void initState() {
        getUserInfo();
        super.initState();
      }
      // ...
    }
    

Running the web app

You can run the Flutter web app normally from the IDE or using the terminal with the command:

flutter run -d chrome

This runs your web app in debug mode using any random port. As I mentioned before, when configuring Google Sign-In, you have to run it on a specific port that you have added to the Authorized JavaScript origins list in your Google Sign-In OAuth client in the Credentials page. You can use the following command:

flutter run -d chrome --web-hostname localhost --web-port 7357

If you are running from VS Code, you can also add a configuration (in the file .vscode/launch.json) to run the app on port 7357 by default.

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Flutter Web (port 7357)",
            "request": "launch",
            "type": "dart",
            "args": ["--web-port", "7357"]
        }
    ]
}

But this does not run it on your default Chrome browser. So, if you try to use Google Sign-In here, you will get the following message:

To use Google Sign-In, copy the link of the localhost port on which your app is currently running, and open it from the default Chrome browser. Now you will be able to sign in without any problem.

Although you can access the Google Sign-In here, you will not be able to use hot reload/hot restart in this window. Also, you won't be able to see any debug messages on your IDE console or terminal.

The only way to see the debug messages is by going in the Inspect mode of the Chrome browser and then selecting the Console tab.

There is already an issue open on GitHub regarding this, you can follow it here.

Build and deploy using Codemagic

You can build and host your Flutter Web projects directly to a custom subdomain of codemagic.app without any extra cost using Codemagic Static Pages.

  • Go to your project settings on Codemagic:

  • Under the Build tab, set the Flutter version to channel Beta and check-mark the Web platform

  • If you want to deploy your web app using Codemagic, then go to Codemagic Static Pages under Publish tab. Check-mark Enable Codemagic Static Page publishing and specify your subdomain.

Now, you can start building your project.

After a successful build, you can access the web app by going to your specified link.

Just more thing before we wrap. If you try to use Google Sign-In by going to the codemagic.app subdomain, nothing will pop-up. To fix this go to Credentials on the GCP console.

  • First of all, enter the editing mode of Explore client.

  • Add the new Codemagic domain under URIs.

  • Go to Web client.

  • Add the Codemagic domain under URIs and the same domain with __/auth/handler under Authorized redirect URIs.

Now, you will be able to access Google Sign-In from the page deployed using Codemagic.

Conclusion

You have successfully implemented Firebase Authentication and Google Sign-In to your Flutter web app and deployed it using Codemagic. This article covers the basics of Firebase Authentication using the two most popular authentication methods (email/password and Google Sign-In), but Firebase provides authentication using a lot of other identity providers as well.


Souvik Biswas is a passionate Mobile App Developer (Android and Flutter). He has worked on a number of mobile apps throughout his journey. Loves open source contribution on GitHub. He is currently pursuing a B.Tech degree in Computer Science and Engineering from Indian Institute of Information Technology Kalyani. He also writes Flutter articles on Medium - Flutter Community.

How did you like this article?

Oops, your feedback wasn't sent

Latest articles

Show more posts