Summary
A React Native Expo app successfully initiates Stripe Connect Express onboarding on iOS, desktop browsers, and Android.
However, on Android devices the user receives a “User Not Found” error after submitting the test phone number.
The same onboarding URL works flawlessly on other platforms, indicating a platform‑specific issue.
Root Cause
Android’s WebView and browser sandboxing block the temporary session cookies that Stripe relies on to map the user to the Express account during onboarding.
- Android’s default behaviour clears third‑party cookies when a URL is opened in an external browser or in a WebView that hasn’t enabled
setAllowThirdPartyCookies. - Stripe’s onboarding flow uses a short‑lived cookie to associate the user’s session with the account being created.
- Without that cookie, Stripe cannot locate the user and returns “User Not Found.”
Why This Happens in Real Systems
- Cookie isolation: Android enforces stricter cookie policies to protect privacy, especially in embedded browsers.
- External browser fallback: Expo’s
Linking.openURLmay launch Chrome or the system browser with limited session persistence. - WebView defaults: The Expo WebBrowser API creates a new WebView instance that disables third‑party cookies by default.
- Session token length: Stripe’s onboarding token is short‑lived (≈ 15 minutes); any delay or cookie loss before completion triggers the error.
Real-World Impact
- User churn: Users attempting to connect their accounts on Android are blocked, leading to abandoned onboarding attempts.
- Revenue loss: Express accounts cannot be created, preventing merchants from collecting payments.
- Support tickets: Increased backend logs and support calls for a vague “user not found” message.
Example or Code (if necessary and relevant)
// Incorrect WebView usage that disables third‑party cookies
WebViewComponent({
source: { uri: onboardingUrl },
// no setAllowThirdPartyCookies flag set
});
// Correct WebView usage with third‑party cookies enabled
WebViewComponent({
source: { uri: onboardingUrl },
thirdPartyCookiesEnabled: true,
});
(Note: In Expo, use WebBrowser.openBrowserAsync(onboardingUrl, { dialogTitle: 'Stripe Onboarding', showInRecents: true, enableBarCollapsing: true }); to preserve session cookies.)
How Senior Engineers Fix It
-
Open the URL in the system browser with cookie persistence
import * as Linking from 'expo-linking'; Linking.openURL(onboardingUrl);Ensure the user stays in the same browser tab until the flow completes.
-
Use Expo’s
WebBrowserAPI with cookie supportimport * as WebBrowser from 'expo-web-browser'; WebBrowser.openBrowserAsync(onboardingUrl, { showInRecents: true, enableBarCollapsing: true }); -
Embed a custom WebView with third‑party cookies enabled (if complex UI needed)
import { WebView } from 'react-native-webview'; -
Set the
ONBOARDING_URL_TIMEOUTin Stripe to extend the session token expiry if network latency is high. -
Log cookie values during development to verify that
stripe_connect_sessionis present before redirecting back.
Why Juniors Miss It
- Assuming browsers behave the same across platforms; many overlook Android’s stricter cookie policies.
- Missing Expo WebBrowser defaults: Junior devs often use default bindings without enabling third‑party cookies.
- Overlooking session expiry: They may not realize the short lifespan of Stripe’s onboarding token, leading to premature session loss.
- Not inspecting network traces: Without looking at the cookie payload, the underlying issue is hidden behind a generic error message.
By focusing on cookie handling and platform differences, senior engineers can quickly identify and resolve the “User Not Found” error in Android environments.