useSignInWithApple() - Native hooks - Expo | Clerk Docs

useSignInWithApple()

Before you start

This hook is only available on iOS devices and requires a native build. It will not work with Expo Go.

The useSignInWithApple() hook provides native Sign in with Apple⁠ functionality for iOS devices. It handles the ID token exchange with Clerk's backend and automatically manages the transfer flow⁠ between sign-up and sign-in.

Installation

This hook requires the following peer dependencies:

npx expo install expo-apple-authentication expo-crypto

Returns

The useSignInWithApple() hook returns the startAppleAuthenticationFlow() method, which you can use to initiate the native Apple authentication flow.

startAppleAuthenticationFlow()

startAppleAuthenticationFlow() has the following function signature:

function startAppleAuthenticationFlow(
  startAppleAuthenticationFlowParams?: StartAppleAuthenticationFlowParams,
): Promise<StartAppleAuthenticationFlowReturnType>

Parameters

startAppleAuthenticationFlow() accepts the following parameters (StartAppleAuthenticationFlowParams):

Returns

startAppleAuthenticationFlow() returns the following:

Examples

Reusable component

The following example demonstrates how to use the useSignInWithApple() hook to manage the Apple authentication flow.

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 }) {
  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 });
        onSignInComplete ? onSignInComplete() : router.replace('/');
      }
    } catch (err) {
      if (err.code === 'ERR_REQUEST_CANCELED') return;
      Alert.alert('Error', err.message || 'An error occurred during Apple sign-in');
    }
  };

return (
    <View style={styles.container}>
      <Pressable onPress={handleAppleSignIn}>
        <Text>Continue with Apple</Text>
      </Pressable>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { width: '100%', marginVertical: 8 },
});

With custom metadata

The following example demonstrates how to pass custom metadata that will be saved to the user's unsafe metadata during sign-up.

import { useRouter } from 'expo-router';
import { useSignInWithApple } from '@clerk/expo/apple';
import { Alert, Platform, TouchableOpacity, Text } from 'react-native';

export default function SignInPage() {
  const { startAppleAuthenticationFlow } = useSignInWithApple();
  const router = useRouter();
  
  if (Platform.OS !== 'ios') return null;

const onAppleSignInPress = async () => {
    try {
      const { createdSessionId, setActive } = await startAppleAuthenticationFlow({
        unsafeMetadata: {
          referralSource: 'ios-app',
          signupDate: new Date().toISOString(),
        },
      });

if (createdSessionId && setActive) {
        await setActive({ session: createdSessionId });
        router.replace('/');
      } 
    } catch (err) {
      if (err.code === 'ERR_REQUEST_CANCELED') return;
      Alert.alert('Error', err.message || 'An error occurred during Apple sign-in');
    }
  };

return <TouchableOpacity onPress={onAppleSignInPress}><Text>Sign in with Apple</Text></TouchableOpacity>;
}

Error handling

The useSignInWithApple() hook may throw errors in the following scenarios:

Always wrap calls to startAppleAuthenticationFlow() in a try/catch block, and handle the ERR_REQUEST_CANCELED error separately.