Implementing OAuth2 Clients with Flutter made simple

Femi-ige Muyiwa - Sep 7 '23 - - Dev Community

Having to input our information every time we register for a new service is tiring. With open authorization or OAuth2, we no longer have to undergo that pain. Open authorization is a design that lets websites and applications access certain hosted resources from a provider by request from the user. These resources can range from the user’s registered email address to personal information to cloud data.

This article will show how to implement OAuth2 in a Flutter application with Google as the provider and Appwrite as the OAuth2 Client.
Here is the link to the repository containing the code for this project.

Prerequisites

The following are required to follow along with this tutorial:

  • Basic understanding of Dart and Flutter
  • Flutter SDK installed
  • Xcode with a developer account
  • Appwrite account; sign-up is completely free
  • A Gmail account; sign-up is completely free

Creating an Appwrite project

After registering on the Appwrite cloud platform, we will be redirected to an onboarding page where we will have to create a new project. We will fill in our preferred project name and ID (optional as ID can be autogenerated), then select Create Project.

create-project

After creating a new project, we must register our application to a specific platform within our project. Therefore, in the Add platform area of the Home section, we will select the Flutter App button and select our preferred operating system (in this case, Android). Then, we will fill in the application and package names (the package name is in the app-level build.gradle file).

platform
Flutter platform

Getting started

We will start by cloning the project repository to our PC. This repository contains the template and code we will use for the project. To clone the repository, run the command below:



git clone https://github.com/muyiwexy/google_auth_flutter.git


Enter fullscreen mode Exit fullscreen mode

After the cloning process, we will run the command flutter pub get to load all the packages used in the project to our PC.

Finally, we will run the project using the command flutter run and we should have the result below:

template

To use our Appwrite instance within our Flutter app, we need to connect our project to Appwrite. This process differs from the emulator's OS (Android or IOS).

iOS
First, obtain the bundle ID by going to the project.pbxproj file (ios > Runner.xcodeproj > project.pbxproj) and searching for the PRODUCT_BUNDLE_IDENTIFIER.

Now, head to the Runner.xcworkspace folder in the applications iOS folder in the project directory on Xcode. To select the runner target, choose the Runner project in the Xcode project navigator and find the Runner target. Then, select General and IOS 11.0 in the deployment info section as the target.

Android
For Android, copy the XML script below and paste it below the activity tag in the Androidmanifest.xml file (to find this file, head to android > app > src > main).

Note: change [PROJECT-ID] to the ID used when creating the Appwrite project.

Enabling Google OAuth2 provider
In order to use Google as a provider in Appwrite, we will need to have it enabled. To do this, we will head to Auth > Settings. We will scroll to Google and check the enabled switch within the settings area. We are also required to fill in the App ID and secret, but we will do that later as we initially need to set up Google OAuth.

Setting up Google OAuth 2.0
To set up, we will head to the Google API console page and head to API and Services within our project (we must create a new project if we do not have one).

api and services

Next, we select Credentials, followed by clicking on CREATE CREDENTIALS. Doing this will show a dropdown with some options, and we will proceed to select OAuth client ID.

credentials

Note: If it is your first time creating a client ID, you will need to configure your consent screen, which you won’t be required to do again after.

When creating a new OAuth Client ID, we will follow the configurations below:

  • Application Type - Web Application
  • Name - (choose preferred name)
  • Authorized JavaScript origins
  • Authorized redirect URIs
    • URIs - paste URL from the Google OAuth provider provided by Appwrite

client id for web application

After filling in the prompts on the page, we select save. Then we will get a splash screen showing our client ID and secret.

credentials

We will then head back to the Google OAuth provider page, paste in the Client ID and secret in the App ID and secret section, respectively, and click update. That is all, and we have successfully enabled Appwrite as our OAuth2 client.

Google OAuth2 provider and Flutter
This project utilizes the provider package for its state management. In the util.dart file, we will create an Appconstants class to serve as placeholders for some important constants, such as our Appwrite endpoint and ProjectID. Next, create a ChangeNotifier class called AppProvider. This class initializes the client and account instance from Appwrite. Next, create a function called socialSignIn which takes in the OAuth2 provider as a string and context. This function will use the Account API to create a new OAuth2 session on Appwrite and run the condition that if an account is successfully created, it redirects to a new page by setting _isLoggedin to true.



import 'package:appwrite/appwrite.dart';
import 'package:flutter/material.dart';
import 'package:google_auth/screens/home.dart';

class Appconstants {
  static const String endpoint = "<endpoint or hostname>";
  static const String projectid = "<project ID>";
}

class AppProvider extends ChangeNotifier {
  Client client = Client();
  late Account account;
  late bool _isLoggedIn;
  bool get isLoggedIn => _isLoggedIn;
  AppProvider() {
    _isLoggedIn = true;
    initialize();
  }
  initialize() {
    client
      ..setProject(Appconstants.projectid)
      ..setEndpoint(Appconstants.endpoint);
    account = Account(client);
    checkLogin();
  }
  checkLogin() async {
    try {
      await account.get();
    } catch (_) {
      _isLoggedIn = false;
      notifyListeners();
    }
  }
  socialSignIn(String provider, context) async {
    await account
        .createOAuth2Session(
      provider: provider,
      success: "",
      failure: "",
    )
        .then((response) {
      _isLoggedIn = true;
      notifyListeners();
    }).catchError((e) {
      _isLoggedIn = false;
      notifyListeners();
    });
  }
}


Enter fullscreen mode Exit fullscreen mode

To use this code from our ChangeNotifier class, we will create a UI consisting of a button and an alternate screen called Homepage, which we will route to after successfully running the socialSignIn function. Therefore, in our lib folder, create an alternate folder called screens and create two files in it, user_reg.dart and home.dart.

The user_reg.dart screen’s UI will contain an elevated button in which its onPressed property triggers the socialSignIn function in the ChangeNotifier class.



import 'package:flutter/material.dart';
import 'package:google_auth/util.dart';
import 'package:provider/provider.dart';
class UserRegistration extends StatefulWidget {
  const UserRegistration({super.key, required this.title});
  final String title;
  @override
  State<UserRegistration> createState() => _UserRegistrationState();
}
class _UserRegistrationState extends State<UserRegistration> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: IntrinsicWidth(
          child: Container(
            padding: const EdgeInsets.all(20.0),
            decoration: const BoxDecoration(
              color: Colors.blueGrey,
              borderRadius: BorderRadius.all(Radius.circular(20.0)),
            ),
            child: ElevatedButton.icon(
              onPressed: () {
                final state = Provider.of<AppProvider>(context, listen: false);
                state.socialSignIn("google", context);
              },
              icon: const Icon(Icons.g_mobiledata),
              label: const Text("Sign in with Google"),
            ),
          ),
        ),
      ),
    );
  }
}


Enter fullscreen mode Exit fullscreen mode

For the home.dart file, we will have a StatefulWidget called Homepage consisting of text at the center of the page.



import 'package:flutter/material.dart';
class Homepage extends StatefulWidget {
  const Homepage({super.key});
  @override
  State<Homepage> createState() => _HomepageState();
}
class _HomepageState extends State<Homepage> {
  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
        child: Text("data"),
      ),
    );
  }
}


Enter fullscreen mode Exit fullscreen mode

When we run the app, we should have our results as below:

result

Conclusion

This post showed how to use Google as a provider using Appwrite as an OAuth client. Appwrite utilizes Google as a provider and serves as a client for 35 more providers. Thus, creating a vast plain of knowledge to explore.

Here are some resources to aid the learning journey:

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .