Login Widget

Show content depending on whether or not the user is logged in. Simply provide two arguments: A Widget to display when logged in, one to display when not. The goal is to make setting up a login page and handling that process much less of a hassle, and I am shaming Google hardcore for not building something like this this for the core framework or the FlutterFire package.

Relies on the firebase_auth and google_sign_in packages. Pull requests are welcome.


The Login widget is meant to simplify the process of stateful content for logged-in / logged-out users, and it was designed to be as easy to use as possible. There are a few static methods (like Login.signInWithGoogle and Login.signInWithEmail) that work out of the box, but you can use any of the login methods provided by FirebaseAuth.instance and easily verify there were no issues with Login.checkUser(FirebaseUser user).

Example usage:

  loggedIn: HomePage(),
  loggedOut: HerculesLoginPage(),

It's recommended to style the generated forms using themes, and contain the root of the app in a Login widget, like so:

  title: 'MyApp',
  theme: MyAppTheme,
  home: Scaffold(
    // Login widget
    body: Login(
      // Homepage for logged-in users
      loggedIn: HomePage(),
      // Login form for logged-out users 
      loggedOut: LoginPage(),
    // recommended to set this to false
    // so user keyboard doesn't trigger resize
    resizeToAvoidBottomInset: false,

Sign in with Google

Inside myLoginForm (or any widget), you could simply call Login.signInWithGoogle() to call the google_sign_in plugin and automatically refresh the page when the user state changes. This is especially helpful for buttons, i.e., inside myLoginForm:

RaisedButton(onPressed: Login.signInWithGoogle, child: Text("Sign in"))  

For this specific case, the work has been done for you, and the package includes a helper widget with the onPressed set to the static method Login.signInWithGoogle.


Effortless. You can initialize this with no arguments, as seen above. (Take notes, Mr. Sneath.) All of the branding guidelines provided by Google have been incorporated into the widget.

enter image description here

The Login Widget will automatically display the relevant content when the login status changes using the FirebaseAuth.instance.onAuthStateChanged listener. In the first example under the Usage section, myHomePage will be shown when the user is logged in, and myLoginForm will be displayed when the user is not logged in.

Easy peeze. Additionally, because each app will (generally) only have one user, there is no harm (and tons of convenience) in exposing the current Firebase user data and login status as static properties (FirebaseUser) Login.currentUser and (bool) Login.isLoggedIn. You can access these at any time anywhere in your code.

Login Fields

There are now standard static TextFields available at Login.email and Login.password. The controller logic is handled by the Login package. Reference these static widgets wherever you want to accept an email or password for logging in, and customize the styling in your app's ThemeData.

Login.signInWithEmail will automatically read the text from its private TextEditingControllers (email and password) for the sign-in process, same with Login.resetPassword. These static TextFields will share the same controllers no matter where they're initialized, which can be an inconvenience but can also be useful - for instance, initializing both a sign-in form and a "forgot password" form with Login.email will mean text is shared across the two fields. A user who types their email to sign in, and then opens the Forgot Password page, will automatically have that text inputted for them - they are, quite literally, the same field.

Before, these functions accepted TextEditingControllers when invoked, but this package is really meant to be as simple to use as possible so those parameters have been removed. Simply place these static widgets somewhere and call Login.signInWithEmail() on a button press to attempt the sign-in.

Automatic Snackbars

Most of the sign-in functions accept a BuildContext context to trigger a relevant Snackbar message. For instance, calling Login.resetPassword(context: context) will show a message saying "Check your email for a password reset link." Failed logins will behave similarly.


Any theming you wish to do can be done in your app's ThemeData, including the email and password TextFields and Snackbars.


There is a callback available at Login.callback, and it receives positional arguments BuildContext context and FirebaseUser user respectively. For example, consider the situation where a LoginPage route is pushed via Navigator.push (say, from a generic "Welcome" page), and we want to schedule it to automatically close when a successful login is processed, i.e., a user signs in with Google or email.

Inside the LoginPage.build definition, e.g., before the return statement:

Login.callback = (context, _) {
	if(Login.isLoggedIn) Navigator.pop(context);

IMPORTANT! If a user is logged in and restarts the app, it will trigger the AuthStateChanged listener almost immediately, so it's important that the callback not be set in, say, the main MaterialApp.build function, or else the first page will load and then get popped off immediately. However, if you define the callback inside the build function for the pushed login form, it will pop the login form off when a successful login is processed, replacing the content below with your loggedIn argument afterward.

To be super explicit, the code above assumes that the build function in which you call it belongs to the login form that is pushed onto the Navigator, and also that this is the only widget that can produce a context which will result in a login. If a user can log in from more than one place in the loggedOut widget, they may open one of them and trigger the build() function, setting the callback to pop the Navigator when the state changes, end up logging in elsewhere, and thus call Navigator.pop() in an unexpected location.

For the general use case - one login location per loggedOut widget - this works well. If you find this section confusing, you can probably safely ignore it unless you run into issues.

Pre-Installation & Debugging

1. Make sure you set up Firebase before using the widget, otherwise FirebaseAuth will not work. For instance, the example included in this package displays the usage and general concept, but cannot actually change state without a google-services file or the necessary configuration. Once Firebase is set up, you can simply depend on the Login package and it will work automatically.

2. Make sure your Firebase project is set up with a support email in Project Settings or you may get backend errors.

3. Make sure you have sign-in methods enabled under Authentication.

4. Check the Callbacks section above if you are having issues with Login.callback.