0

I’m working on a Flutter app that integrates an external authentication system provided by another company. The login and password-reset flows are handled entirely inside a WebView (their backend + their hosted HTML pages).

Flow overview

  1. User opens the Flutter app
  2. Taps Login
  3. A WebView opens and loads the external login page
  4. User taps Forgot Password
  5. A second WebView opens (also external)
  6. User enters their email and submits the form
  7. Expected: a password-reset email is sent

The problem

On iOS, the request on step 6 never reaches the server. The WebView simply doesn’t send the request — no redirect, no network traffic. On Android, everything works perfectly. Also its super hard to generate any type of logs, just nothing happens when sending the request.

It looks like opening a second WebView on iOS causes a context switch that breaks the request. The external provider claims that their backend + pages are correctly configured, and since Android works, the issue seems to be on the iOS/WebView/Flutter side.

What we tried

  • Originally used oauth2_client → same problem
  • Switched to flutter_appauth → same problem
  • Verified redirect URLs and callback schemes
  • Cleared Xcode’s DerivedData
  • Reset iOS build folder (flutter clean, removing /ios/Pods, pod install)
  • Checked iOS entitlements
  • Tried to configure persisting storage and cookies between both WEbViews (like preferEphemeralSession)

Nothing seems to fix the issue.

Has anyone encountered an issue where iOS blocks requests from a second WebView, especially when the flow involves authentication or form submission hosted externally?

Disclaimer: I am completely new to flutter + auth + ios So if you need any specific code just tell me and i try to give you all the information you need.

Future<void> signInWithUsernamePassword() async {
    try {
      _authType = AuthType.emailPassword;
      AccessTokenResponse tkn = await _authProvider.authorizeAndExchangeCode(
        clientId: AuthType.emailPassword.clientId,
        redirectUrl: "com.example.app://oauth2redirect",
        discoveryUrl: "https://example.com/auth/realms/yourrealm/.well-known/openid-configuration",
        scopes: const ["openid", "profile", "roles"],
        preferEphemeral: false,
      );
      await _handleTokenResponse(tkn);
    } catch (e) {
      FlutterError.presentError(FlutterErrorDetails(exception: e));
      print("Error: " + e.toString());
    }
}

Thank you so much for your input!

1 Answer 1

0

This is not really an “auth” problem it is an iOS WebView / WKWebView popup problem.

On iOS, WKWebView does not handle target="_blank" / window.open links by default. Those links simply do nothing unless you explicitly handle them in the native delegate.

Most “Forgot password” links in hosted login pages open a new window/tab (target="_blank"). So your flow is:

  • Login page inside WebView -> click Forgot password

  • Provider tries to open a new window for the reset page

  • On Android WebView: new page opens and works -> POST is sent

  • On iOS WKWebView: the popup/new window is ignored -> the reset page never really loads -> submitting “does nothing”

That’s why you see no network traffic on iOS.

What you should do

Do not use a second WebView at all.
Add a “Forgot password” button in Flutter and open the provider’s reset URL via Safari/Chrome:

import 'package:url_launcher/url_launcher.dart';

Future<void> openForgotPassword() async {
  final uri = Uri.parse('https://example.com/auth/realms/yourrealm/account/password');
  await launchUrl(uri, mode: LaunchMode.externalApplication);
}

This bypasses the popup issue completely and is what most IdPs recommend.

If you control the HTML: ask the provider to remove target="_blank" (or popup logic) and open the reset page in the same window.

If you are using a custom WebView (not flutter_appauth):

  • On iOS you must handle popup/new-window navigation and load it in the same WKWebView (via WKUIDelegate.createWebViewWithConfiguration in native code).

  • In Flutter plugins like flutter_inappwebview, this is usually exposed as onCreateWindow where you manually load the URL in the existing WebView.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much for your input, i will test it and give feedback. Maybe other people have the same issue

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.