Authentication and Permissions
Sign In with Apple
Instant supports Sign In with Apple on the Web and in native applications.
#Step 1: Create App ID
- Navigate to Certificates, Identifiers & Profiles
- Select Identifiers
- Click +
- Register a new identifier → Select App IDs
- Select a type → Select App
- Capabilities → Sign In with Apple → Check
- Fill in Bundle ID and Description
- Click Register
#Step 2: Create Services ID
- Navigate to Services IDs
- Click +
- Register a new identifier → Select Services IDs
- Fill in Description and Identifier. You’ll need this Identifier later
- Click Register
#Step 3: Configure Services ID (React Native flow)
This step is not needed for Expo.
#Step 4: Register your OAuth client with Instant
- Go to the Instant dashboard and select Auth tab.
- Select Add Apple Client
- Select unique clientName (
appleby default, will be used indb.authcalls) - Fill in Services ID from Step 2
- Click
Add Apple Client
#Step 5: Add Sign In code to your app (React Native flow)
Instant comes with support for Expo AppleAuthentication library.
Add dependency:
npx expo install expo-apple-authentication
Update app.json by adding:
{"expo": {"ios": {"usesAppleSignIn": true}}}
Go to Instant dashboard → Auth tab → Redirect Origins → Add an origin.
Add exp:// for development with Expo.
Authenticate with Apple and then pass identityToken to Instant along with clientName from Step 4:
const [nonce] = useState('' + Math.random());try {// sign in with Appleconst credential = await AppleAuthentication.signInAsync({requestedScopes: [AppleAuthentication.AppleAuthenticationScope.FULL_NAME,AppleAuthentication.AppleAuthenticationScope.EMAIL,],nonce: nonce,});// pass identityToken to Instantdb.auth.signInWithIdToken({clientName: '<clientName>',idToken: credential.identityToken,nonce: nonce,}).catch((err) => {console.log('Error', err.body?.message, err);});} catch (e) {if (e.code === 'ERR_REQUEST_CANCELED') {// handle that the user canceled the sign-in flow} else {// handle other errors}}
Sign out code:
<Buttontitle="Sign Out"onPress={async () => {await db.auth.signOut();}}/>
Full example:
import React, { useState } from 'react';import { Button, View, Text, StyleSheet } from 'react-native';import { init, tx } from '@instantdb/react-native';import * as AppleAuthentication from 'expo-apple-authentication';const APP_ID = '__APP_ID__';const db = init({ appId: APP_ID });function App() {return (<><db.SignedIn><UserInfo /></db.SignedIn><db.SignedOut><Login /></db.SignedOut></>);}function UserInfo() {const user = db.useUser();return (<View style={styles.container}><Text>Hello {user.email}!</Text><Buttontitle="Sign Out"onPress={async () => {await db.auth.signOut();}}/></View>);}function Login() {const [nonce] = useState('' + Math.random());return (<View style={styles.container}><AppleAuthentication.AppleAuthenticationButtonbuttonType={AppleAuthentication.AppleAuthenticationButtonType.SIGN_IN}buttonStyle={AppleAuthentication.AppleAuthenticationButtonStyle.BLACK}cornerRadius={5}style={styles.button}onPress={async () => {try {const credential = await AppleAuthentication.signInAsync({requestedScopes: [AppleAuthentication.AppleAuthenticationScope.FULL_NAME,AppleAuthentication.AppleAuthenticationScope.EMAIL,],nonce: nonce,});// signed indb.auth.signInWithIdToken({clientName: 'apple',idToken: credential.identityToken,nonce: nonce,}).catch((err) => {console.log('Error', err.body?.message, err);});} catch (e) {if (e.code === 'ERR_REQUEST_CANCELED') {// handle that the user canceled the sign-in flow} else {// handle other errors}}}}/></View>);}const styles = StyleSheet.create({container: {flex: 1,alignItems: 'center',justifyContent: 'center',},button: {width: 200,height: 44,},});export default App;