Firebase Authentication – Simple Signin with Email and Password for Android

Email and Password – The Simple Log In

One of the most useful features in Firebase Authentication is the ability create a secure user account with the user’s own email and password.  Utilizing Firebase’s secure methods is very simple and powerful and available cross platform.  Follow along in this article to learn how to tackle simple sign in for Firebase Authentication based on a user’s email and password in Android. To learn how to setup simple sign in for iOS please read my article Firebase Authentication – Simple Signin With Email and Password for iOS on Swift and please look for Web version to be posted very soon.

I admittedly believe The Setup section is a bit dry, but if you can make it through till the Manage section I believe you’ll be a bit more entertained.

The Setup 

No matter which platform you are developing on, you will need to do a little bit of setup before you get started with email and password sign in. This won’t hurt a bit, so we’ll take a look at the setup now for Android.

Android 

1. First, you will need to create a Firebase project in the Firebase Console or import an existing project into the Firebase Console.
2. Click on Add Firebase to Your Android app and follow the setup steps, you’ll need your project’s package name and your SHA-1 (the SHA-1 says that it is optional but you need this for a fully functioning app).
3. Download the google-services.json file and save this in the /app folder of your Android app.
4. Update your root level build.gradle file to include the google-services plugin –

 buildscript { dependencies { classpath 'com.google.gms:google-services:3.0.0' } }

 

5. Update your module gradle file to add dependencies for Firebase and Firebase Auth –

 dependences { compile 'com.google.firebase:firebase-core:9.6.1' compile 'com.google.firebase:firebase-auth:9.6.1' } //ADD THIS TO THE BOTTOM apply plugin: 'com.google.gms.google-services'

6. Go back to the Firebase Console and enable the Email/password sign-in method. Do this by navigating to the Auth section in the console, then click the Sign in method tab, enable the Email/password sign-in method and click Save.

Create a User’s Account

Now that we’re all setup we can get started. The first thing to do is create a user’s account in our app, you will be amazed at how simple this actually is to accomplish.

In our class we’ll get a shared instance of the FirebaseAuth object and the AuthStateListener.  In the onCreate() method call FirebaseAuth.getObject() and set up the AuthStateListener.  The AuthStateListener’s job is to respond to changes in the user’s sign in state, so as a user signs in or out our AuthStateListener listens to this and provides information on the sign in state.  You’ll notice we create a user with FirebaseUser and calling firebaseAuth.getCurrentUser(), if that user is not null then the user is signed in, otherwise the user is signed out.

Now we’ll start and stop the AuthStateListener by adding or removing in our onStart() and onStop() methods.  onStart() is called when the Class is started and we will add the AuthStateListener so it can begin doing it’s job listening for changes in our user’s AuthState.  onStop() is called when our Class is stopping and we will test to see if our AuthStateListener is already null and if it is not then we will remove our AuthStateListener before the Class is fully stopped.

The Firebase documentation recommends doing validation steps prior to creating your user’s account and I fully support this.  At this point the items you can validate are simply email address and password by having the user type them in a second time and validating that the entries match, I’ll leave that up to you as the developer to come up with that complete strategy.

 private FirebaseAuth mAuth; private FirebaseAuth.AuthStateListener mAuthListener; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mAuth = FirebaseAuth.getInstance(); mAuthListener = new FirebaseAuth.AuthStateListener() { @Override public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) { FirebaseUser user = firebaseAuth.getCurrentUser(); if (user != null) { // User is signed in } else { // User is signed out Log.d(LOG_TAG, "onAuthStateChanged:signed_out"); } } }; } @Override public void onStart() { super.onStart(); mAuth.addAuthStateListener(mAuthListener); } @Override public void onStop() { super.onStop(); if (mAuthListener != null) { mAuth.removeAuthStateListener(mAuthListener); } }

At this point we are finally ready to create the user’s account, to accomplish this we will call FirebaseAuth.createUserWithEmailAndPassword(), we’ll create a method for this process that you may call with a button click or in any other manner that you choose.  Most likely you have had your user enter their email and password into an EditText widget and the createUserWithEmailAndPassword requires string values for the email and password so you must convert those values to a String for the method to work correctly.

 ... email = emailWidget.getText().toString(); password = passwordWidget.getText().toString(); .... private void createUserAccount(email String, password String){ Log.d(LOG_TAG, "email: "+getEmail+" password: "+getPassword); mAuth.createUserWithEmailAndPassword(getEmail, getPassword) .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { // If account creation fails, log the exception and notifiy the user. // If account creation is successful then the authStateListener will be // notified and the signed in user information is handled by // the listener. if (!task.isSuccessful()) { Log.w(LOG_TAG, "signInWithEmail:failed", task.getException()); Log.w(LOG_TAG, "email: "+email.toString()+" password: "+password.toString()); Toast.makeText(MainActivity.this, R.string.create_account_fail+task.getException(), Toast.LENGTH_LONG).show(); } } }); };

Sign In with an email and password

Now that our user’s account has been created we’ll need to have them sign into their account.  Below I’ve created a method called signInWithEmail() which requires email and password as string values, again.  In the method we call FirebaseAuth.signInWithEmailAndPassword and pass the email and password strings and addOnCompleteListener which creates and OnCompleteListener that listens for the AuthResult.  Then we override the onComplete and require a non-null Task with the AuthResult and if the task.isSuccessful() returns true the user is signed in with their own email.

 ... email = emailWidget.getText().toString(); password = passwordWidget.getText().toString(); ... private void signInWithEmail(email String, password String){ mAuth.signInWithEmailAndPassword(email, password) .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { Log.d(LOG_TAG, "signInWithEmail:onComplete:" + task.isSuccessful()); // If sign in fails, display a message to the user. If sign in succeeds // the auth state listener will be notified and logic to handle the // signed in user can be handled in the listener. if (!task.isSuccessful()) { Log.w(LOG_TAG, "signInWithEmail:failed", task.getException()); Log.w(LOG_TAG, "email: "+email.toString()+" password: "+password.toString()); Toast.makeText(MainActivity.this, R.string.auth_failed, Toast.LENGTH_LONG).show(); } } }); };

Manage Users

After you have created a user with email and password and then successfully signed the user into your app, you can perform many actions with their user information.  You can get the current user, get the user’s profile information (which may include a photo, email address or name), update the user’s profile information, reset passwords, etc.  As we continue we’ll discuss how to perform each of these and other tasks, and we’ll be doing this with our boy Bob.  Bob is a recent college grad who’s finally landed a job and is trying to clean up his act a bit from his hard partying days at college.

Get Currently Signed In User

We’ll start by getting Bob’s user ID,  the currently signed in user, and we’ll build from there.  We create a FirebaseUser and get FirebaseAuth.getInstance().getcurrentUser(), if the FirebaseUser is not null then we can get the user id with .getUid().

 FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); if (user != null) { String currentUser = user.getUid(); }

Get User’s Profile Information

After we have the a valid FirebaseUser we an dig deeper and get additional data elements such as photo, email and name.  Assume we were able to getCurrentUser() successfully we can simply request to get the user name (getDisplayName()), user’s email (getEmail()), and get user’s photo url (getPhotoUrl()).

 String userName = user.getDisplayName(); String userEmail = user.getEmail(); Uri userPhotoUrl = user.getPhotoUrl();

Update a User’s Profile Information

We are able to make some simple changes to Bob’s profile, we can change the Bob’s display name and his photo url.  To accomplish this we’ll use the static class UserProfileChangeRequest.Builder() which allows us to setDisplayName(String) and setPhotoUri(Uri) and then call .build().  We’ll call the FirebaseUser.updateProfile() and pass in the UserProfileChangeRequest that we created.

 FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder() .setDisplayName("Bob Smith") .setPhotoUri(Uri.parse("https://mysocialmedia.com/user/bob_in_a_suit_not_drunk.jpg")) .build(); user.updateProfile(profileUpdates) .addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { if (task.isSuccessful()) { Log.d(LOG_TAG, "User profile successfully updated."); } } });

Change a User’s Email Address

So your user has registered with their favorite email address they have deceided that superSeXy18@yahoo.com is not very professional (no idea if that’s a real email address) and they want to update their email address to something more corporate like bob_smith_cpa@gmail.com, well fortunately with Firebase this is pretty easy to accomplish.  If the user’s credential is too old you may be required to re-authenticate, make sure you read the Re-Authenticate a User section below.

 FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); user.updateEmail("bob_smith_cpa@gmail.com") .addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { if (task.isSuccessful()) { Log.d(TAG, "User email address updated to:"+user.getEmail()); } } });

Send a User an Email to Reset Their Password

So now Bob Smith looks professional to all his new buddies at E-Corp, but he forgot his password (probably too busy trying to find a way to convert the masses to E-Coin).  Fortunately you can help him out (don’t expect the favor to be returned) and send him an email to reset his password.

To send Bob his password email you will need to get an instance of the FirebaseAuth (don’t you have this already?) and then get the email address that the account is registered to, I would have Bob enter this via an EditText field.  Once you have the string version of Bob’s email then you will call FirebaseAuth.sendPasswordResetEmail(emailAddress) as shown below.  If everything is successful then Bob should get an email allowing him to reset his password.  Keep in mind that you can customize the email that is sent to your user’s by visiting the Firebase Console on the Email Templates page.

 FirebaseAuth auth = FirebaseAuth.getInstance(); String emailAddress = "bob_smith_cpa@gmail.com"; auth.sendPasswordResetEmail(emailAddress) .addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { if (task.isSuccessful()) { Log.d(TAG, "Password Reset Email sent."); } } });

Update a User’s Password

Since Bob is too busy to check his email and probably only uses Slack (#zeroinbox), we can allow him to update his password right in the app.  Allow Bob to enter a new password (security verification is left up to you and I encourage you to set a minimum length, special characters, upper and lower case rules) as a String.  Most likely you’ll do this via an EditText so don’t forget to get the string value.  Call FirebaseUser.updatePassword() and pass in the string value for the new password.  If you allow Bob to set a password that is less than 6 characters you can expect to get a FirebaseAuthWeakPasswordException and no one wants that.  If the user’s credential is too old you may be required to re-authenticate, make sure you read the Re-Authenticate a User section below.

 String newPassword = "eXpl0!t_Dn1eD!"; user.updatePassword(newPassword) .addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { if (task.isSuccessful()) { Log.d(LOG_TAG, "User password updated."); } } });

Delete a User’s Account

The time may come when Bob is too swamped at E-Corp to keep using your app as it’s distracting him from his climp up the evil ladder and Bob just wants to delete his account.  Never fear Bob, we can’s save you from selling your soul but we can delete your account from our awesome app.  As long as you have a reference to the FirebaseUser you can call FirebaseUser.delete() and Bob’s account is no more.  Simple.  If the user’s credential is too old you may be required to re-authenticate, make sure you read the Re-Authenticate a User section below.

 FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); user.delete() .addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { if (task.isSuccessful()) { Log.d(LOG_TAG, "Adios Bob"); } } });

Re-Authenticate a User

If it’s been some time since Bob signed in (forget that whole account deletion section above, Bob couldn’t go through with deleting his account) you may need to re-authenticate a user for several of the actions above – Delete a User’s Account, Updating a User’s Password, Change a User’s Email Address.  If you try one of these actions and receive a FirebaseAuthRecentLoginRequiredException error then you will need to Re-Authenticate your user and get new signin credentials.  To do this you will basically have the user sign in to their app but this time you’ll use a different method.  Get a new instance of FirebaseUser.  Create a new AuthCredential and set it equal to EmailAuthProvider.getCredential(email, password), you’ll need to pass in email and password as String values.  Next call FirebaseAuth.reauthenticate() and pass in the AuthCredential, if successful the user is reauthenticaed and you can retry the original action.  If you receive an error then you may listen for that and deal with it as appropriate.

 

 FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); AuthCredential credential = EmailAuthProvider .getCredential("bob_smith_cpa@gmail.com", "reallyHardPassword"); user.reauthenticate(credential) .addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { Log.d(TAG, "User re-authenticated."); } });

Sign a User Out

Now after all that work don’t forget to give Bob a way to sign out of your app, after all he’s got work to do!

 FirebaseAuth.getInstance().signOut();

That’s all folks!  Thanks for reading this to the end, I hope it wasn’t too boring for you.  The Firebase Docs have everything you’ve read here documented, but without my amazing commentary, they are excellent and I encourage you to check them out.

As I mentioned in the beginning I’ll be posting an article detailing these same actions for iOS and the web soon.  Please check back for those and if you enjoyed this please share it on social media.  If you have found any errors or ommisions please leave me feedback so I can get it corrected as soon as possible!