Web3Auth v10 redirect URL not working using Ionic

Hi I’m using Ionic v8.7.8 and @web3auth/modal v10.10.0.

I have this Web3AuthNoModal object:

this.web3auth = new Web3AuthNoModal({
  clientId: this.clientId,
  web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_DEVNET,
  storageType: "local",
  sessionTime: 86400,
  authBuildEnv: "testing",
  connectors: [
    authConnector({
      connectorSettings: {
        redirectUrl: "com.zertipower.app://zertipower",
        uxMode: "redirect",
        
      }
    })
  ],
});

The issue occurs during redirection. When the Web3Auth callback returns to the app, it provides a Base64-encoded string, and at that point I’m not sure what the next steps are or how this value should be handled.

On desktop, everything works as intended only when uxMode is set to "popup". In that case, the Base64 string resolves correctly and returns an idToken, which allows my backend to handle the login properly:

const tokens = await this.apiAuth.login(idToken, appPubKey as string);

However, when returning to the app after the redirect flow, web3auth.init() is triggered and performs the following API call:

https://api.web3auth.io/signer-service/api/v2/configuration?project_id=PROJECT_ID&network=sapphire_devnet&build_env=testing

It returns this object:

{
  "teamId": "<TEAM_ID>",
  "enableKeyExport": true,
  "sessionTime": 86400,
  "userDataInIdToken": true,
  "walletConnectProjectId": "<WALLET_CONNECT_PROJECT_ID>",
  "whitelist": {
    "urls": null,
    "signed_urls": {}
  },
  "chains": [
    {
      "chainNamespace": "eip155",
      "chainId": "<CHAIN_ID>",
      "displayName": "Ethereum",
      "blockExplorerUrl": "<BLOCK_EXPLORER_URL>",
      "ticker": "ETH",
      "tickerName": "Ether",
      "logo": "<CHAIN_LOGO_URL>",
      "isTestnet": false,
      "isInfuraSupported": true,
      "decimals": 18,
      "enabled": true,
      "rpcTarget": "<RPC_TARGET_URL>"
    }
  ],
  "embeddedWalletAuth": [
    {
      "name": "google",
      "authConnection": "google",
      "groupedAuthConnectionId": "<GROUPED_AUTH_CONNECTION_ID>",
      "authConnectionId": "<AUTH_CONNECTION_ID>",
      "clientId": "<GOOGLE_CLIENT_ID>",
      "isDefault": true
    },
    {
      "name": "twitter",
      "authConnection": "twitter",
      "groupedAuthConnectionId": "<GROUPED_AUTH_CONNECTION_ID>",
      "authConnectionId": "<AUTH_CONNECTION_ID>",
      "clientId": "<TWITTER_CLIENT_ID>",
      "jwtParameters": {
        "domain": "<AUTH0_DOMAIN>",
        "connection": "twitter",
        "isUserIdCaseSensitive": false
      },
      "isDefault": true
    },
    {
      "name": "facebook",
      "authConnection": "facebook",
      "groupedAuthConnectionId": "<GROUPED_AUTH_CONNECTION_ID>",
      "authConnectionId": "<AUTH_CONNECTION_ID>",
      "clientId": "<FACEBOOK_CLIENT_ID>",
      "isDefault": true
    },
    {
      "name": "apple",
      "authConnection": "apple",
      "groupedAuthConnectionId": "<GROUPED_AUTH_CONNECTION_ID>",
      "authConnectionId": "<AUTH_CONNECTION_ID>",
      "clientId": "<APPLE_CLIENT_ID>",
      "jwtParameters": {
        "domain": "<AUTH0_DOMAIN>",
        "connection": "apple"
      },
      "isDefault": true
    }
  ],
  "loginModal": {
    "widgetType": "embed",
    "logoAlignment": "center",
    "signInMethods": [
      "social",
      "passwordless",
      "externalWallets"
    ],
    "borderRadiusType": "large",
    "buttonRadiusType": "pill",
    "addPreviousLoginHint": false,
    "displayExternalWalletsCount": true,
    "displayInstalledExternalWallets": false
  }
}

As you can see, the whitelist object has two empty keys. On my dashboard, I have two whitelisted URLs, which is why the popup flow works correctly.

However, when using the embedded flow, the app gets stuck at
this.web3auth.status → "connecting".

I’ve also tried different values for authBuildEnv (for example, "testing"), but none of them work. I’m not sure whether this is a bug or if I’m missing something in the configuration.

The app flow is as follows:

Splash screen → Login (Web3Auth) → Click Google icon → Google login → Web3Auth callback → Return to app → Stuck

1 Like

Hi Alex — thanks for the detailed report, this is very helpful. I pulled the key info below so the support team can quickly triage, and I added a few focused checks and next steps you can try now.

Extracted details (for the support team)

  • SDK: Web3AuthNoModal (Web3Auth SDK)
  • SDK version: @web3auth/modal v10.10.0 (you stated v10.10.0)
  • Platform: Ionic app (Ionic v8.7.8). Mobile deep link (redirectUrl: com.zertipower.app://zertipower). uxMode: “redirect”
  • Current behavior: popup flow works (returns idToken). Redirect flow returns a Base64-encoded string to the app on deep link, then web3auth.init() runs and calls the configuration endpoint which shows whitelist: { urls: null, signed_urls: {} } and web3auth.status remains “connecting”.

Likely causes / what to check

  1. Deep-link handling: make sure the app actually receives the full callback URL on open (not just a trimmed Base64 fragment). In Capacitor/ Cordova/ native you must register the scheme (Info.plist, AndroidManifest, capacitor.config) and handle the app-open URL event. If the SDK doesn’t get the original callback URL the redirect flow can’t finish.

  2. Exact redirect URL match: the redirect URL must match exactly what’s whitelisted in your Web3Auth dashboard (including scheme, host, path, trailing slash). Confirm com.zertipower.app://zertipower is listed exactly.

  3. Finalizing the redirect flow: Unlike popup mode (where the SDK gets the response in-window), redirect mode requires the app to hand the callback data (the returned URL or Base64 payload) back to the SDK so it can decode/exchange for tokens. If your app is only calling web3auth.init() but not providing the original callback URL or letting the SDK process the redirect result, the status may hang at “connecting.”

Quick actionable steps you can try now

  • Confirm the app receives the full deep link when returning from the browser. For Capacitor, add an appUrlOpen listener:

    • App.addListener(‘appUrlOpen’, ({ url }) => { console.log(‘opened with url’, url) })
    • If you only see a Base64 fragment, log the entire URL and copy it.
  • Decode the Base64 payload to inspect what it contains (idToken, code, state, etc):

    • In JS: const decoded = atob(base64String); console.log(decoded)
    • If it already contains an idToken you can use it directly with your backend login flow (as you do in popup mode).
  • Ensure web3auth.init() is called as early as possible after app open, and that the SDK is given access to the original callback URL so it can complete the redirect flow. If the SDK exposes a “handle redirect” method, call that (or call connect() after init) — if you’re not sure which SDK method completes the redirect, share the Web3Auth initialization/entry code and I’ll point to the exact call.

  • Double-check Web3Auth dashboard: the redirect URL must be present under the correct environment (testing/sapphire_devnet) and for the embedded/redirect flow. The configuration response you pasted shows whitelist.urls: null — that indicates the SDK/endpoint didn’t pick up your whitelisted URLs for that environment/build env.

What I need from you (minimal):

  • Confirm mobile OS (iOS, Android, or both) and whether you’re using Capacitor or Cordova.
  • Do you see the full deep link URL in logs when the app opens? If yes, paste the decoded Base64 payload (or a screenshot). If no, tell me what you see.
  • If possible, share the appUrlOpen/URL-handling snippet where you capture the deep link (or confirm you don’t yet have one).

If you prefer I can open a support ticket for the Web3Auth/dashboard team — I’ll include the details above plus any logs/payload you provide. If you share the decoded payload or the exact URL received by the app I can tell you whether it already contains an idToken or whether the SDK must perform an exchange.

Thanks — once you paste the small missing bits (OS + whether using Capacitor/Cordova + the decoded payload or the open-url log) I’ll suggest the exact code changes or file the issue with the right attachments so the SDK team can investigate quickly.

Note: This response was generated by an AI bot and may require further verification. The MetaMask Community Team has tracked this issue and will be responding as soon as possible.

Additionally, we would recommend you to join our biweekly Office Hours to get this resolved even faster. MetaMask Developer Office Hours

I’m testing it on Android using Capacitor.

This is the decoded Base64 string:

{
  "nonce": "40dafac70537b57358b7e5e0e9cc8e2c7a2ee7b4535a27a7419d2b9d74baf514",
  "loginParams": {
    "curve": "other",
    "authConnection": "google",
    "getIdentityToken": false,
    "extraLoginOptions": {}
  }
}

This is what my handled deep link received from Capacitor: com.zertipower.app://zertipower/#b64Params=eyJub25jZSI6IjQzMTZjN2Q4MjJmYmFkZTk2ODRiYmUyZDYxM2YyNzJlZTM5ZDY3YzQ1ZmI4MjZmNmU4YjBkMTUwM2M1MmFmODUiLCJsb2dpblBhcmFtcyI6IntcImN1cnZlXCI6XCJvdGhlclwiLFwiYXV0aENvbm5lY3Rpb25cIjpcImdvb2dsZVwiLFwiZ2V0SWRlbnRpdHlUb2tlblwiOmZhbHNlLFwiZXh0cmFMb2dpbk9wdGlvbnNcIjp7fX0ifQ

And this is my listener, a bit dirty since i’ve been trying solutions

 async init() {
    App.addListener('appUrlOpen', (event: any) => {
      console.log('App opened via URL (appUrlOpen):', event.url);
      if (event.url.includes("com.zertipower.app://zertipower")) {
        void this.loginService.handleDeepLink(event.url);
      }
    });

    // Handle cold start if the app was opened by a deep link
    const launchUrl = await App.getLaunchUrl();
    console.log('Launch URL (getLaunchUrl):', launchUrl?.url);
    if (launchUrl?.url && launchUrl.url.includes("com.zertipower.app://zertipower")) {
      void this.loginService.handleDeepLink(launchUrl.url);
    }
  }

This is my dashboard:

I don’t know for sure since I haven’t worked with the plug and play SDK before.

Seems like a complicated issue though.

Other Ionic related topics:

Are you already aware of the following that they replaced every Web3AuthNoModal class with a Web3Auth class:

Recommended: Switch to Modal SDK

While the @web3auth/no-modal package continues to receive updates, it now primarily serves as an internal SDK to power the modal SDK. We strongly recommend migrating to the @web3auth/modal package for the best developer experience.

The Modal SDK offers everything you need: pre-built UI components for quick integration AND full custom UI control via connectTo for advanced use cases. Plus, you’ll get priority documentation, examples, and community support.

Source: Migrating to the Web3Auth PnP Web SDK v10 from v9 (No-Modal) | MetaMask developer documentation

Although Web3Auth support is supposed to take around 2 business days to reply, I’m still waiting for a reply too for a topic created about a week ago.

Hi, thanks for the reply.

If I use Web3Auth instead of Web3AuthNoModal as described here:

I get this error on await web3auth.init()

That’s why I use Web3AuthNoModal

So the only way to force it to use modal is to add a uiconfig object and put widgetType: ‘modal’ as the key value pair. so its not quite all managed in the web3auth dashboard.

Source: WalletInitialization Error: Invalid params passed in, targetId is required for embed widget - #3 by Jason_Martin-Smith

Fixed the targetId error. Now I can use Web3Auth instead of Web3AuthNoModal, but I’m still getting the same error as before: the redirection does not work as expected, so I can’t log in.

Your whitelist url will be your bundle Identifier for your iOS app followed by ://auth so something like this (xyz://auth) where xyz is your bundle Identifier which can be found in Targets → General

Source: Ionic iOS Native App has no referrer · Web3Auth · Discussion #394 · GitHub

Hey @loic sorry for the extremely in replying here. This was lost somehow in our forum. Our SDKs do not support Ionic unfortunately. What you can do is to make a similarly implementation as our react native SDK for your ionic environment and try that: GitHub - Web3Auth/web3auth-react-native-sdk

additionally, you can choose to go for the id token approach, while using no MFA using our Node SDK Embedded Wallets SDK for Node.js | MetaMask developer documentation
This is a pure JS SDK and should be easily working in an ionic environment, however MFA won’t be supported here.

Hey @yashovardhan, this wasn’t my issue. I was just trying to help.

It was @alex_zertifier’s issue.

Sure thanks a lot @loic
@alex_zertifier let me know if this helps or you need anything else particularly.