Jetpack Compose is a modern toolkit for building native Android user interfaces. Implementing authentication in your app is essential for securing user data and providing personalized experiences. This step-by-step guide will walk you through setting up authentication in your Jetpack Compose Android app.

Prerequisites

  • Android Studio installed (Arctic Fox or later)
  • Basic knowledge of Kotlin and Jetpack Compose
  • Google Firebase account
  • Android project set up with Jetpack Compose

Step 1: Add Firebase to Your Project

First, connect your Android app to Firebase. Go to the Firebase Console and create a new project or select an existing one. Follow the instructions to add your Android app, download the google-services.json file, and place it in your app's app/ directory.

Next, add the Firebase SDK to your project's build.gradle files:

// Project-level build.gradle
buildscript {
    dependencies {
        classpath 'com.google.gms:google-services:4.3.15'
    }
}

// App-level build.gradle
plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'com.google.gms.google-services'
}

dependencies {
    implementation 'com.google.firebase:firebase-auth-ktx:21.1.0'
}

Step 2: Set Up Firebase Authentication

In the Firebase Console, navigate to the Authentication section. Enable the sign-in methods you want to support, such as Email/Password, Google, Facebook, etc. For this guide, we'll focus on Email/Password authentication.

Step 3: Create Authentication UI in Jetpack Compose

Design simple login and registration screens using Jetpack Compose. Here's an example of a login screen:

@Composable
fun LoginScreen(
    onLoginSuccess: () -> Unit,
    onNavigateToRegister: () -> Unit
) {
    var email by remember { mutableStateOf("") }
    var password by remember { mutableStateOf("") }
    var errorMessage by remember { mutableStateOf(null) }
    val auth = FirebaseAuth.getInstance()

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        verticalArrangement = Arrangement.Center
    ) {
        Text(text = "Login", style = MaterialTheme.typography.h4)
        Spacer(modifier = Modifier.height(16.dp))
        OutlinedTextField(
            value = email,
            onValueChange = { email = it },
            label = { Text("Email") }
        )
        Spacer(modifier = Modifier.height(8.dp))
        OutlinedTextField(
            value = password,
            onValueChange = { password = it },
            label = { Text("Password") },
            visualTransformation = PasswordVisualTransformation()
        )
        Spacer(modifier = Modifier.height(16.dp))
        Button(
            onClick = {
                auth.signInWithEmailAndPassword(email, password)
                    .addOnCompleteListener { task ->
                        if (task.isSuccessful) {
                            onLoginSuccess()
                        } else {
                            errorMessage = task.exception?.message
                        }
                    }
            },
            modifier = Modifier.fillMaxWidth()
        ) {
            Text("Login")
        }
        errorMessage?.let {
            Text(text = it, color = Color.Red)
        }
        Spacer(modifier = Modifier.height(8.dp))
        TextButton(onClick = onNavigateToRegister) {
            Text("Create an account")
        }
    }
}

Step 4: Handle Authentication State

Implement a way to observe the user's authentication state and navigate accordingly. For example:

@Composable
fun AuthNavigation() {
    val auth = FirebaseAuth.getInstance()
    val user by remember { mutableStateOf(auth.currentUser) }

    LaunchedEffect(Unit) {
        auth.addAuthStateListener { firebaseAuth ->
            // Update UI based on auth state
        }
    }

    if (auth.currentUser != null) {
        // Show main app screen
        MainScreen()
    } else {
        // Show login screen
        LoginScreen(
            onLoginSuccess = { /* handle success */ },
            onNavigateToRegister = { /* navigate to registration */ }
        )
    }
}

Step 5: Register New Users

Create a registration screen similar to the login screen, using createUserWithEmailAndPassword method:

@Composable
fun RegisterScreen(
    onRegisterSuccess: () -> Unit,
    onNavigateToLogin: () -> Unit
) {
    var email by remember { mutableStateOf("") }
    var password by remember { mutableStateOf("") }
    var errorMessage by remember { mutableStateOf(null) }
    val auth = FirebaseAuth.getInstance()

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        verticalArrangement = Arrangement.Center
    ) {
        Text(text = "Register", style = MaterialTheme.typography.h4)
        Spacer(modifier = Modifier.height(16.dp))
        OutlinedTextField(
            value = email,
            onValueChange = { email = it },
            label = { Text("Email") }
        )
        Spacer(modifier = Modifier.height(8.dp))
        OutlinedTextField(
            value = password,
            onValueChange = { password = it },
            label = { Text("Password") },
            visualTransformation = PasswordVisualTransformation()
        )
        Spacer(modifier = Modifier.height(16.dp))
        Button(
            onClick = {
                auth.createUserWithEmailAndPassword(email, password)
                    .addOnCompleteListener { task ->
                        if (task.isSuccessful) {
                            onRegisterSuccess()
                        } else {
                            errorMessage = task.exception?.message
                        }
                    }
            },
            modifier = Modifier.fillMaxWidth()
        ) {
            Text("Register")
        }
        errorMessage?.let {
            Text(text = it, color = Color.Red)
        }
        Spacer(modifier = Modifier.height(8.dp))
        TextButton(onClick = onNavigateToLogin) {
            Text("Already have an account? Login")
        }
    }
}

Conclusion

Integrating Firebase Authentication with Jetpack Compose simplifies managing user sign-in and registration. By following this guide, you can add secure authentication features to your Android apps, enhancing user experience and security.