Fixing Stripe Connect User Not Found Errors on Android with Expo

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.openURL may 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

  1. 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.

  2. Use Expo’s WebBrowser API with cookie support

    import * as WebBrowser from 'expo-web-browser';
    WebBrowser.openBrowserAsync(onboardingUrl, {
      showInRecents: true,
      enableBarCollapsing: true
    });
  3. Embed a custom WebView with third‑party cookies enabled (if complex UI needed)

    import { WebView } from 'react-native-webview';
    
  4. Set the ONBOARDING_URL_TIMEOUT in Stripe to extend the session token expiry if network latency is high.

  5. Log cookie values during development to verify that stripe_connect_session is 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.

Leave a Comment