Android user authentication using Firebase with Spring boot backend — Part 1
Architecture is an indispensable part of software development. Taking the wise decisions in the early stages of your product development lifecycle will save you a lot of money. Most importantly a well architected solution will protect a company from the grudges of disgruntled software developers.
It is often the case that you might want to provide user specific content or features in your android app. A social networking app, a video backup tool, a fitness app, all of these will require a user authentication. But when an Architect is not aware of options other than oauth we might end up in a rigid solution.
When I said other options I meant Firebase. Firebase is a one stop shop to integrate a wide variety of solutions in your android app like authentication, crash reports, database, etc. In this 2 part article we will see how to integrate Google authentication in your android app. The probability of android users having a Google account is pretty high. So providing ‘Google SignIn’ button in your android app is more than enough to serve the world during your MVP phase.
There are 2 major steps in accomplishing this.
- Integrate Firebase in your android app
- Integrate Firebase in your Backend for Frontend (BFF)
Integrating Firebase in your android app
Firebase is a tool from Google to build android app infrastructure using ready made tools like Authentication. Firebase behind the scene is run on Google Cloud Platform, so when you create a Firebase project for your android app a GCP project is automatically created.
Create different Firebase projects for each of your environments (DTAP).
https://console.firebase.google.com/
Login using your google account (organisational) into firebase console.

If you want to share users between apps and you are providing an ecosystem like services then you can create one project for the whole ecosystem. If you don’t want to share users between apps you can create app specific projects.





Don’t forget to create Billing alerts for your Firebase projects in GCP.


Enable Google Sign-in method. Also ‘support email’ is mandatory for the login to work. Leave rest of the fields for defaults and Save.

Android Project and Code changes for Authentication
Firstly we will have to add few dependencies in gradle to enable Firebase authentication.
I have created a sample android project with just Main Activity in Android studio.
Before we start with code changes the app needs to be added to Firebase.


Also copy the package from android manifest and keep it ready for the next step.

Open Project Overview in Firebase.



Skip the next 2 steps which we will see in detail later. You can click on the app to view the settings.


Now let’s get back to our code changes.

Add the below dependency in Project build.gradle file
classpath 'com.google.gms:google-services:4.3.4'
Add the below plugin and dependencies in Module build.gradle


Add the below plugin in build.gradle of the Module.
id 'com.google.gms.google-services'
Add the below dependencies in build.gradle of the Module.
implementation platform('com.google.firebase:firebase-bom:26.1.1')
implementation 'com.google.firebase:firebase-auth'
implementation 'com.google.android.gms:play-services-auth:19.0.0'
Now let’s add the Google SignIn button and a Logout button to our main activity layout.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.gms.common.SignInButton
android:id="@+id/loginButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:colorScheme="dark"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/logoutButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_marginEnd="20dp"
android:layout_marginBottom="20dp"
android:clickable="true"
android:contentDescription="Logout"
android:focusable="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:srcCompat="@android:drawable/ic_lock_power_off" />
</androidx.constraintlayout.widget.ConstraintLayout>
Open MainActivity.java and paste the below code for SignIn and Logout.
package com.softwok.softwoktutorialapp;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.common.SignInButton;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.tasks.Task;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.GoogleAuthProvider;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "MainActivity";
private static final int RC_SIGN_IN = 9001;
private FirebaseAuth mAuth;
private GoogleSignInClient mGoogleSignInClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SignInButton loginButton = findViewById(R.id.loginButton);
loginButton.setOnClickListener(this);
FloatingActionButton logoutButton = findViewById(R.id.logoutButton);
logoutButton.setOnClickListener(this);
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.build();
mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
mAuth = FirebaseAuth.getInstance();
if (mAuth.getCurrentUser() == null) {
setLoggedOutUi();
} else {
setLoggedInUi();
}
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.loginButton) {
Log.i(TAG, "loginButton Clicked");
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
startActivityForResult(signInIntent, RC_SIGN_IN);
} else if (v.getId() == R.id.logoutButton) {
Log.i(TAG, "logoutButton Clicked");
signOut();
}
}
private void firebaseAuthWithGoogle(String idToken) {
AuthCredential credential = GoogleAuthProvider.getCredential(idToken, null);
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, task -> {
if (task.isSuccessful()) {
// Sign in success, update UI with the signed-in user's information
Log.i(TAG, "signInWithCredential:success");
setLoggedInUi();
Snackbar.make(findViewById(android.R.id.content),
"Login successful", Snackbar.LENGTH_LONG).show();
} else {
// If sign in fails, display a message to the user.
Log.w(TAG, "signInWithCredential:failure", task.getException());
Snackbar.make(findViewById(android.R.id.content),
"Login failed", Snackbar.LENGTH_LONG).show();
}
});
}
private void signOut() {
// Firebase sign out
mAuth.signOut();
// Google sign out
mGoogleSignInClient.signOut().addOnCompleteListener(this,
task -> {
Log.i(TAG, "signOut:success");
setLoggedOutUi();
Snackbar.make(findViewById(android.R.id.content),
"Logout successful", Snackbar.LENGTH_LONG).show();
});
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
try {
// Google Sign In was successful, authenticate with Firebase
GoogleSignInAccount account = task.getResult(ApiException.class);
if (account == null) {
throw new ApiException(Status.RESULT_INTERNAL_ERROR);
}
Log.i(TAG, "firebaseAuthWithGoogle:" + account.getId());
firebaseAuthWithGoogle(account.getIdToken());
} catch (ApiException e) {
// Google Sign In failed, update UI appropriately
Log.w(TAG, "Google sign in failed", e);
Snackbar.make(findViewById(android.R.id.content),
"Login failed", Snackbar.LENGTH_LONG).show();
}
}
}
private void setLoggedInUi() {
findViewById(R.id.loginButton).setVisibility(View.INVISIBLE);
findViewById(R.id.logoutButton).setVisibility(View.VISIBLE);
}
private void setLoggedOutUi() {
findViewById(R.id.logoutButton).setVisibility(View.INVISIBLE);
findViewById(R.id.loginButton).setVisibility(View.VISIBLE);
}
}
Most important step after this is to Build the project to see if you have skipped any step which might have caused a compile error.
Most often developers forget to paste the google-services.json in app module.
Login Flow in action
