# 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. &#x20;

When accessing most Authentication services, you need the appropriate FirebaseAuth object.&#x20;

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):&#x20;

```
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!
         */
    }
}
```

{% hint style="info" %}
Check out [Manage Users](https://firebase.google.com/docs/auth/android/manage-users) to see operations one can do on a user object!
{% endhint %}

### Sign-out

You can sign out a user using:

```
Firebase.auth.signOut()
```

## Google Sign-In&#x20;

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

{% embed url="<https://firebase.google.com/docs/auth/android/google-signin#kotlin+ktx>" %}

{% embed url="<https://developers.google.com/identity/sign-in/android/sign-in>" %}

1\. Enable Google Sign-In in the Firebase console:\
&#x20;    1.1. In the [Firebase console](https://console.firebase.google.com/), open the **Auth** section for your project\
&#x20;    1.2. On the **Sign in method** tab, enable the **Google** sign-in method and click **Save**.

![Authentication section in the console](https://195521982-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvOeSx5ZqjJA8sxykMu%2F-MYcOknt8AWV_Djv6f1c%2F-MYcPP8nreY6Bxv8OLxU%2Fimage.png?alt=media\&token=91a9d935-d6aa-4e40-9d55-0e8ed9f0366e)

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`](https://developers.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInOptions.Builder#GoogleSignInOptions.Builder\(\)) 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`](https://developers.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInOptions.Builder#requestScopes\(com.google.android.gms.common.api.Scope,%20com.google.android.gms.common.api.Scope...\)). 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](https://developers.google.com/identity/sign-in/android/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`](https://developers.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInClient#getSignInIntent\(\)) method, and starting the intent with the `ActivityResultLauncher`.

```kotlin
override fun onClick(view: View?) {
    if (view != null) {
        when (view.id) {
            R.id.sign_in_button -> {
                signInGoogle();
            }
        // ...
        }
    }
}
```

```kotlin
private fun signInGoogle() {
    val signInIntent = googleSignInClient.signInIntent
    intentLauncher.launch(signInIntent)
}
```

7\. **Expand the intent launcher**

```kotlin
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:

```kotlin
    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 :)

{% hint style="info" %}
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 ](https://firebase.google.com/docs/auth/android/firebaseui)for seamless integration.
{% endhint %}

## Password Authentication

.1. Enable Email/Password sign-in:\
&#x20;    1.1. In the [Firebase console](https://console.firebase.google.com/), open the Auth section.\
&#x20;    1.2. On the **Sign in method** tab, enable the **Email/password** sign-in method and click **Save**.

![Authentication section in the console](https://195521982-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvOeSx5ZqjJA8sxykMu%2F-MYcOknt8AWV_Djv6f1c%2F-MYcQ_rfyL_NIiop0qM0%2Fimage.png?alt=media\&token=619b4620-bb60-4368-a08e-4b6a5414d78f)

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.

{% hint style="info" %}
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](https://github.com/nulab/zxcvbn4j), which is used by Dropbox.
{% endhint %}

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.
                 */
            }
        }
```

{% hint style="info" %}
Creating an account automatically signs a user in!
{% endhint %}

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.
                 */
            }
        }
```

{% hint style="info" %}
Firebase Auth offers many more ways to authenticate users, I implore you to explore the [API ](https://firebase.google.com/docs/auth)and see what could possibly fit your needs!
{% endhint %}
