Skip to main content
Docs

useSignInWithApple()

Important

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 between sign-up and sign-in.

Installation

This hook requires the following peer dependencies:

terminal
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
    SignUpUnsafeMetadataJavaScript Icon
    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.

  • Name
    setActive?
    Type
    (params: SetActiveParams) => Promise<void>
    Description

    A method used to set the active session and/or Organization. Accepts a SetActiveParamsJavaScript Icon object.

  • Name
    signIn?
    Type
    SignInJavaScript Icon | undefined
    Description

    The SignInJavaScript Icon object that was created, which holds the state of the current sign-in and provides helper methods to navigate and complete the sign-in process.

  • Name
    signUp?
    Type
    SignUpJavaScript Icon | undefined
    Description

    The SignUpJavaScript Icon object that was created, which holds the state of the current sign-up and provides helper methods to navigate and complete the sign-up process.

Examples

Reusable component

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',
  },
})

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.

app/(auth)/sign-in.tsx
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()

  // Only render on iOS
  if (Platform.OS !== 'ios') {
    return null
  }

  const onAppleSignInPress = async () => {
    try {
      const { createdSessionId, setActive } = await startAppleAuthenticationFlow({
        // Add information about the user to their unsafe metadata
        unsafeMetadata: {
          referralSource: 'ios-app',
          signupDate: new Date().toISOString(),
        },
      })

      if (createdSessionId && setActive) {
        // Set the created session as the active session
        await setActive({ session: createdSessionId })
        // Once the session is set as active,
        // redirect the user to the home page
        router.replace('/')
      }
    } catch (err: any) {
      // User canceled the authentication flow
      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 (
    <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, resulting in an error with code ERR_REQUEST_CANCELED.
  • Platform error: The hook is called on a non-iOS platform.
  • Missing package: The expo-apple-authentication package is not installed.
  • Authentication failure: Apple authentication fails or the returned ID token is invalid.

Important

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

Feedback

What did you think of this content?

Last updated on