---
title: Add "Sign in with Apple" to your Flutter app
description: Learn how to add native Sign in with Apple to your Clerk Flutter app on iOS.
---

<Info>
  **Before you start:**

  - [A Clerk application is required.](https://clerk.com/docs/getting-started/quickstart/setup-clerk)
  - [An Apple Developer account is required.](https://developer.apple.com/)
</Info>

<Info>
Native Sign in with Apple is only available on **iOS**. On Android, use the browser-based OAuth flow instead — call `ssoSignIn(context, Strategy.oauthApple)` as described in the [authentication flows reference](/reference/authentication-flows#sign-in-with-oauth).
</Info>

This guide explains how to add native Sign in with Apple to your Flutter app using Clerk. The native approach uses Apple's platform SDK to obtain an ID token directly, which is then passed to Clerk for authentication.

If you only need browser-based OAuth (a WebView flow that doesn't require additional packages), you can call `ssoSignIn(context, Strategy.oauthApple)` directly — see the [authentication flows reference](/reference/authentication-flows#sign-in-with-oauth). The steps below cover the native ID token approach.

<Steps>
<Step title="Enable Apple as a social connection">

1. In the Clerk Dashboard, navigate to the [**SSO connections**](https://dashboard.clerk.com/~/user-authentication/sso-connections) page.
1. Select **Add connection** and select **For all users**.
1. In the **Choose provider** dropdown, select **Apple**.
1. Toggle on **Enable for sign-up and sign-in** and select **Save**.
</Step>

<Step title="Add the Sign in with Apple capability in Xcode">

1. Open your Flutter project's iOS workspace in Xcode (`ios/Runner.xcworkspace`).
1. Select the **Runner** target, then open the **Signing & Capabilities** tab.
1. Select **+ Capability** and add **Sign In with Apple**.

<Info>
Sign in with Apple works on both iOS Simulators and physical devices. However, simulators have limited support — physical devices provide full functionality including biometric authentication (Face ID / Touch ID).
</Info>
</Step>

<Step title="Install dependencies">

Add the `sign_in_with_apple` and `uuid` packages to your `pubspec.yaml`:

```sh title="Terminal"
flutter pub add sign_in_with_apple uuid
```
</Step>

<Step title="Implement Sign in with Apple">

### Use Clerk's pre-built UI

If you're using `ClerkAuthentication`, no additional code is required. Once Apple is enabled as a social connection in the Clerk Dashboard, the **Sign in with Apple** button is rendered automatically.

```dart
ClerkAuthentication()
```

### Use a custom flow

For custom UI, use `sign_in_with_apple` to obtain an ID token and pass it to Clerk using `idTokenSignIn`.

```dart
import 'package:clerk_auth/clerk_auth.dart' as clerk;
import 'package:clerk_flutter/clerk_flutter.dart';
import 'package:sign_in_with_apple/sign_in_with_apple.dart';
import 'package:uuid/uuid.dart';

Future<void> signInWithApple(BuildContext context) async {
  final authState = ClerkAuth.of(context);

  // Request Apple ID credentials with a secure nonce
  final credential = await SignInWithApple.getAppleIDCredential(
    nonce: const Uuid().v4(),
    scopes: [
      AppleIDAuthorizationScopes.email,
      AppleIDAuthorizationScopes.fullName,
    ],
  );

  final token = credential.identityToken;
  if (token == null) return;

  // Pass the ID token to Clerk
  await authState.idTokenSignIn(
    provider: clerk.IdTokenProvider.apple,
    token: token,
  );

  // If this is a new user, a sign-up object may be returned with missing fields
  if (authState.signUp case clerk.SignUp signUp
      when signUp.missingFields.isNotEmpty) {
    await authState.attemptSignUp(
      firstName: signUp.missing(clerk.Field.firstName)
          ? credential.givenName
          : null,
      lastName: signUp.missing(clerk.Field.lastName)
          ? credential.familyName
          : null,
    );
  }
}
```

<Warning>
Apple only provides the user's full name (`givenName` and `familyName`) during their **first** app authorization. On subsequent sign-ins, this data is not returned. Store the name when you first receive it and treat it as optional thereafter.
</Warning>

<Info>
If your Clerk instance has [legal acceptance](https://clerk.com/docs/guides/secure/legal-compliance) enabled, `signUp.missingFields` will also contain `clerk.Field.legalAccepted` and `attemptSignUp` will fail unless you pass `legalAccepted: true`. Collect consent from the user first (for example, a checkbox agreeing to your Terms of Service), then pass it conditionally: `legalAccepted: signUp.missing(clerk.Field.legalAccepted) ? true : null`.
</Info>
</Step>
</Steps>

## Hide My Email

Apple's **Hide My Email** feature lets users share a private relay email address instead of their real one. Clerk supports this out of the box, but you may need to configure [email communication through Apple's private relay](https://developer.apple.com/documentation/sign_in_with_apple/communicating_using_the_private_relay_service) in your Apple Developer account if your app sends transactional emails.
