Sign in with Apple
This guide will teach you how to add native Sign in with Apple to your Clerk Expo application.
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
- 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.
- Ensure that Enable for sign-up and sign-in is toggled on.
Install dependencies
The Expo Apple Authentication library provides access to Apple's native Sign in with Apple functionality from your Expo app.
Run the following command to install the library:
npx expo install expo-apple-authenticationpnpm dlx expo install expo-apple-authenticationyarn dlx expo install expo-apple-authenticationbun x expo install expo-apple-authenticationAdd expo-apple-authentication to your app config
Add the expo-apple-authentication plugin to your app.json or app.config.js.
{
"expo": {
"plugins": ["expo-apple-authentication"]
}
}export default {
expo: {
plugins: ['expo-apple-authentication'],
},
}Build your authentication flow
The following example demonstrates how to use the useSignInWithApple() 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.
import { useSignInWithApple } from '@clerk/clerk-expo'
import { useRouter } from 'expo-router'
import { Alert, Platform, StyleSheet, Text, TouchableOpacity, View } from 'react-native'
// Example props that you could pass to your button
interface AppleSignInButtonProps {
// Callback function that is called when the sign-in is complete
onSignInComplete?: () => void
// Whether to show a divider between the button and the text
showDivider?: boolean
}
export function AppleSignInButton({
onSignInComplete,
showDivider = true,
}: AppleSignInButtonProps) {
const { startAppleAuthenticationFlow } = useSignInWithApple()
const router = useRouter()
// Only render on iOS
if (Platform.OS !== 'ios') {
return null
}
const handleAppleSignIn = async () => {
try {
const { createdSessionId, setActive } = await startAppleAuthenticationFlow()
if (createdSessionId && setActive) {
// Set the created session as the active session
await setActive({ session: createdSessionId })
// Once the session is set as active,
// if a callback function is provided, call it.
// Otherwise, redirect to the home page.
onSignInComplete ? onSignInComplete() : router.replace('/')
}
} catch (err: any) {
// User canceled the sign-in flow
if (err.code === 'ERR_REQUEST_CANCELED') return
Alert.alert('Error', err.message || 'An error occurred during Apple Sign-In')
console.error('Apple Sign-In error:', JSON.stringify(err, null, 2))
}
}
return (
<>
<TouchableOpacity style={styles.appleButton} onPress={handleAppleSignIn}>
<Text style={styles.appleButtonText}>Sign in with Apple</Text>
</TouchableOpacity>
{showDivider && (
<View style={styles.divider}>
<View style={styles.dividerLine} />
<Text style={styles.dividerText}>OR</Text>
<View style={styles.dividerLine} />
</View>
)}
</>
)
}
const styles = StyleSheet.create({
appleButton: {
backgroundColor: '#000',
padding: 15,
borderRadius: 8,
alignItems: 'center',
marginBottom: 10,
},
appleButtonText: {
color: '#fff',
fontSize: 16,
fontWeight: '600',
},
divider: {
flexDirection: 'row',
alignItems: 'center',
marginVertical: 20,
},
dividerLine: {
flex: 1,
height: 1,
backgroundColor: '#ccc',
},
dividerText: {
marginHorizontal: 10,
color: '#666',
},
})Create a native build
Create a native build with EAS Build or a local prebuild, since Apple Authentication is not supported in Expo Go.
# Using EAS Build
eas build --platform ios
# Or using local prebuild
npx expo prebuild && npx expo run:ios --deviceFeedback
Last updated on