When i login a user using the customer account API in my react native application, I get directed to the orders page and then redirected to the mobile application

I’m creating a react native mobile application and recently applied the customer account API.

So, as for the otp authentication i need to use the webview so as in my website after login it redirects to acount/orders page in my mobile application it is doing the same and then after 2 seconds it then redirects to the mobile application. Which should not happen and it should directly open the mobile application.

i’m attaching the part of the code so that you get the source and tell me where i am going wrong

 async function handleNav(url: string) {

  console.log("NAV URL:", url);

  /**

   * STEP A — Capture OAuth redirect

   */

  if (url.startsWith(REDIRECT_URI)) {

    const codeMatch = url.match(/[?&]code=([^&]+)/);

const code = codeMatch ? decodeURIComponent(codeMatch[1]) : null;

if (code) {

  console.log("✅ OAuth code received:", code);

  await exchangeCodeForToken(code);

}

    return;

  }

  /**

   * STEP B — Detect OTP login success

   */

  const loggedIn =

    url.includes("/account") &&

    !url.includes("login") &&

    !url.includes("authorize");




  if (loggedIn && !pkceStarted.current) {

    pkceStarted.current = true;

    console.log("🎉 OTP Login Success → Starting OAuth");




    const verifier = generateCodeVerifier();

    const challenge = generateCodeChallenge(verifier);




    await AsyncStorage.setItem("PKCE_VERIFIER", verifier);




    // Discover OAuth endpoints

    const discovery = await fetch(

      `https://${SHOP_DOMAIN}/.well-known/openid-configuration`

    ).then(res => res.json());

    const authorizeUrl =

      `${discovery.authorization_endpoint}?` +

      `client_id=${CLIENT_ID}` +

      `&response_type=code` +

      `&scope=${encodeURIComponent(SCOPES)}` +

      `&redirect_uri=${encodeURIComponent(REDIRECT_URI)}` +

      `&code_challenge=${challenge}` +

      `&code_challenge_method=S256`;

    console.log("🔐 Loading OAuth URL:", authorizeUrl);

    setWebViewUrl(authorizeUrl);

    return;

  }

}

async function exchangeCodeForToken(code: string) {

  console.log("🔁 Exchanging code for token...");




  // 1. Get PKCE verifier

  const verifier = await AsyncStorage.getItem("PKCE_VERIFIER");

  if (!verifier) {

    throw new Error("PKCE verifier missing");

  }

  // 2.Discover token endpoint

  const discovery = await fetch(

    `https://${SHOP_DOMAIN}/.well-known/openid-configuration`

  ).then(res => res.json());

  // 3. Build body

  const body = new URLSearchParams();

  body.append("grant_type", "authorization_code");

  body.append("client_id", CLIENT_ID);

  body.append("redirect_uri", REDIRECT_URI);

  body.append("code", code);

  body.append("code_verifier", verifier);

  // 4. Call token endpoint

  const response = await fetch(discovery.token_endpoint, {

    method: "POST",

    headers: {

      "content-type": "application/x-www-form-urlencoded",

      "user-agent": "mimosa-react-native",

    },

    body: body.toString(),

  });




  if (!response.ok) {

    const err = await response.text();

    throw new Error(err);

  }

  const {

    access_token,

    refresh_token,

    expires_in,

    id_token,

  } = await response.json();

  // 5. Persist tokens

  await AsyncStorage.multiSet([

    ["ACCESS_TOKEN", access_token],

    ["REFRESH_TOKEN", refresh_token],

    ["TOKEN_EXPIRES_AT", String(Date.now() + expires_in * 1000)],

    ["ID_TOKEN", id_token],

  ]);

  console.log("✅ Tokens stored successfully");

  // 6. Navigate only AFTER success

  navigation.reset({

    index: 0,

    routes: [{ name: "MainTabs" }],

  });

}



  return (

<WebView

  source={{ uri: webViewUrl }}

  sharedCookiesEnabled

  thirdPartyCookiesEnabled

  onNavigationStateChange={(nav: { url: string; }) => handleNav(nav.url)}

/>

  );

}

Can you let me know what the REDIRECT_URI is and what the authorize url ends up looking like when you construct it.

redirect uri: “shop.(SHOP-ID).app://auth/callback”;

Authorize url: https://shopify.com/authentication/(Shop-ID)/oauth/authorize?client_id=(CLIENT-ID)&response_type=code&scope=openid%20email%20customer-account-api%3Afull&redirect_uri=shop.(Shop-ID).app%3A%2F%2Fauth%2Fcallback&code_challenge=b8BSCS_s0oHDC_cxFDawHLH2xJFHBTMtqS5_z_mUwkg&code_challenge_method=S256

What part of the code you shared is the callback?

The callback is handled inside handleNav() when url.startsWith(REDIRECT_URI) is true. That’s where I extract the code and call exchangeCodeForToken.

async function handleNav(url: string) {
  console.log("NAV URL:", url);

  /**
   * STEP A — Capture OAuth redirect
   */
  if (url.startsWith(REDIRECT_URI)) {
    const codeMatch = url.match(/[?&]code=([^&]+)/);
const code = codeMatch ? decodeURIComponent(codeMatch[1]) : null;


if (code) {
  console.log("✅ OAuth code received:", code);
  await exchangeCodeForToken(code);
}


    return;
  }

everything is working but the issue is that, when the user logs in he first directs to the account/order screen webview then redirects to the mobile application

Interesting, so it’s redirecting to the customer account page on your shop instead of staying in the mobile application?

Let me investigate.

ok I tested myself on my web app and couldn’t reproduce it. Do you have a video or screenshots you can share to show your experience. The redirect uri should make it so you redirect to your web app and not the customer account pages.