Skip to main content
Docs

This guide will teach you how to add native Sign in with Apple to your Clerk Expo application.

Important

If you're using native componentsExpo Icon, Sign in with Apple is automatically available in <AuthView />Expo Icon when Apple is enabled as a social connection in the Clerk Dashboard. This guide applies to applications that implement a custom sign-in UI using the useSignInWithApple()Expo Icon hook.

Note

Sign in with Apple works on both iOS Simulators and physical devices. However, physical devices provide full functionality including biometric authentication (Face ID/Touch ID), while simulators have limited support. Always test on a physical device before releasing to production.

Add your Native Application

Add your iOS application to the Native applications page in the Clerk Dashboard. You will need your iOS app's App ID Prefix (Team ID) and Bundle ID.

Enable Apple as a social connection

  1. In the Clerk Dashboard, navigate to the SSO connections page.
  2. Select Add connection and select For all users.
  3. Select Apple from the provider list.
  4. Ensure that Enable for sign-up and sign-in is toggled on.

Note

Apple provides a privacy feature called Hide My Email, allowing users to sign in to your app with Apple without disclosing their actual email addresses. Instead, your instance receives an app-specific email address that forwards any emails to the user's real address. To be able to send emails properly to users with hidden addresses, you must configure an additional setting in the Apple Developer portal. See Configure Email Source for Apple Private Relay for more information.

Important

If you're using <AuthView />Expo Icon from @clerk/expo/native, you do not need to install expo-apple-authentication, expo-crypto, or use the useSignInWithApple() hook — <AuthView /> handles the sign-in flow automatically.

The useSignInWithApple()Expo Icon hook requires the following packages:

  • expo-apple-authentication provides access to Apple's native Sign in with Apple functionality.
  • expo-crypto is used for generating secure nonces during the authentication flow.
terminal
npx expo install expo-apple-authentication expo-crypto
terminal
pnpm dlx expo install expo-apple-authentication expo-crypto
terminal
yarn dlx expo install expo-apple-authentication expo-crypto
terminal
bun x expo install expo-apple-authentication expo-crypto

Add expo-apple-authentication to your app config

Add the expo-apple-authentication plugin to your app.json or app.config.js.

app.json
{
  "expo": {
    "plugins": ["expo-apple-authentication"]
  }
}
app.config.js
export default {
  expo: {
    plugins: ['expo-apple-authentication'],
  },
}

Important

If you're using <AuthView />Expo Icon from @clerk/expo/native, you do not need to install expo-apple-authentication, expo-crypto, or use the useSignInWithApple() hook — <AuthView /> handles the sign-in flow automatically.

  1. The following example demonstrates how to use the useSignInWithApple()Expo Icon hook to manage the Apple authentication flow. Because the useSignInWithApple() hook automatically manages the between sign-up and sign-in, you can use this component for both your sign-up and sign-in pages.

    components/AppleSignInButton.tsx
    import { useSignInWithApple } from '@clerk/expo/apple'
    import { useRouter } from 'expo-router'
    import { Alert, Platform, Pressable, StyleSheet, Text, View } from 'react-native'
    
    export function AppleSignInButton({ onSignInComplete }: { onSignInComplete?: () => void }) {
      const { startAppleAuthenticationFlow } = useSignInWithApple()
      const router = useRouter()
    
      // Only show on iOS
      if (Platform.OS !== 'ios') return null
    
      const handleAppleSignIn = async () => {
        try {
          const { createdSessionId, setActive } = await startAppleAuthenticationFlow()
    
          if (createdSessionId && setActive) {
            await setActive({ session: createdSessionId })
    
            if (onSignInComplete) {
              onSignInComplete()
            } else {
              router.replace('/')
            }
          }
        } catch (err: any) {
          if (err.code === 'ERR_REQUEST_CANCELED') return
    
          Alert.alert('Error', err.message || 'An error occurred during Apple sign-in')
          console.error('Sign in with Apple error:', JSON.stringify(err, null, 2))
        }
      }
    
      return (
        <View style={styles.container}>
          <Pressable
            style={({ pressed }) => [styles.button, pressed && styles.buttonPressed]}
            onPress={handleAppleSignIn}
          >
            <Text style={styles.buttonText}>Continue with Apple</Text>
          </Pressable>
        </View>
      )
    }
    
    const styles = StyleSheet.create({
      container: {
        width: '100%',
        marginVertical: 8,
      },
      button: {
        backgroundColor: '#000',
        paddingVertical: 14,
        paddingHorizontal: 24,
        borderRadius: 8,
        alignItems: 'center',
      },
      buttonPressed: {
        opacity: 0.7,
      },
      buttonText: {
        color: '#fff',
        fontSize: 16,
        fontWeight: '600',
      },
    })
  2. Then, add the <AppleSignInButton /> component to your sign-in or sign-up page.

Create a native build

Create a native build with EAS Build or a local prebuild, since Apple Authentication is not supported in Expo Go.

terminal
# Using EAS Build
eas build --platform ios

# Or using local prebuild
npx expo prebuild && npx expo run:ios --device

Feedback

What did you think of this content?

Last updated on