{ }
Published on

Set Up Appwrite Auth with Apple Login in Expo (2025 Guide)

Authors
  • avatar
    Name
    Ahmed Farid
    Twitter
    @

TIP

Bookmark this page when adding social logins to your Expo projects—Apple demands strict guidelines and this checklist keeps you compliant.

Appwrite offers a unified auth layer, while Expo simplifies cross-platform builds. Apple, however, imposes special requirements for OAuth. This guide details all steps to connect Sign in with Apple to Appwrite Auth in an Expo SDK 50+ project.

Table of Contents

1. Prerequisites & Terminology

  • Appwrite 1.4+ self-hosted or Cloud project.
  • Expo SDK 50 (managed workflow).
  • macOS with Xcode 15 for Apple Developer portal.
  • An Apple Developer account ($99/year).
TermMeaning
Service IDIdentifier used by Apple for web / native OAuth flows
Key IDIdentifier for the private key that signs JWTs
Client SecretJWT signed with your private key; validates token exchange
expo-apple-authenticationExpo module exposing AppleAuthentication API

2. Create an Expo Project & Install Dependencies

npx create-expo-app AppleAuthApp
cd AppleAuthApp
yarn add expo-apple-authentication react-native-appwrite
npx expo prebuild --platform ios # generates native xcode project for entitlements

NOTE

On bare workflow you can skip prebuild—just ensure the Apple entitlement file is updated (see §6).

3. Set Up Apple Credentials in Developer Portal

  1. Identifiers → App IDs: Create com.yourco.appleauthapp.
  2. Enable Sign In with Apple capability.
  3. Keys → +: Create Sign In with Apple key, select the above App ID.
  4. Download the .p8 file—store securely.
  5. Note Key ID and Team ID (Organization). You’ll use them in Appwrite.
  6. Identifiers → Service IDs: Create com.yourco.appleauthapp.service.
    • Configure Primary App ID = your app.
    • Under Web Authentication Configuration add https://YOUR_APPWRITE_ENDPOINT/v1/account/sessions/oauth2/callback/apple as redirect.

4. Configure Appwrite OAuth Provider

Dashboard → Auth / Providers / Apple:

  • Team ID
  • Key ID
  • Private Key (paste .p8 contents)
  • Bundle ID = com.yourco.appleauthapp
  • Callback URL (auto-filled) → Add same in Apple dashboard.
  • Scopes: name, email (Apple only returns once—store immediately).

Save → Appwrite now lists APPLE as active provider.

5. Add OAuth Callback to Allowed URLs

Project settings → API / Platforms → iOS → add appscheme://auth for deep links.

Also add https://auth.expo.dev/@yourname/AppleAuthApp if you later use EAS AuthSession.

6. Configure iOS Entitlements & Info.plist

The Expo config plugin handles this automatically:

// app.json
{
  "expo": {
    "ios": {
      "bundleIdentifier": "com.yourco.appleauthapp",
      "usesAppleSignIn": true,
    },
  },
}

Regenerate with npx expo prebuild --platform ios after updates.

7. Initialising Appwrite SDK

// src/lib/appwrite.ts
import { Client, Account, Avatars } from 'react-native-appwrite'

export const client = new Client()
  .setEndpoint('https://cloud.appwrite.io/v1')
  .setProject('YOUR_PROJECT_ID')

export const account = new Account(client)

8. Implement Sign in with Apple Flow

// src/screens/Login.tsx
import * as Apple from 'expo-apple-authentication'
import { account } from '@/lib/appwrite'
import * as AuthSession from 'expo-auth-session'
import { useState } from 'react'
import { View, Text, Button, Alert } from 'react-native'

export default function Login() {
  const [loading, setLoading] = useState(false)

  const loginWithApple = async () => {
    setLoading(true)
    try {
      // 1. Open Apple Authentication prompt
      const credential = await Apple.signInAsync({
        requestedScopes: [
          Apple.AppleAuthenticationScope.FULL_NAME,
          Apple.AppleAuthenticationScope.EMAIL,
        ],
      })

      // 2. Exchange identity token with Appwrite
      const session = await account.createOAuth2Session(credential.identityToken!, 'apple')

      console.log('Logged in ✨', session)
    } catch (err: any) {
      console.error(err)
      Alert.alert('Login failed', err.message)
    } finally {
      setLoading(false)
    }
  }

  return (
    <View className="flex-1 items-center justify-center px-4">
      <Text className="mb-4 text-2xl">Apple Login Demo</Text>
      <Apple.AppleAuthenticationButton
        buttonType={Apple.AppleAuthenticationButtonType.SIGN_IN}
        buttonStyle={Apple.AppleAuthenticationButtonStyle.BLACK}
        cornerRadius={8}
        style={{ width: 280, height: 45 }}
        onPress={loginWithApple}
        disabled={loading}
      />
    </View>
  )
}

Key points:

  1. identityToken comes from Apple—JWT with sub.
  2. createOAuth2Session accepts token, provider ("apple"), optional redirect (we bypass by performing exchange client-side).
  3. Store the returned session or JWT in secure storage.

9. Handling First-Time Name/Email

Apple returns name/email once. Appwrite stores them automatically, but if you need to save display name in your DB, capture from credential.fullName during first login.

if (credential.fullName?.givenName) {
  await account.updateName(`${credential.fullName.givenName} ${credential.fullName.familyName}`)
}

10. Testing on Simulator & Real Device

  • Simulator with Xcode 15 supports Apple Sign In.
  • Ensure Settings → Apple ID → iCloud signed in.
  • On TestFlight, Apple requires Sign in with Apple justification if other social logins exist.

11. Adding Web Support (Optional)

For Expo Web, use AuthSession:

const redirectUri = AuthSession.makeRedirectUri({ useProxy: true })
await AuthSession.startAsync({
  authUrl: `https://cloud.appwrite.io/v1/account/sessions/oauth2/apple?project=YOUR_PROJECT_ID&success=${redirectUri}`,
})

Appwrite will redirect back with #access_token= fragment. Parse and create stored session.

12. Production Checklist

✅ App Clip disabled unless needed. ✅ usesAppleSignIn: true in Expo config. ✅ Privacy policy links in App Store Connect. ✅ Store user email immediately—Apple may hide it (private relay). ✅ Support account deletion (App Store rule §5.1.1).

13. Troubleshooting

IssueFix
Error: invalid_clientCheck Key ID / Team ID mismatch in Appwrite
Identity token nullApple prompt cancelled; guard against aborts
Appwrite 401Project ID wrong or platform not allowed

14. Further Reading & Resources

15. Conclusion

You now have an end-to-end Sign in with Apple flow powered by Appwrite and Expo—covering certificates, entitlements, token exchange and UI. Happy shipping! 🚀