Logging in using the Auth library package
Authentication is a common task put to mobile apps — making it an ideal candidate for a class library. A class library would execute the task in a formalized and standardized fashion — making authenticating a breeze. I use such a class library for my own apps in the form of the Dart package, Auth. I will use example code to demonstrate this package. This example code can be viewed in the Dart package’s example tab. I’ll then follow up with the traditional ‘walkthrough’ the class library in nice ‘easy to read’ screenshots.
Ironically, it’s better to read this article about mobile development on your computer than on your phone. Besides, we program mostly on our computers; not on our phones. For now.
Before you do anything, you gotta set up Firebase. I’m not going to instruct you this step-by-step as it’s beyond the scope of this article. You can do that on your own. I will, however, throw up some screenshots giving you hints on what you need to do and what you’ll likely see on your screen if you try to get ahead of yourself and run this library package.
Note, most of the screenshots will have a corresponding gist or Github entry in their captions. You can go to these entries for easy copy and paste for example. I personally find gists hard on the eyes, and I don’t like using them in my articles. However, if you must look at those ugly things. You’ve got that option either by clicking on the screenshots’ caption or the screenshots themselves.
Another point I should mention here. As it is, I’m Android
I’m originally an Android developer, not iOS, and so this next section applies more so to Android developers. I apologize to you iOS folk. Please, for you, how about we just skip this part and go to the rest of the article?
Now, as for the rest of you, maybe open up this website, Add Firebase to Your Android Project, as a supplement to help you set up Firebase as I’m going to describe this stuff in brief. Under the directory, android , add the following two dependencies to the build.gradle file.
It’s important now to also add the following to the bottom of the second build.gradle file. This file is found under the directory: android/app
You may encounter the follow error if you then try the class library. There’s a minimum version requirement it would seem, and you’ll need to go under the ‘wrapper’ directory and update your g_radle-wrapper.properties_ file. For example, change the file entry, gradle-4.4-all.zip to gradle-_5.1.1-all.zip_.
The next error you might encounter involves a json file. An example of the error is listed below, and it’s complaining the json file is missing. You’ll need to go to Firebase (keeping the package name of your sample app in mind) and make a google-services.json configuration file: Your Firebase Projects
Along with that configuration file, you’ll likely need to get the SHA1 number for your app. Turn to this website to get just that, Authenticating Your Client. And so, after all that. You’re ready to run the sample app and log onto Firebase.
With Firebase all set up, let’s go ahead and run that sample app and see what it does. As a rule, I run such things right from Android Studio using an emulator.
There you are. When it’s all ready, and you run the app, you’ll be greeted with the ‘sign in’ buttons. Now, unlike most of my library packages, this one works with not one but two plugins: firebase_auth and google_sign_in. And so, if you’ve a Google Gmail account, you’ve the means to log into the app using that account. For example, click “Google Sign In” button as its presented above, and the app will prompt you to log in using your Google account.
What follows are the screenshots of the process:
The last screenshot above is interesting because the app has (using the class library’s ‘scopes’ parameter) requested access to the user’s contacts. Despite clicking on the button, allow, I myself got a 403 response (PERMISSION DENIED), and so none of my contacts get accessed. I suspect, one would have to go under their developer console and enable such permissions, but I’m not going to do that frankly. Knowing it worked is good enough for now. The screenshot below depicts the class library using its ‘scopes’ parameter requesting access to the user’s contact information as well as email info.
After successfully logging in, you can tap on the ‘Results’ tab to view some of the many properties you then have privy to through the Auth object. These properties will be presented a little later on.
It’s in the function, initState (), in the example app where the ‘sign in’ is attempted. There is some eight different functions in this class library used for signing in. For example, in the screenshot below, the function, signInSilently (), is used to allow the user to sign in automatically through their Google account without involving the user if they’ve already done so in the past. If so, the app will sign in silently then and there. The named parameter, listen, will then fire when successfully signed in using Google.
Again, you see in the init () function, I’m requesting access to the user’s contacts. However, note the second named parameter, listener, supplies an anonymous function to be triggered when the user successfully logs in using instead Firebase and not Google. And so, with two different plugins, there’s two different event handlers involved. One named, listen; the other listener.
Lastly, in the screenshot above, like any good class library, it cleans up after itself when the app terminates by calling its function, dispose (), in the State object’s own dispose () function.
When the user successfully signs in using Google, again, that anonymous function assigned to the named parameter, listen, is triggered. There, the variable, loggedIn, is assigned a boolean value depending on whether the variable, account, is null or not. See above.
The variable, account, by the way is of type, GoogleSignInAccount, and when signed in successfully contains the user’s Google account information_._ Notice above the function, setState (), is called next. This will cause the State object’s build () to be called and consequently the function, _buildBody (), to be executed. As you see in the code below, if the variable, loggedIn, is set to true, then that will display the user’s name and email address on the screen.
Below, you’ll see I’ve changed things up a little bit. The init () function has been modified to now supply the two ‘event handlers’ parameters leaving the ‘sign in’ function to be called without any parameters. This demonstrates how the class library allows one to call signInSilently () elsewhere (anywhere the developer wants) leaving the init () function in the initState () to initialize.
Looking again at the two the named parameters: listener and listen. The distinction between them are their parameter values. The function, listen, is used to log in with Google and is passed the parameter of class type, GoogleSignInAccount. The function, listener, is used to login with Firebase and is passed the parameter of class type, FirebaseUser. You can see this below with a screenshot of the Auth class and its named constructor, Auth.init ().
For brevity, the code demonstrating this class library is all being presented in one place — in the initState () function — but it doesn’t have to all be done in the initState () function of course. Pretend, for example, you’ve an app that sets the authentication scope in one place, and the ‘event handler’ options in another place, or (as you’ll see later) sets authentication listeners more than once in many different places in the code. You’ve the option to do this using the class library’s setters.
Let’s begin our walkthrough the class library itself. Look at the parameter list below. What do you see? You see the every same ‘named parameters’ you would see if you were using the plugins separately…only here they’re combined. Because they’re named parameters, they’re all optional, but once this function is called, you know one thing: Both instances those plugins have been created. They’re created and stored in the respective static variable highlighted below. Note, the class library itself is also stored in a static variable, _this, because this class uses a factory constructor.
The dispose () function is listed next, and is to be called in a State object’s corresponding dispose () function. In other words, it’s called when your app is terminating. This function cleans things up by signing out and clearing from memory a number of ‘heavy’ variables — that take up much valuable memory.
What then follows is the two Stream Subscriptions implemented ‘to catch’ any and all authentication events that occur when logging in or logging out for example. It’s then the library-private function, _init (), a named constructor which is called by the factory constructor to indeed initialize the two plugins to the static variables, _fireBaseAuth and _googleSignIn. You can see the ‘Google’ plugin initialized right there in the function while the ‘Firebase’ plugin is actually initialized further on in the function, _initFirebase ().
In fact, the function, _initFireBase (), is the next stretch of code listed in the class library. There, the Firebase plugin is initialized and referenced in the variable, _fireBaseAuth. Note, a reference to the plugin is also assigned to an instance variable, _fbAuth, making it publicly available through a_ getter._
When an instance of the plugin, FirebaseAuth, is created, it is assigned the listener function, \ _listFireBaseListeners. The List variable, __ fireBaseListeners_, is then used to store one or more functions that can to be fired if an ‘authentication change’ occurs. For example, when a user of type FirebaseUser logs in and or logs out. There is the function, fireBaseListener, and the setter, listener, giving two ways to assign any number of ‘listeners’ to the class library.
What follows next is the function, _ initListen (), and, as you’ve seen above, is called in the _ init () function. Four parameters are passed into this function — to be then passed into the GoogleSignIn’s ‘listener.’
Note, the first parameter, listen, is passed on indirectly to the listener. It’s added first to the List variable, \ _googleListeners, which is later processed in the function, __ listGoogleListeners._ It’s this function, \ _listGoogleListeners,_that’s actually passed in as the first parameter to the listener. This arrangement, again, allows you to assign any number of listeners to the plugin because the function, _ listGoogleListeners_, then uses the for loop to go through all those listeners.
Next, is the very function that’s that first parameter above, \ _listGoogleListeners. You see that it, indeed, processes the List variable, __ googlListeners_, revealing , what one might see as being, a profound feature of this class library — again, you can assign ‘any number’ of listeners to this class library. There’s a for loop there to call each in turn.
Another programmer, for example, working on another part of your app may also need to trigger an event when the ‘authentication changes.’ This class library allows for multiple functions to be fired in turn for this particular event. Further below, you see the add () function being used in the setter called, listen. It‘s’ adding to the List variable a function of type, GoogleListener, to later be called in this event. Finally, there is a function called, removeListen (), to remove a particular function if and when it’s necessary.
The function, alreadyLoggedIn (), serves to reduce the unnecessary recreation of important objects. If the user is already logged in, there’s no need to log in again. It’s used throughout the class library with almost every authentication function. It’s public too, and so developers can use it as well.
The next function allows you to sign into Firebase anonymously. While doing so, it allows you to provide a ‘listener’ function to fire after you successfully log in. Note, with this function and practically all the other ‘sign in’ functions there’s a try..catch statement to ‘catch’ any errors that may occur. The exception is then stored in the ‘library-private’ variable, _ex, using the funciton, _setError ().
Just to demonstrate, the three screenshots below display the what happens when you click on the ‘Log in anonymously’ button.
The next function will allow one to log into Firebase using their email and password. There’s some preparation involved here. You’ve got to go to your Firebase console and allow for passwords to be used for authentication. This is detailed further on the Firebase website:
As an aside, do notice I’m using the very same names for the functions as those used by the plugins. I want to make this class library recognizable to developers. If they already know how to use the plugins, they’ll know how to use this class library.
If your app requires you to provide a list of the ‘providers’ your user has logged into, there’s an function for that: fetchProvidersForEmail (). Why? How should I know?! It’s your app. The plugin provides such an function, and so does the class library. What follows is then a means to ‘reset’ your password. That is, if you’ve logged into Firebase with an email and password, signInWithEmailAndPassword ()
Below is a demonstration attempting to log in with an email an password. Obviously, I didn’t perform the preparation steps yet in this case.
The example code displayed below highlights the code involved in displaying the error message. It demonstrating how you can, of course, perform asynchronous operations using the class library.
The class type, AuthCredential, is used by some systems (Google for one) to further get authentication information from the logged in user. In fact, further on in this class library, it’s used to get such information when logging in using Facebook. You’ve access to this function below as well if you like.
This function is used when you’ve to ‘refresh the log in session.’ Logging into Firebase only last a certain amount of time depending (one hour I’m told) . This posting will offer some insight, firebase signInWithCustomToken broken
Like the official documentation states the next function below, “Sets the user-facing language code for auth operations that can be internationalized, such as [sendEmailVerification]. This language code should follow the conventions defined by the IETF in BCP47”
The following function, _setUserFromFirebase, is called every time when logging into only Firebase and not into Google. With that, the parameter is of type FirebaseUser. The user profile information is assigned into the many static variables you can then readily access with the class library’s corresponding getters.
The next function has you log into Firebase using Google. You sign into Google and then sign into Firebase using the supplied Google’s credential.
That’s what the function, _setFireBaseWithGoogle (), is for. It’ll be found further down the code. It takes the info retrieved from the ‘Google’ sign in and uses that to log into Firebase as well.
This function will sign in the user for them if they have signed in before in the past. Sign them into Google that is. It then signs into Firebase using the Google credentials.
As of this writing, I noted an ‘internal error’ was occurring in the plugin the ‘very first time’ to sign into Google. I merely have the class library attempt again (in the catch statement), and it successfully signs in. There’s something I’m missing here…maybe someone can contribute and help out.
The next function is used to have the user manually log into their Google account. I use this function a lot, and it is this function when you click on the ‘sign in’ button in the example presented at the start of this article.
This next function, takes the in the account information of a successful sign into Google in the form of a class object, GoogleSignInAccount. That is then passed into this function and supplies two token values to then log into Firebase. The class library’s many static variables, again, are then assigned the ‘user profile information’ easily accessible by their corresponding setters.
Again, once the user logs in, you’re privy to a bit of the user’s information. The class library provide such access with the use of a number of getters demonstrated in the example app itself under the ‘Results’ tab.
You can see there’s a little segment of code listed below using the FlutterOAuth () function. It then calls the function, signInWithCredential (), encountered earlier.
At this time, this class library doesn’t log in using Twitter. There’s a plugin for that: flutter_twitter_login. However for now, I’ll invite you to read,Flutter+Firebase — Authenticate with Twitter by Etimbuk. He introduces this plugin, and it is this plugin that supplies the two tokens you would, in turn, pass on to the function below.
To sign out is to log out of the Google backend and the Firebase backend. Returning to the app, ‘silently’ signing is possible without having the user signing in manually again. However, if you sign out and then disconnect, the user will have to sign in manually again.
It’s good practice to explicitly sign out when the app is terminating. The dispose () function calls the signOut () function listed below. You see it merely calls the plugin’s signOut () function respectively. Note, you don’t disconnect, but the function that follows does.
The next two functions tests to see if you’re current ‘logged in.’ Again the init () function is called upon in the last two functions to make sure, in this case, the variable, __googleSignIn,_is not null.
Next, is the internal function to record any errors the class library may encounter. There’s the function, getError (), to retrieve such errors,
The class library finishes up with, again, several getters conveying the user’s profile information. They, of course, are updated in either the functions _setUserFromFirebase () or _setFireBaseUserFromGoogle ().
A lot of redundancy in this class library. That’s what makes it a class library. Ugly on the inside, but slick on the outside. Just a few calls and you’re done authenticating users to your app. This class library is just another tool in the toolkit to make life a little bit easier when developing mobile apps in Flutter — the best platform in mobile development.