Add "Sign in with Apple" to your Flutter app
Learn how to add native Sign in with Apple to your Clerk Flutter app on iOS.
Before you start:
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.
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. The steps below cover the native ID token approach.
Enable Apple as a social connection
- In the Clerk Dashboard, navigate to the SSO connections page.
- Select Add connection and select For all users.
- In the Choose provider dropdown, select Apple.
- Toggle on Enable for sign-up and sign-in and select Save.
Add the Sign in with Apple capability in Xcode
- Open your Flutter project's iOS workspace in Xcode (
ios/Runner.xcworkspace). - Select the Runner target, then open the Signing & Capabilities tab.
- Select + Capability and add Sign In with Apple.
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).
Install dependencies
Add the sign_in_with_apple and uuid packages to your pubspec.yaml:
flutter pub add sign_in_with_apple uuidImplement 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.
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.
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,
);
}
}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.
If your Clerk instance has legal acceptance 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.
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 in your Apple Developer account if your app sends transactional emails.