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):
- Name:
unsafeMetadata?- Type: SignUpUnsafeMetadata
- Description: Metadata that can be read and set from the frontend and the backend. Once the authentication process is complete, the value of this field will be automatically copied to the created user's unsafe metadata (
User.unsafeMetadata). One common use case is to collect custom information about the user during the authentication process and store it in this property. Read more about unsafe metadata.
Returns
startAppleAuthenticationFlow() returns the following:
- Name:
createdSessionId- Type:
string | null - Description: The ID of the session that was created, if authentication is successful.
- Type:
- Name:
setActive?- Type:
(params: SetActiveParams) => Promise<void> - Description: A method used to set the active session and/or Organization.
- Type:
- Name:
signIn?- Type:
SignIn | undefined - Description: The SignIn object that was created, which holds the state of the current sign-in.
- Type:
- Name:
signUp?- Type:
SignUp | undefined - Description: The SignUp object that was created, which holds the state of the current sign-up.
- Type:
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:
- User cancellation: The user cancels the authentication flow.
- Platform error: The hook is called on a non-iOS platform.
- Missing package: The
expo-apple-authenticationpackage is not installed. - Authentication failure: Apple authentication fails or the returned ID token is invalid.
Always wrap calls to startAppleAuthenticationFlow() in a try/catch block, and handle the ERR_REQUEST_CANCELED error separately.