Day 19 of Flutter - Authentication Service

In this phase, I worked on creating an auth service for my Firebase authentication since I was previously handling that in the UI source code of my app. So I'll discuss why we use the auth service and explain how it was done as much as I can.

Why Auth Service?

Previously, the authentication provider of our app, FirebaseAuth, communicated directly with the user interface, meaning that the lines of code for our authentication were written in the widgets of our app, which isn't regarded as best practice. And some of the reasons are;

  • Code Duplication: Authentication logic may be duplicated across many parts of our app may lead to bugs and inconsistencies.

  • Maintenance Issues: Spreading authentication logic across your UI may make it hard to maintain, and this could lead to security issues and bugs.

  • Security Risks: Storing sensitive authentication data in the UI can lead to potential security risks, such as data leakage or unauthorized access.

  • Also, writing authentication code in your UI makes testing difficult.

In the next part, I will explain the roles of the providers and services used in implementing our Auth service and how they were done using some code snippets.

Auth Service Implementation

With the implementation of our auth service, there will be an additional layer between our FirebaseAuth provider and user interface.

Auth Provider

The auth provider is an abstract class that lays the foundation upon which the actual authentication provider, be it Firebase or any other provider, will be built. So in our case, the FirebaseAuth provider will inherit from the auth provider. As you can tell from the code below, our AuthProvider class contains only methods, some of which have required parameters, and also a getter to get the current user.

abstract class AuthProvider {
  AuthUser?
      get currentUser;

  Future<AuthUser> createUser({
    required String email,
    required String password,
  });

  Future<void> sendEmailVerification();

  Future<AuthUser> login({
    required String email,
    required String password,
  });

  Future<void> logOut();
}

FirebaseAuth Provider

The Firebase auth provider will be a concrete implementation of our auth provider abstract class and will receive the abstract class's methods. The requirements and logic for each method will be provided in this class. Below, you'll see the implementation of some of the methods.

class FirebaseAuthProvider implements AuthProvider {
  @override
  Future<void> sendEmailVerification() async {
    final user = FirebaseAuth.instance.currentUser;
    if (user != null) {
      await user.sendEmailVerification();
    } else {
      throw UserNotLoggedInAuthException();
    }
  }

  @override
  Future<void> logOut() async {
    final user = FirebaseAuth.instance.currentUser;
    if (user != null) {
      await FirebaseAuth.instance.signOut();
    } else {
      throw UserNotLoggedInAuthException();
    }
  }
}

Auth Service

The auth service will be our final class, and it will be the class communicating with the UI of our app. The auth service will take any auth provider and expose its functionalities to the UI.

I will cover this phase more in my next post, where I will be incorporating the auth service with the UI.