Implementing OAuth2 Clients with Flutter made simple
Tags: authentication, appwrite, flutter, google
Published: 2023-09-07 11:47:38

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](https://github.com/muyiwexy/google_auth_flutter.git) 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](https://flutter.dev/docs/get-started/install) installed
- [Xcode](https://developer.apple.com/xcode/) with a developer account
- Appwrite account; [s](https://cloud.appwrite.io/register?utm_source=hackmamba&utm_medium=hackmamba-blog)[ign-up](https://cloud.appwrite.io/register?utm_source=hackmamba&utm_medium=hackmamba-blog) is completely free
- A Gmail account; [s](https://accounts.google.com/signup/v2/createaccount?flowName=GlifWebSignIn&flowEntry=SignUp)[ign-up](https://accounts.google.com/signup/v2/createaccount?flowName=GlifWebSignIn&flowEntry=SignUp) 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](https://paper-attachments.dropboxusercontent.com/s_3B0C58D65C32A5F2630CE6F3891A8DC31B5D31A660AAF26159BA4792B7EA0BE3_1687283315023_create-project.png)


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](https://paper-attachments.dropboxusercontent.com/s_3B0C58D65C32A5F2630CE6F3891A8DC31B5D31A660AAF26159BA4792B7EA0BE3_1687289483183_platform.png)
![Flutter platform](https://paper-attachments.dropboxusercontent.com/s_3B0C58D65C32A5F2630CE6F3891A8DC31B5D31A660AAF26159BA4792B7EA0BE3_1687289483165_create-platform.png)

## 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:

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

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](https://paper-attachments.dropboxusercontent.com/s_3B0C58D65C32A5F2630CE6F3891A8DC31B5D31A660AAF26159BA4792B7EA0BE3_1687346748828_2023-06-21+12_23_26-Window.png)


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](https://developer.apple.com/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`).

{% embed https://gist.github.com/muyiwexy/f1a0f6c59329d25d37c353f34a4fa9aa %}

> 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](https://console.developers.google.com/) 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](https://paper-attachments.dropboxusercontent.com/s_3B0C58D65C32A5F2630CE6F3891A8DC31B5D31A660AAF26159BA4792B7EA0BE3_1687789913555_api+and+services.png)


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](https://paper-attachments.dropboxusercontent.com/s_3B0C58D65C32A5F2630CE6F3891A8DC31B5D31A660AAF26159BA4792B7EA0BE3_1687297495786_credentials.png)




> 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** 
    - URIs1 - https://cloud.appwrite.io
    - URIs2 - https://localhost
- **Authorized redirect URIs**
    - URIs - paste URL from the Google OAuth provider provided by Appwrite


![client id for web application](https://paper-attachments.dropboxusercontent.com/s_3B0C58D65C32A5F2630CE6F3891A8DC31B5D31A660AAF26159BA4792B7EA0BE3_1688578912987_2023-07-05+18_39_49-Window.png)


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](https://paper-attachments.dropboxusercontent.com/s_3B0C58D65C32A5F2630CE6F3891A8DC31B5D31A660AAF26159BA4792B7EA0BE3_1688124200330_credentials.png)


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`.

```javascript
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();
    });
  }
}
```
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.

```javascript
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"),
            ),
          ),
        ),
      ),
    );
  }
}
```

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

```javascript
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"),
      ),
    );
  }
}
```

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

![result](https://paper-attachments.dropboxusercontent.com/s_3B0C58D65C32A5F2630CE6F3891A8DC31B5D31A660AAF26159BA4792B7EA0BE3_1688142781419_ezgif.com-video-to-gif+11.gif)


   

## 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:

- [Appwrite official documentation](https://appwrite.io/docs?utm_source=hackmamba&utm_medium=hackmamba-blog)
- [Appwrite OAuth support](https://appwrite.io/docs/authentication#oauth)
[](https://hackmamba.io/blog/2023/02/how-to-quickly-add-github-login-to-your-flutter-application/)
- [How to Quickly Add GitHub Login to your Flutter Application](https://hackmamba.io/blog/2023/02/how-to-quickly-add-github-login-to-your-flutter-application/)