diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart index 192e673e7bd0..c1c83936a222 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart @@ -57,6 +57,14 @@ class FirebaseCoreWeb extends FirebasePlatform { ); } + /// Whether [service] is still registered for per-app initialization. + /// + /// Used by tests to ensure App Check is not removed after the first + /// [initializeApp] (secondary apps must re-run ensurePluginInitialized). + @visibleForTesting + static bool isServiceRegistered(String service) => + _services.containsKey(service); + static const String _libraryName = 'flutter-fire-core'; /// Registers that [FirebaseCoreWeb] is the platform implementation. @@ -394,15 +402,20 @@ class FirebaseCoreWeb extends FirebasePlatform { } } - final appCheck = _services.remove('app-check'); - if (appCheck != null) { - // Activate app check first - await appCheck.ensurePluginInitialized!(app!); + // Activate App Check before other services so Auth/etc. attach tokens. + // Do NOT remove 'app-check' from [_services]: secondary (named) apps also + // need ensurePluginInitialized on each Firebase.initializeApp() call. + // Removing it caused App Check to skip reactivation for named apps on + // reload, so accounts:lookup ran without X-Firebase-AppCheck (#18556). + final appCheck = _services['app-check']; + final appCheckEnsureInitialized = appCheck?.ensurePluginInitialized; + if (appCheckEnsureInitialized != null) { + await appCheckEnsureInitialized(app!); } await Future.wait( - _services.values.map((service) { - final ensureInitializedFunction = service.ensurePluginInitialized; + _services.entries.where((entry) => entry.key != 'app-check').map((entry) { + final ensureInitializedFunction = entry.value.ensurePluginInitialized; if (ensureInitializedFunction == null || app == null) { return Future.value(); diff --git a/packages/firebase_core/firebase_core_web/test/firebase_core_web_app_check_multi_app_test.dart b/packages/firebase_core/firebase_core_web/test/firebase_core_web_app_check_multi_app_test.dart new file mode 100644 index 000000000000..88bfad5eb7a1 --- /dev/null +++ b/packages/firebase_core/firebase_core_web/test/firebase_core_web_app_check_multi_app_test.dart @@ -0,0 +1,67 @@ +// Copyright 2026 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +@TestOn('browser') +library; + +import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart'; +import 'package:firebase_core_web/firebase_core_web.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('App Check multi-app initialization', () { + setUp(() async { + FirebasePlatform.instance = FirebaseCoreWeb(); + }); + + test( + 'keeps app-check registered and re-runs ensurePluginInitialized for named apps', + () async { + final initializedAppNames = []; + + FirebaseCoreWeb.registerService( + 'app-check', + productNameOverride: 'app_check', + ensurePluginInitialized: (firebaseApp) async { + initializedAppNames.add(firebaseApp.name); + }, + ); + + expect(FirebaseCoreWeb.isServiceRegistered('app-check'), isTrue); + + const options = FirebaseOptions( + apiKey: 'fake-api-key', + appId: '1:1234567890:web:fake', + messagingSenderId: '1234567890', + projectId: 'fake-project', + authDomain: 'fake-project.firebaseapp.com', + ); + + final coreWeb = FirebaseCoreWeb(); + final version = coreWeb.firebaseSDKVersion; + await coreWeb.injectSrcScript( + 'https://www.gstatic.com/firebasejs/$version/firebase-app.js', + 'firebase_core', + ); + + await FirebasePlatform.instance.initializeApp(options: options); + + // Must still be registered so a secondary app can reactivate App Check. + expect(FirebaseCoreWeb.isServiceRegistered('app-check'), isTrue); + expect(initializedAppNames, contains('[DEFAULT]')); + + await FirebasePlatform.instance.initializeApp( + name: 'prod', + options: options, + ); + + expect(FirebaseCoreWeb.isServiceRegistered('app-check'), isTrue); + expect( + initializedAppNames, + containsAll(['[DEFAULT]', 'prod']), + ); + }, + ); + }); +}