diff --git a/.changeset/guard-native-client-sync-ghost-tokens.md b/.changeset/guard-native-client-sync-ghost-tokens.md new file mode 100644 index 00000000000..3b253dc8ab4 --- /dev/null +++ b/.changeset/guard-native-client-sync-ghost-tokens.md @@ -0,0 +1,5 @@ +--- +'@clerk/expo': patch +--- + +Fix signed-in sessions being dropped shortly after browser SSO on Android when the native SDK refreshes with a stale device token and receives a new anonymous client. The native-to-JS client sync now rejects a device token that belongs to a different client with no signed-in sessions, keeps the JS session active, and re-syncs the native SDK back to the JS client. Native client events that carry a stale device token are also ignored while a JS-to-native token sync is still in flight. diff --git a/integration/templates/expo-native/App.tsx b/integration/templates/expo-native/App.tsx index 2031e9b4512..7e38fa83949 100644 --- a/integration/templates/expo-native/App.tsx +++ b/integration/templates/expo-native/App.tsx @@ -5,6 +5,9 @@ import { tokenCache } from '@clerk/expo/token-cache'; import { useState } from 'react'; import { Button, Modal, StyleSheet, Text, View } from 'react-native'; +import { E2EControls } from './components/E2EControls'; +import { JsSignInForm } from './components/JsSignInForm'; + const publishableKey = process.env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY; if (!publishableKey) { @@ -17,6 +20,7 @@ function NativeBuildFixture() { const { startGoogleAuthenticationFlow } = useSignInWithGoogle(); const [isAuthOpen, setIsAuthOpen] = useState(false); const [googleResult, setGoogleResult] = useState(null); + const [e2eStatus, setE2eStatus] = useState(null); return ( @@ -45,6 +49,9 @@ function NativeBuildFixture() { /> )} {googleResult && {googleResult}} + {!isSignedIn && } + {isSignedIn && } + {e2eStatus && {e2eStatus}} {isSignedIn && (