10.2 Authentication

Firebase Authentication provides backend services, easy-to-use SDKs, and ready-made UI libraries to authenticate users to your app. It supports authentication using passwords, phone numbers, popular federated identity providers like Google, Facebook and Twitter, and more

https://firebase.google.com/docs/auth

Setting up Authentication

Make sure your Firebase project is set up, the steps of which are covered in the first section 11.1!

Add these two dependencies to your module-level Gradle file:

implementation 'com.google.firebase:firebase-auth-ktx'
implementation 'com.google.android.gms:play-services-auth:19.0.0'

These dependencies add the Firebase Authentication Android library and Google Play services SDK to your app.

When accessing most Authentication services, you need the appropriate FirebaseAuth object.

First, declare your auth variable:

private lateinit var auth: FirebaseAuth

In the onCreate/onCreateView method of your activity/fragment, initialize the auth variable as so:

auth = Firebase.auth

General

Check for signed-in users

When initializing your Activity, check to see if the user is currently signed in in your onStart method (which is called automatically after onCreate):

override fun onStart() {
    super.onStart()
    val currentUser = auth.currentUser
    if (currentUser == null) {
        /**
         * No user is currently signed in, can update UI elements to account for this
         * or maybe redirect to some sign in activity!
         */
    } else {
        /**
         * A signed in user is detected, carry out some respective actions if needed!
         */
    }
}

Check out Manage Users to see operations one can do on a user object!

Sign-out

You can sign out a user using:

Firebase.auth.signOut()

Google Sign-In

This will most likely just be a collection of the links below, some personal reflections also!

1. Enable Google Sign-In in the Firebase console: 1.1. In the Firebase console, open the Auth section for your project 1.2. On the Sign in method tab, enable the Google sign-in method and click Save.

2. In your sign-in activity's onCreate method, configure Google Sign-In to request the user data required by your app. For example, to configure Google Sign-In to request users' ID and basic profile information, create a GoogleSignInOptions object with the DEFAULT_SIGN_IN parameter. To request users' email addresses as well, create the GoogleSignInOptions object with the requestEmail option.

private lateinit var googleSignInClient: GoogleSignInClient

......

// Configure sign-in to request the user's ID, email address, and basic
// profile. ID and basic profile are included in DEFAULT_SIGN_IN.
val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
        .requestIdToken(getString(R.string.default_web_client_id))
        .requestEmail()
        .build()

googleSignInClient = GoogleSignIn.getClient(this, gso)

If you need to request additional scopes to access Google APIs, specify them with requestScopes. For the best user experience, on sign-in, only request the scopes that are required for your app to minimally function. Request any additional scopes only when you need them, so that your users see the consent screen in the context of an action they performed. See Requesting Additional Scopes.

3. Add an ActivityResultLauncher for the Google Sign In Activity intent (the API launches a separate activity to sign the user in):

    private lateinit var intentLauncher: ActivityResultLauncher<Intent>
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        intentLauncher =
            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
                ...
            }
        ...
    }

4. You can add a handy Google sign-in button via:

<com.google.android.gms.common.SignInButton
 android:id="@+id/sign_in_button"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content" />
 
 <!--  Can add app:buttonSize attribute and specifiy icon_only, standard, or wide-->
 <!--  Can add app:colorScheme attribute and specifiy dark, light, or auto-->

5. You can then register the OnClickListener for this button in your activity via:

findViewById<SignInButton>(R.id.sign_in_button).setOnClickListener(this)

6. In the activity's onClick method, handle sign-in button taps by creating a sign-in intent with the getSignInIntent method, and starting the intent with the ActivityResultLauncher.

override fun onClick(view: View?) {
    if (view != null) {
        when (view.id) {
            R.id.sign_in_button -> {
                signInGoogle();
            }
        // ...
        }
    }
}
private fun signInGoogle() {
    val signInIntent = googleSignInClient.signInIntent
    intentLauncher.launch(signInIntent)
}

7. Expand the intent launcher

private lateinit var intentLauncher: ActivityResultLauncher<Intent>
override fun onCreate(savedInstanceState: Bundle?) {
    ...
    intentLauncher =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            if (result.resultCode == Activity.RESULT_OK) {
                val task = GoogleSignIn.getSignedInAccountFromIntent(result.data)
                try {
                    // Google Sign In was successful, authenticate with Firebase
                    val account = task.getResult(ApiException::class.java)!!
                    firebaseAuthWithGoogle(account.idToken!!)
                } catch (e: ApiException) {
                    // Google Sign In failed, update UI appropriately
                }
            }
        }
    ...
}

8. After a user successfully signs in, get an ID token from the GoogleSignInAccount object, exchange it for a Firebase credential, and authenticate with Firebase using the Firebase credential:

    private fun firebaseAuthWithGoogle(idToken: String) {
        val credential = GoogleAuthProvider.getCredential(idToken, null)
        auth.signInWithCredential(credential)
            .addOnCompleteListener(this) { task ->
                if (task.isSuccessful) {
                    /**
                     * A signed in user is detected, carry out some respective actions if needed!
                     */
                    val user = auth.currentUser
                    ...
                } else {
                    /**
                     * No user is currently signed in, can update UI elements to account for this
                     * and display some feedback to the user.
                     */
                }
            }
    }

9. All done :)

Many of the other providers (i.e. Facebook and Twitter and GitHub) follow similar patterns. If you find yourself using multiple of these in your app in your authentication process, it may be worth it looking into FirebaseUI for seamless integration.

Password Authentication

.1. Enable Email/Password sign-in: 1.1. In the Firebase console, open the Auth section. 1.2. On the Sign in method tab, enable the Email/password sign-in method and click Save.

2. When a new user signs up using your app's sign-up form, complete any new account validation steps that your app requires, such as verifying that the new account's password was correctly typed and meets your complexity requirements.

EditTexts are very useful for fields for input for emails/passwords!

If you are looking for a good password strength detector, take a look at zxcvbn, which is used by Dropbox.

3. Create a new account by passing the new user's email address and password to createUserWithEmailAndPassword:

auth.createUserWithEmailAndPassword(email, password)
        .addOnCompleteListener(this) { task ->
            if (task.isSuccessful) {
                /**
                 * A signed in user is detected, carry out some respective actions if needed!
                 */
                val user = auth.currentUser
            } else {
                /**
                 * No user is currently signed in, can update UI elements to account for this
                 * and display some feedback to the user.
                 */
            }
        }

Creating an account automatically signs a user in!

If given some email and password, you can sign in a user with signInWithEmailAndPassword:

auth.signInWithEmailAndPassword(email, password)
        .addOnCompleteListener(this) { task ->
            if (task.isSuccessful) {
                /**
                 * A signed in user is detected, carry out some respective actions if needed!
                 */
                val user = auth.currentUser
                ...
             } else {
                /**
                 * No user is currently signed in, can update UI elements to account for this
                 * and display some feedback to the user.
                 */
            }
        }

Firebase Auth offers many more ways to authenticate users, I implore you to explore the API and see what could possibly fit your needs!

Last updated