Adding authentication to your apps using Apple OAuth 2.0
Tags: appwrite, flutter, appleoauth, oauth
Published: 2023-08-01 08:42:20

Apple’s iOS is one of the leading mobile operating systems, with an estimated market share of about 20.5% of the [global smartphone market](https://www.statista.com/statistics/236031/market-share-of-ios-in-global-smartphone-os-shipments/). Beyond its usability, timely updates, security, and privacy features, an integral part of the system is the **Apple ID**; an identifier for accessing all Apple products and services.

In 2019, Apple [announced](https://developer.apple.com/videos/play/wwdc2019/706/) the **Sign in with Apple** functionality. A fast, secure, and easy way for users to sign in to applications and websites. The functionality has helped developers seamlessly build software without the associated authentication and authorization overheads.

In this post, we will learn how to set up OAuth 2.0 social login in a Flutter application using Apple as the provider. The project repository can be found [here](https://github.com/Mr-Malomz/flutter_auth_apple).

## Prerequisites

To fully grasp the concepts presented in this tutorial, the following are required:

-   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)[ign-up](https://cloud.appwrite.io/register) is completely free
-   Apple developer [account](https://developers.apple.com/)

## Getting started

To get started, we need to clone the project by navigating to the desired directory and running the command below:

```bash
git clone https://github.com/Mr-Malomz/flutter_auth_apple
```

## Running the project

First, we need to install the project dependencies by running the command below:

```bash
flutter pub get
```

Then, run the project using the following command:

```bash
flutter run
```

The command above will run the application on the selected device.

![Login screen](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1688678597821_Screenshot+2023-07-06+at+22.23.00.png)

## Set up a project on Appwrite

To get started, we need to log into our Appwrite console, click the **Create project** button, input `flutter_auth_apple` as the name, and then **Create**.

![Create project](https://paper-attachments.dropboxusercontent.com/s_C9210607DAFF6D80615947ED6BE237716E98BADEF0416B60FACF081B1CAEFB80_1687518026974_Screenshot+2023-06-23+at+11.38.55.png)

**Add platform support**

To add support for our Flutter app, navigate to the **Home** menu and click the **Flutter App** button.

![Add platform](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687616042885_Screenshot+2023-06-23+at+21.51.19.png)

Next, we must modify the Flutter application as detailed below:

To obtain our Bundle ID, navigate to the path below:
**ios > Runner.xcodeproj > project.pbxproj**

Open the `project.pbxproj` file and search for `PRODUCT_BUNDLE_IDENTIFIER`.

![Select new Flutter app](https://paper-attachments.dropboxusercontent.com/s_1F2738109066A0A5582E754A3908A7FD06BE17296D17A867AFE208C1CA00E9C0_1671388862700_Screenshot+2022-12-18+at+01.30.54.png)

Finally, open the project directory on [Xcode](https://developer.apple.com/xcode/), open the `Runner.xcworkspace` folder in the app's iOS folder, select the **Runner** project in the Xcode project navigator, select the **Runner** target in the primary menu sidebar, and then select **iOS 11** in the deployment info’s target.

![Change deployment target](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1688678621237_Screenshot+2023-07-06+at+21.56.26.png)

**Enable Apple as the preferred OAuth 2.0 provider**

To do this, we must navigate to the **Auth** menu, click the **Settings** tab, and enable `Apple` as a provider.

![Navigate to the provider](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687616251008_Screenshot+2023-06-23+at+21.53.41.png)
![Apple OAuth](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687616261798_Screenshot+2023-06-24+at+15.17.01.png)

We will fill in the required details later. However, we must copy and keep the redirect **URI**, it will come in handy when setting up our application on the Apple developer portal.

![Copy URI](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687716646473_Screenshot+2023-06-24+at+15.18.04.png)

## Set up Apple OAuth 2.0

With our project partly configured on Appwrite, we must also set up our project on the Apple developer portal.

**Create App ID using Xcode**

An App ID is used to identify one or more applications in the development team. We must tie our application with an App ID on the platform. To get started, we need to first open the `ios` folder in our source code with Xcode.

![ios folder open on Xcode](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687619604785_Screenshot+2023-06-24+at+15.56.28.png)

Second, we must add **Sign in with Apple** capability to our App ID. To do this, navigate to the **Signing & Capabilities** tab, click the “**+ Capability**” button, search for `Sign in with Apple`, and double-click the result to add it.

![Add capability](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687619947376_Screenshot+2023-06-24+at+16.02.32.png)
![Added sign in](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687619947410_Screenshot+2023-06-24+at+16.09.02.png)

Lastly, we must modify our **Bundle Identifier** to a unique string by prefixing it with any letters of our choice and then change the **Team** to our Apple developer team.

![](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687620086773_Screenshot+2023-06-24+at+16.10.12.png)

On doing the step above, the system should automatically create an App ID for us. See details below.

![](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687620891167_Screenshot+2023-06-24+at+16.33.10.png)

**PS**: _We might get an error about registering the bundle identifier; we can resolve this by prefixing the_ **_Bundle identifier_** _to another set of unique strings. Beyond the use of Xcode, we can also create an App ID using our_ [_Apple developer portal_](https://developer.apple.com/account/resources/identifiers/list/bundleId)_._

**Create a Service ID**

A Service ID is used to identify the applications or websites interacting with Apple web services. To do this, we need to log into the portal, navigate to the **Identifiers** screen, change to **Services IDs**, and **Register a Services ID**.  
https://developer.apple.com/account/resources/identifiers/list/serviceId

![Account](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687622936847_Screenshot+2023-06-24+at+01.19.09.png)
![Create Service ID](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687622936881_Screenshot+2023-06-24+at+01.24.47.png)

Select **Service IDs** and **Continue**.

![Continue](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687623074778_Screenshot+2023-06-24+at+01.26.28.png)

Input `flutter auth apple` as the **Description**, input another unique ID as the Identifier, and **Register**. We also need to keep the inputted **Identifier** as it will come in handy when we finish setting up our application on Appwrite.

![Register](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687623214599_Screenshot+2023-06-24+at+01.31.56.png)

View the details of the newly created Service ID, enable the `Sign in with Apple` and **Configure**.

![Click details](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687623849170_Screenshot+2023-06-24+at+01.34.21.png)
![Enable and configure](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687623849198_Screenshot+2023-06-24+at+01.36.12.png)

Select the **App ID** we configured using Xcode earlier, input `appwrite.io` as the **Domain**, input the **Redirect URI** we copied from Appwrite earlier as the **Redirect URLs**, **click Next**, and **Save**.

![Input](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687623997566_Screenshot+2023-06-24+at+01.40.05.png)
![](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687623997617_Screenshot+2023-06-24+at+01.43.40.png)

**Create a Key ID**

We need to create a key ID that our application will use to securely communicate with Apple services. To do this, navigate to the **Keys** tab and **Create**.

![](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687624758210_Screenshot+2023-06-24+at+01.45.35.png)

Input `flutterAuthApple` as the **Key Name**, enable the `Sign in with Apple` option, and **Configure**.

![configure](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687624813117_Screenshot+2023-06-24+at+01.49.40.png)

Select the **App ID** we created earlier and **Save**.

![Select and Save](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687624950767_Screenshot+2023-06-24+at+01.52.52.png)

**Register** the key, copy the **Key ID**, and **Download** the `Key File`.

![Register the app](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687625235294_Screenshot+2023-06-24+at+01.55.58.png)
![Copy and download](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687625353753_Screenshot+2023-06-24+at+01.56.36.png)

## Putting it together on Appwrite

With our application configured on Apple, we need to create a link to it on Appwrite. To do this, we must update the Apple provider details on Appwrite with the copied **Service ID Identifier**, **Key ID**, **Team ID**, **P8 File**, and **Update**.

![Add credentials](https://paper-attachments.dropboxusercontent.com/s_A947A84E466F3A1129628A6A175CCC5CBAF61907861234B6B59949686454755F_1687625557498_Screenshot+2023-06-24+at+15.17.01.png)

We can get our **Team ID** by navigating to the `Membership details` of the [Apple Developer account](https://developer.apple.com/account) section and the **P8 File** by opening the downloaded `Key File` in an editor.

## Integrating Apple OAuth 2.0 with Flutter using Appwrite

With all that done, let’s build the social login into our application. First, we need to create a class for storing our Appwrite credentials. To do this, we need to create a `utils.dart` file in the `lib` folder and add the snippet below:

```dart
class AppConstant {
  final String projectId = "REPLACE WITH PROJECT ID";
  final String endpoint = "https://cloud.appwrite.io/v1";
}
```

**PS**: _We can get our Project ID from the Appwrite console._

Secondly, we need to create a service file to separate the application core logic from the UI. To do this, we need to create an `auth_service.dart` file in the same `lib` folder and add the snippet below:

```dart
import 'package:appwrite/appwrite.dart';
import 'package:flutter_auth_apple/utils.dart';

class AuthService {
  Client _client = Client();
  late Account _account;

  AuthService() {
    _init();
  }

  //initialize the application
  _init() async {
    _client
        .setEndpoint(AppConstant().endpoint)
        .setProject(AppConstant().projectId);

    _account = Account(_client);
  }

  Future loginWithApple() async {
    try {
      return await _account.createOAuth2Session(provider: 'apple');
    } catch (e) {
      throw Exception('Error login into Apple!');
    }
  }
}
```

The snippet above does the following:

-   Imports the required dependencies
-   Creates an `AuthService` class with `_client` and `_account` properties to connect to the Appwrite instance
-   Creates an `_init` method that configures Appwrite using the properties
-   Creates a `loginWithApple` method that uses the `_account` property to log in with OAuth 2.0 using `apple` as the provider

Lastly, we need to modify the `login.dart` file inside the `screens` folder to use the service.

```dart
import 'package:flutter/material.dart';
import 'package:flutter_auth_apple/auth_service.dart';

class Login extends StatefulWidget {
  const Login({Key? key}) : super(key: key);

  @override
  State<Login> createState() => _LoginState();
}

class _LoginState extends State<Login> {
  bool _isLoading = false;

  _loginWithApple() {
    setState(() {
      _isLoading = true;
    });
    AuthService()
        .loginWithApple()
        .then((value) => {
              setState(() {
                _isLoading = false;
              })
            })
        .catchError((e) {
      setState(() {
        _isLoading = false;
      });
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Error login into Apple!')),
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            const Text(
              "Appwrite + Apple Auth",
              style: TextStyle(
                fontWeight: FontWeight.bold,
                fontSize: 18.0,
              ),
            ),
            const SizedBox(height: 30),
            SizedBox(
              width: double.infinity,
              height: 45.0,
              child: TextButton(
                onPressed: _isLoading
                    ? null
                    : () {
                        _loginWithApple();
                      },
                style: ButtonStyle(
                  backgroundColor:
                      MaterialStateProperty.all<Color>(Colors.black),
                ),
                child: const Text(
                  'Sign in with Apple',
                  style: TextStyle(
                    color: Colors.white,
                    fontWeight: FontWeight.bold,
                    fontSize: 14.0,
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
```

The snippet above does the following:

-   **Lines** **1-2**: Import the required dependencies
-   **Line** **12**: Creates an `_isLoading` property to manage the application state
-   **Lines** **14-33**: Create a `_loginWithApple` method to log in users using the `AuthService().loginWithApple` service and set state accordingly
-   **Lines** **57-61**: Update the button to use the method created

With that done, we restart the application using the code editor or run the command below:

    flutter run

![](https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExYjE5cjMycnN1ZzA2NjR5ejgyeHZhOHFvYzU3dmo4M3c1Y2ZzeWlpZSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/OHUNVIJjJHo1qkcfsX/giphy.gif)

## Conclusion

This post detailed a step-by-step guide on how to add Apple OAuth 2.0 social login in a Flutter application using Appwrite. Beyond what was discussed above, the SDK also supports the `success`, `failure`, and `scope` `mechanism` for managing callbacks and the amount of user information requested from Apple.

These resources may also be helpful:

-   [Appwrite official documentation](https://appwrite.io/docs?utm_source=hackmamba&utm_medium=hackmamba-blog)
-   [Appwrite OAuth support](https://appwrite.io/docs/authentication#oauth?utm_source=hackmamba&utm_medium=hackmamba-blog)
-   [Apple developer account](https://developer.apple.com/)
-   [Configuration scope in Apple](https://developer.apple.com/documentation/sign_in_with_apple/clientconfigi/3230955-scope)