Flutter Persistent Authentication Flow with Supabase

What is supabase?

Supabase is a new amazing Firebase alternative. It provides you Postgres Database (SQL), authentication, instant APIs, Realtime Subscriptions, and storage out of the box And many more services:

  • Your own database, each project in Supabase has its own PostgreSQL database and even gives you access to queries!
  • Authenticating, creating and managing users has never been so easy!
  • Query your tables, including filtering, pagination, and deeply nested relationships (like GraphQL).
  • Create, update, and delete rows.
  • Manage your users and their permissions.
  • Interact with your database via a simple UI.

Why Supabase?

Supabase is open source and completely free. Supabase has an amazing community of developers supporting the product. Unlike Firebase where the community has no influence on the platform, Supabase interacts with the community and asks them what features they want and need.

Today we will learn how to integrate Supabase authentication into your Flutter application. By using Supabase, you will have a complete and secure authentication system in no time.

Create a new Supabase project.

Sign up on Supabase’s website, it’s free! Follow the instructions to create your organization on Supabase.

Each application on Supabase has a project with its own URL and key. Create a project, give it a name, a password and choose the location of your database.

Add the name of your project, the database password, and the database region.

Initialize a SupabaseClient

All you need to use Supabase in your project is an instance of SupabaseClient.

Each project has its own URL and key. Go back to the Supabase website and navigate to Settings:

Click on Settings in the left menu.

Then open the API section. Here you will see your project URL and key. We will use these two strings to set up an instance of SupabaseClient in the Flutter app.

In the API section you have your URL (in the config panel) and public key.

Import Supabase in your Flutter app.

Open your Flutter project. The first step is to import the Supabase package into your Flutter app. Open your pubspec.yaml file and add the following dependency:

dependencies:
  flutter:
    sdk: flutter
  supabase: "<latest version>"

Then run the flutter pub get command to download the package to your project.

Create an instance of _client with your Supabase URL and the key copied from the Supabase project:

import 'package:supabase/supabase.dart';
class AuthUtils extends ChangeNotifier {
  final _client = SupabaseClient(kSupabaseUrl, kSupabaseKey);
}

Sign up the user using Supabase authentication.

Through _client, we have access to the supabase authentication API. You just need to access the auth attribute and call the signUp method, passing the user’s email and password:

 Future<void> signUp(String email, String password) async {
    try {
      final response = await _client.auth.signUp(email, password);
      if (response.error != null) {
        print("Error! Could not signup");
        print(response.error!.message);
      } else {
        SharedPreferences prefs = await SharedPreferences.getInstance();
        final String session = response.data!.persistSessionString;
        await prefs.setString('session', session);
        notifyListeners();
      }
      notifyListeners();
    } catch (e) {
      print(e);
    }
  }

If the response contains an error, then we can show some error message. Otherwise, we have access to the new user’s instance and the current authentication session.

How to recover a session?

We will now recover a session, If you want to keep the user logged in after they have successfully logged into Flutter. If you want to save those details so that the user can stay logged in. If you successfully log the user in, but when you restart the app, you need to log in again, so you need to save the user’s details in a shared preferences so that the user can stay logged in for the entire session until they log out.

Future<bool> recoverSession() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    final String? sessionString = prefs.getString('session');
    if (sessionString != null) {
      try {
        final response = await _client.auth.recoverSession(sessionString);
        if (response.error != null) {
          print("Error! Could not recover the session");
          print(response.error!.message);
        } else {
          _user = response.user;
          notifyListeners();
        }
      } catch (e) {
        print(e);
      }
    }
    return true;
  }

If everything goes well, the session will be restored, otherwise you will get the error message that the session could not be restored.

We made the auth_utils class as provider, a wrapper around InheritedWidget to make it easier to use and reusable.
By using provider we get:

  • lazy-loading
  • simplified allocation
  • No need to create a class every time, it largely reduced boilerplate.
  • Increases system performance with listening mechanism.

You can use it to provide a value anywhere in the widget tree. However, it does not help you to update the widget tree when that value changes.

You don’t want the user to have to enter their information every time they open an app, you want it to be stored over the lifecycle of the app.

When a user logs in, a new instance is created in the Supabase authentication session and the user is redirected to the home page where they remain logged in for the entire session until they log out.


Check out github repository for full code.

Download App

Give us a call or fill in the form below to start a 30 days free trial.