Skip to content
This repository has been archived by the owner on Sep 29, 2023. It is now read-only.

add apple oauth provider documentation #418

Open
wants to merge 1 commit into
base: oauth-providers
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
351 changes: 351 additions & 0 deletions app/views/docs/oauth-providers/apple.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,351 @@
# Apple provider

Appwrite allows you to authenticate users using their Apple account through the Apple OAuth2 provider. OAuth authentication is a great way to reduce friction for your users and increase user conversion by simplifying the signup process. Apple has multiple types of OAuth2 authentication, including Sign in with Apple, iCloud Keychain, and physical security keys. This guide will walk you through integrating the **Sign in with Apple authorization code grant type only**. You can learn more about Appwrite’s other OAuth2 providers [here](placeholder link).

> Please note that you will need to have a paid **Apple Developer Account** to use *Sign in with Apple*. This will allow you to use Certificates, Identifiers & Profiles to set up identifiers and keys. You can learn more about Apple Developer Accounts [here](https://developer.apple.com/support/app-account/#:~:text=Enrolling%20in%20the%20Apple%20Developer%20Program%20as%20an,and%20tap%20or%20click%20the%20Subscribe%20button.%20).

## Enabling the Apple provider
Before using Apple to authenticate users, you must enable the provider in your Appwrite console.
1. Navigate to your Appwrite project
2. Navigate to **Auth** > **Settings**
3. Find and open the OAuth provider
4. In the **Apple OAuth2 Settings** modal, use the toggle to enable the provider

Don’t close this modal. We’ll need to create a *Sign in with Apple* private key and fill out the following fields in the modal:
- **Bundle ID**: You can find your [Bundle ID](https://developer.apple.com/documentation/appstoreconnectapi/bundle_ids) in the Apple Developer Portal under the Identifiers section.
- **Team ID**: You can find your [Team ID](https://developer.apple.com/help/account/manage-your-team/locate-your-team-id) in the Apple Developer Portal under the Membership section.
- **Key ID**: You can find your [Key ID](https://developer.apple.com/help/account/manage-keys/get-a-key-identifier) in the Apple Developer Portal under the Keys section.
- **P8 file**: You can download the P8 file from the Apple Developer Portal prior to creating the key. You can learn more about creating a key (make sure to open the file in VSCode to view its contents).

To learn more, visit this Apple documentation for setting up [Sign in with Apple](https://developer.apple.com/sign-in-with-apple/get-started/).

Once you have filled out these fields and enabled the provider, you can start using Sign in with Apple to authenticate users with Appwrite.

## Implementing *Sign in with Apple*
To implement **Sign in with Apple**, you need to follow these steps:
1. Add a Sign in with Apple button to your app or website
2. When a user clicks on this button, redirect them to the Sign in with Apple authorization page
3. After successful authentication, use the authorization code returned by Sign in with Apple to exchange it for an access token and ID token from Appwrite’s server-side API

## Authenticating
You can use any of the Appwrite Client SDKs to authenticate users with their Apple accounts.

### Web
When a user calls the [Create OAuth2 Session](https://appwrite.io/docs/client/account#accountCreateOAuth2Session) endpoint in your web app, they will be taken to Apple's OAuth page to complete their login.

After authenticating, they'll be redirected back to your app using either the `success` or `failure` URLs provided. To provide the best experience to your users, make sure to **implement and provide both routes** to prompt the user about successful and failed authentication attempts.

```js
import { Client, Account } from "appwrite";

const client = new Client();

const account = new Account(client);

client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('[PROJECT_ID]') // Your Project ID
;

// Go to the OAuth provider login page
account.createOAuth2Session('apple', '[LINK_ON_SUCCESS]', '[LINK_ON_FAILURE]');
```

### Flutter
You can use OAuth in your Flutter application, but some platforms like Android and Apple requires additional configuration to enable the OAuth callback, so the your users can be redirected back to your app.

#### Android OAuth callback

In order to capture the Appwrite OAuth callback url, the following activity needs to be added inside the `<application>` tag, along side the existing `<activity>` tags in your `AndroidManifest.xml`. Be sure to replace the `[PROJECT_ID]` string with your actual Appwrite project ID. You can find your Appwrite project ID in your project settings screen in your Appwrite console.

```xml
<manifest ...>
...
<application ...>
...
<!-- Add this inside the `<application>` tag, along side the existing `<activity>` tags -->
<activity android:name="io.appwrite.views.CallbackActivity" android:exported="true">
<intent-filter android:label="android_web_auth">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="appwrite-callback-[PROJECT_ID]" />
</intent-filter>
</activity>
</application>
</manifest>
```

#### Apple

In order to capture the Appwrite OAuth callback url, the following URL scheme needs to added to your `Info.plist`. Be sure to replace the `[PROJECT_ID]` string with your actual Appwrite project ID. You can find your Appwrite project ID in your project settings screen in your Appwrite console.

```xml
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>io.appwrite</string>
<key>CFBundleURLSchemes</key>
<array>
<string>appwrite-callback-[PROJECT_ID]</string>
</array>
</dict>
</array>
```

To authenticate a user in your Flutter application, use the [Create OAuth2 Session](https://appwrite.io/docs/client/account?sdk=flutter-default#accountCreateOAuth2Session) endpoint.

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

void main() async {
final client = new Client();
final account = new Account(client);

client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('[PROJECT_ID]') // Your Project ID
;

// OAuth Login, for simplest implementation you can leave both success and
// failure link empty so that Appwrite handles everything.
await account.createOAuth2Session(provider: 'apple');

}
```

### Android (Kotlin)
Before you can add OAuth to your Android app, you need to setup a callback for your OAuth flow.

In order to capture the Appwrite OAuth callback url, the following activity needs to be added inside the `<application>` tag, along side the existing `<activity>` tags in your `AndroidManifest.xml`. Be sure to replace the `[PROJECT_ID]` string with your actual Appwrite project ID. You can find your Appwrite project ID in your project settings screen in your Appwrite console.

```xml
<manifest ...>
...
<application ...>
...
<!-- Add this inside the `<application>` tag, along side the existing `<activity>` tags -->
<activity android:name="io.appwrite.views.CallbackActivity" android:exported="true">
<intent-filter android:label="android_web_auth">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="appwrite-callback-[PROJECT_ID]" />
</intent-filter>
</activity>
</application>
</manifest>
```

To authenticate a user in your Android application, use the [Create OAuth2 Session](https://appwrite.io/docs/client/account?sdk=android-kotlin#accountCreateOAuth2Session) endpoint.

```kotlin
import io.appwrite.Client
import io.appwrite.services.Account

val client = Client(context)
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("[PROJECT_ID]") // Your Project ID

val account = Account(client)

account.createOAuth2Session(provider = "apple")
```

### Android (Java)
Before you can add OAuth to your Android app, you need to setup a callback for your OAuth flow.

In order to capture the Appwrite OAuth callback url, the following activity needs to be added inside the `<application>` tag, along side the existing `<activity>` tags in your `AndroidManifest.xml`. Be sure to replace the `[PROJECT_ID]` string with your actual Appwrite project ID. You can find your Appwrite project ID in your project settings screen in your Appwrite console.

```xml
<manifest ...>
...
<application ...>
...
<!-- Add this inside the `<application>` tag, along side the existing `<activity>` tags -->
<activity android:name="io.appwrite.views.CallbackActivity" android:exported="true">
<intent-filter android:label="android_web_auth">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="appwrite-callback-[PROJECT_ID]" />
</intent-filter>
</activity>
</application>
</manifest>
```

To authenticate a user in your Android application, use the [Create OAuth2 Session](https://appwrite.io/docs/client/account?sdk=android-java#accountCreateOAuth2Session) endpoint.

```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Account;

Client client = new Client(context)
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("[PROJECT_ID]"); // Your Project ID

Account account = new Account(client);

account.createOAuth2Session(
"apple",
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}

Log.d("Appwrite", result.toString());
})
);
```

### iOS (Swift)

In order to capture the Appwrite OAuth callback url, the following URL scheme needs to added to your `Info.plist`
```xml
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>io.appwrite</string>
<key>CFBundleURLSchemes</key>
<array>
<string>appwrite-callback-[PROJECT_ID]</string>
</array>
</dict>
</array>
```

If you're using UIKit, you'll also need to add a hook to your `SceneDelegate.swift` file to ensure cookies work correctly.
```swift
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url,
url.absoluteString.contains("appwrite-callback") else {
return
}
WebAuthComponent.handleIncomingCookie(from: url)
}
```

To authenticate a user in your Android application, use the [Create OAuth2 Session](https://appwrite.io/docs/client/account?sdk=apple-default#accountCreateOAuth2Session) endpoint.

```swift
import Appwrite

let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("[PROJECT_ID]") // Your Project ID

let account = Account(client)

let success = try await account.createOAuth2Session(provider: "apple")
```

## Refreshing the OAuth2 session
OAuth2 sessions expire to protect from security risks. This means, OAuth2 sessions should be refreshed to keep the user authenticated. You can do this by calling the [Update OAuth Session](https://appwrite.io/docs/client/account#accountUpdateSession) endpoint when ever your user visits your app.

### Web
```js
import { Client, Account } from "appwrite";

const client = new Client();

const account = new Account(client);

client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('[PROJECT_ID]') // Your Project ID
;

// Updates current session
const promise = account.updateSession('current');

promise.then(function (response) {
console.log(response); // Success
}, function (error) {
console.log(error); // Failure
});
```

### Flutter

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

void main() async {
final client = new Client();
final account = new Account(client);

client
.setEndpoint('https://cloud.appwrite.io/v1') // YOUR API Endpoint
.setProject('[PROJECT_ID]'); // Your Project ID

// Simplest implementation of updating an OAuth2 session
// prints Session Object value on success and error message on failure
try {
final future = await account.updateSession(sessionId: 'current');
print(future.toMap()); // Success
} on AppwriteException catch(e){
print(e.message); // Failure
}
}
```

### Android (Kotlin)
```kotlin
import io.appwrite.Client
import io.appwrite.services.Account

val client = Client(context)
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("[PROJECT_ID]") // Your Project ID

val account = Account(client)

val response = account.updateSession(sessionId = "current")
```

### Android (Java)
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Account;

Client client = new Client(context)
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("[PROJECT_ID]"); // Your Project ID

Account account = new Account(client);

account.updateSession(
"current"
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}

Log.d("Appwrite", result.toString());
})
);
```

### iOS (Swift)
``` swift
import Appwrite

let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("[PROJECT_ID]") // Your Project ID

let account = Account(client)

let session = try await account.updateSession(sessionId: "current")
```